From a4062bfc631b917d2519c5e00b7712f8e703839d Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 11:34:12 +0200 Subject: [PATCH 01/26] Control plane FABRID support - FABRID policies are defined with description, identifier, and a set of supported connection points - CSes load policies and validate them - CS appends maps for policy indices and supported connections to beacons - Remote CSes cache policy information from beacons - passes linter --- control/BUILD.bazel | 1 + control/beaconing/BUILD.bazel | 2 + control/beaconing/extender.go | 20 + control/cmd/control/BUILD.bazel | 3 + control/cmd/control/main.go | 29 + control/config/BUILD.bazel | 5 + control/config/config.go | 30 + control/config/fabrid.go | 136 ++ control/config/fabrid_test.go | 136 ++ control/config/sample.go | 36 + control/fabrid/BUILD.bazel | 33 + control/fabrid/fabrid_manager.go | 165 +++ control/fabrid/fabrid_manager_test.go | 368 +++++ control/fabrid/grpc/BUILD.bazel | 43 + control/fabrid/grpc/fabrid_service.go | 115 ++ control/fabrid/grpc/fabrid_service_test.go | 282 ++++ control/fabrid/grpc/fetcher.go | 131 ++ control/fabrid/grpc/fetcher_test.go | 100 ++ control/fabrid/grpc/mock_grpc/BUILD.bazel | 22 + control/fabrid/grpc/mock_grpc/mock.go | 53 + control/fabrid/mpls_map.go | 105 ++ control/fabrid/mpls_map_test.go | 236 +++ .../testdata/correct/1-global_example.yml | 11 + .../testdata/correct/2-global_example.yml | 10 + .../testdata/correct/3-local_example.yml | 17 + .../testdata/correct/55-local_example.yml | 13 + .../testdata/mixed/1-global_example.yml | 11 + control/fabrid/testdata/mixed/invalid.yml | 1 + control/mgmtapi/testdata/TestAPI_beacon_blob | 2 +- .../testdata/TestAPI_beacon_id_prefix_blob | 2 +- control/tasks.go | 3 + doc/dev/design/FABRID.rst | 24 +- pkg/experimental/fabrid/BUILD.bazel | 8 + pkg/experimental/fabrid/defs.go | 33 + pkg/private/xtest/graph/graph.go | 3 +- .../control_plane/experimental/fabrid.pb.go | 1274 +++++++++++++++++ .../experimental/fabrid_extensions.pb.go | 590 ++++++++ .../seg_detached_extensions.pb.go | 114 +- pkg/proto/control_plane/seg_extensions.pb.go | 104 +- pkg/segment/BUILD.bazel | 3 + pkg/segment/extensions/digest/BUILD.bazel | 1 + pkg/segment/extensions/digest/digest.go | 35 +- pkg/segment/extensions/digest/digest_test.go | 23 +- pkg/segment/extensions/fabrid/BUILD.bazel | 22 + pkg/segment/extensions/fabrid/fabrid.go | 349 +++++ pkg/segment/extensions/fabrid/fabrid_test.go | 598 ++++++++ pkg/segment/extensions_test.go | 4 + pkg/segment/unsigned.go | 49 +- pkg/segment/unsigned_test.go | 18 +- .../api/testdata/segments-blob-by-id.txt | 8 +- .../control_plane/experimental/v1/BUILD.bazel | 6 +- .../experimental/v1/fabrid.proto | 121 ++ .../experimental/v1/fabrid_extensions.proto | 78 + .../v1/seg_detached_extensions.proto | 9 + proto/control_plane/v1/seg_extensions.proto | 13 + tools/topogen.py | 2 + tools/topology/go.py | 6 + 57 files changed, 5525 insertions(+), 91 deletions(-) create mode 100644 control/config/fabrid.go create mode 100644 control/config/fabrid_test.go create mode 100644 control/fabrid/BUILD.bazel create mode 100644 control/fabrid/fabrid_manager.go create mode 100644 control/fabrid/fabrid_manager_test.go create mode 100644 control/fabrid/grpc/BUILD.bazel create mode 100644 control/fabrid/grpc/fabrid_service.go create mode 100644 control/fabrid/grpc/fabrid_service_test.go create mode 100644 control/fabrid/grpc/fetcher.go create mode 100644 control/fabrid/grpc/fetcher_test.go create mode 100644 control/fabrid/grpc/mock_grpc/BUILD.bazel create mode 100644 control/fabrid/grpc/mock_grpc/mock.go create mode 100644 control/fabrid/mpls_map.go create mode 100644 control/fabrid/mpls_map_test.go create mode 100644 control/fabrid/testdata/correct/1-global_example.yml create mode 100644 control/fabrid/testdata/correct/2-global_example.yml create mode 100644 control/fabrid/testdata/correct/3-local_example.yml create mode 100644 control/fabrid/testdata/correct/55-local_example.yml create mode 100644 control/fabrid/testdata/mixed/1-global_example.yml create mode 100644 control/fabrid/testdata/mixed/invalid.yml create mode 100644 pkg/experimental/fabrid/BUILD.bazel create mode 100644 pkg/experimental/fabrid/defs.go create mode 100755 pkg/proto/control_plane/experimental/fabrid.pb.go create mode 100755 pkg/proto/control_plane/experimental/fabrid_extensions.pb.go create mode 100644 pkg/segment/extensions/fabrid/BUILD.bazel create mode 100644 pkg/segment/extensions/fabrid/fabrid.go create mode 100644 pkg/segment/extensions/fabrid/fabrid_test.go create mode 100644 proto/control_plane/experimental/v1/fabrid.proto create mode 100644 proto/control_plane/experimental/v1/fabrid_extensions.proto diff --git a/control/BUILD.bazel b/control/BUILD.bazel index 57b4489eb5..eacfa8f689 100644 --- a/control/BUILD.bazel +++ b/control/BUILD.bazel @@ -19,6 +19,7 @@ go_library( "//control/beaconing/grpc:go_default_library", "//control/config:go_default_library", "//control/drkey:go_default_library", + "//control/fabrid:go_default_library", "//control/ifstate:go_default_library", "//control/segreq:go_default_library", "//control/trust:go_default_library", diff --git a/control/beaconing/BUILD.bazel b/control/beaconing/BUILD.bazel index 48714517f5..9aa48ca6ba 100644 --- a/control/beaconing/BUILD.bazel +++ b/control/beaconing/BUILD.bazel @@ -17,6 +17,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//control/beacon:go_default_library", + "//control/fabrid:go_default_library", "//control/ifstate:go_default_library", "//pkg/addr:go_default_library", "//pkg/log:go_default_library", @@ -30,6 +31,7 @@ go_library( "//pkg/segment:go_default_library", "//pkg/segment/extensions/digest:go_default_library", "//pkg/segment/extensions/epic:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/segment/extensions/staticinfo:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/snet:go_default_library", diff --git a/control/beaconing/extender.go b/control/beaconing/extender.go index 4ea5e99704..60e1e22c86 100644 --- a/control/beaconing/extender.go +++ b/control/beaconing/extender.go @@ -20,6 +20,7 @@ import ( "hash" "time" + "github.com/scionproto/scion/control/fabrid" "github.com/scionproto/scion/control/ifstate" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/log" @@ -31,6 +32,7 @@ import ( seg "github.com/scionproto/scion/pkg/segment" "github.com/scionproto/scion/pkg/segment/extensions/digest" "github.com/scionproto/scion/pkg/segment/extensions/epic" + fabridext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/private/trust" ) @@ -86,6 +88,8 @@ type DefaultExtender struct { // is below the maximum expiration time. This happens when the signer expiration time is lower // than the maximum segment expiration time. SegmentExpirationDeficient metrics.Gauge + // Fabrid includes FABRID policy maps into the PCBs. + Fabrid *fabrid.FabridManager } // Extend extends the beacon with hop fields. @@ -196,6 +200,22 @@ func (s *DefaultExtender) Extend( Epic: d, } } + if s.Fabrid != nil { + f := &fabridext.Detached{ + SupportedIndicesMap: s.Fabrid.SupportedIndicesMap, + IndexIdentiferMap: s.Fabrid.IndexIdentifierMap, + } + asEntry.UnsignedExtensions.FabridDetached = f + + d := digest.Digest{Digest: f.Hash()} + if s.EPIC { + asEntry.Extensions.Digests.Fabrid = d + } else { + asEntry.Extensions.Digests = &digest.Extension{ + Fabrid: d, + } + } + } if err := pseg.AddASEntry(ctx, asEntry, signer); err != nil { return err diff --git a/control/cmd/control/BUILD.bazel b/control/cmd/control/BUILD.bazel index 9bf133cb52..e4677c84e1 100644 --- a/control/cmd/control/BUILD.bazel +++ b/control/cmd/control/BUILD.bazel @@ -17,6 +17,8 @@ go_library( "//control/config:go_default_library", "//control/drkey:go_default_library", "//control/drkey/grpc:go_default_library", + "//control/fabrid:go_default_library", + "//control/fabrid/grpc:go_default_library", "//control/ifstate:go_default_library", "//control/mgmtapi:go_default_library", "//control/onehop:go_default_library", @@ -34,6 +36,7 @@ go_library( "//pkg/private/prom:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/proto/control_plane:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", "//pkg/proto/discovery:go_default_library", "//pkg/scrypto:go_default_library", "//pkg/scrypto/cppki:go_default_library", diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 7b36a7e28d..489cac6fa0 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -43,6 +43,8 @@ import ( "github.com/scionproto/scion/control/config" "github.com/scionproto/scion/control/drkey" drkeygrpc "github.com/scionproto/scion/control/drkey/grpc" + "github.com/scionproto/scion/control/fabrid" + fabridgrpc "github.com/scionproto/scion/control/fabrid/grpc" "github.com/scionproto/scion/control/ifstate" api "github.com/scionproto/scion/control/mgmtapi" "github.com/scionproto/scion/control/onehop" @@ -60,6 +62,7 @@ import ( "github.com/scionproto/scion/pkg/private/prom" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" dpb "github.com/scionproto/scion/pkg/proto/discovery" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/scrypto/cppki" @@ -149,6 +152,16 @@ func realMain(ctx context.Context) error { revCache := storage.NewRevocationStorage() defer revCache.Close() + var fabridMgr *fabrid.FabridManager + if globalCfg.Fabrid.Enabled { + fabridMgr = fabrid.NewFabridManager(topo.InterfaceIDs(), + globalCfg.Fabrid.RemoteCacheValidity.Duration) + err = fabridMgr.Load(globalCfg.Fabrid.Path) + if err != nil { + return serrors.WrapStr("initializing FABRID", err) + } + } + pathDB, err := storage.NewPathStorage(globalCfg.PathDB) if err != nil { return serrors.WrapStr("initializing path storage", err) @@ -334,6 +347,21 @@ func realMain(ctx context.Context) error { BeaconsHandled: libmetrics.NewPromCounter(metrics.BeaconingReceivedTotal), }, }) + // Handle fabrid map and policy requests + if globalCfg.Fabrid.Enabled { + polFetcher := fabridgrpc.BasicPolicyFetcher{ + Dialer: &libgrpc.QUICDialer{ + Rewriter: nc.AddressRewriter(), + Dialer: quicStack.Dialer, + }, + Router: segreq.NewRouter(fetcherCfg), + MaxRetries: 20, + } + + f := &fabridgrpc.Server{FabridManager: fabridMgr, Fetcher: &polFetcher} + experimental.RegisterFABRIDIntraServiceServer(tcpServer, f) + experimental.RegisterFABRIDInterServiceServer(quicServer, f) + } // Handle segment lookup authLookupServer := &segreqgrpc.LookupServer{ @@ -801,6 +829,7 @@ func realMain(ctx context.Context) error { HiddenPathRegistrationCfg: hpWriterCfg, AllowIsdLoop: isdLoopAllowed, EPIC: globalCfg.BS.EPIC, + Fabrid: fabridMgr, }) if err != nil { return serrors.WrapStr("starting periodic tasks", err) diff --git a/control/config/BUILD.bazel b/control/config/BUILD.bazel index 06d97aa550..39955efd54 100644 --- a/control/config/BUILD.bazel +++ b/control/config/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "bs_sample.go", "config.go", "drkey.go", + "fabrid.go", "sample.go", ], importpath = "github.com/scionproto/scion/control/config", @@ -15,6 +16,7 @@ go_library( "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//private/config:go_default_library", "//private/env:go_default_library", "//private/mgmtapi:go_default_library", @@ -29,11 +31,13 @@ go_test( srcs = [ "config_test.go", "drkey_test.go", + "fabrid_test.go", ], embed = [":go_default_library"], deps = [ "//pkg/drkey:go_default_library", "//pkg/log/logtest:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//private/env/envtest:go_default_library", "//private/mgmtapi/jwtauth:go_default_library", "//private/mgmtapi/mgmtapitest:go_default_library", @@ -42,5 +46,6 @@ go_test( "@com_github_pelletier_go_toml_v2//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", + "@in_gopkg_yaml_v2//:go_default_library", ], ) diff --git a/control/config/config.go b/control/config/config.go index d0c98e8d9c..c9c4431bf3 100644 --- a/control/config/config.go +++ b/control/config/config.go @@ -44,6 +44,9 @@ const ( DefaultQueryInterval = 5 * time.Minute // DefaultMaxASValidity is the default validity period for renewed AS certificates. DefaultMaxASValidity = 3 * 24 * time.Hour + // DefaultFabridRemoteCacheValidity is the default validity period for a policy description + // fetched from a remote AS. + DefaultFabridRemoteCacheValidity = 3 * time.Hour ) var _ config.Config = (*Config)(nil) @@ -64,6 +67,7 @@ type Config struct { CA CA `toml:"ca,omitempty"` TrustEngine trustengine.Config `toml:"trustengine,omitempty"` DRKey DRKeyConfig `toml:"drkey,omitempty"` + Fabrid FabridConfig `toml:"fabrid,omitempty"` } // InitDefaults initializes the default values for all parts of the config. @@ -83,6 +87,7 @@ func (cfg *Config) InitDefaults() { &cfg.CA, &cfg.TrustEngine, &cfg.DRKey, + &cfg.Fabrid, ) } @@ -140,6 +145,7 @@ func (cfg *Config) Sample(dst io.Writer, path config.Path, _ config.CtxMap) { &cfg.CA, &cfg.TrustEngine, &cfg.DRKey, + &cfg.Fabrid, ) } @@ -342,3 +348,27 @@ func (cfg *CAService) Sample(dst io.Writer, _ config.Path, _ config.CtxMap) { func (cfg *CAService) ConfigName() string { return "service" } + +// FabridConfig contains the configuration for Fabrid on this AS and points to the policies. +type FabridConfig struct { + // Enabled specifies whether the AS should support Fabrid. + Enabled bool `toml:"enabled,omitempty"` + // Path to the folder containing the Fabrid yaml policies + Path string `toml:"path,omitempty"` + // RemoteCacheValidity specifies how long a remote policy should be cached locally, i.e. + // the duration that the identifier->description mapping is stored. + RemoteCacheValidity util.DurWrap `toml:"remote_cache_validity,omitempty"` +} + +func (cfg *FabridConfig) InitDefaults() { + if cfg.RemoteCacheValidity.Duration == 0 { + cfg.RemoteCacheValidity.Duration = DefaultFabridRemoteCacheValidity + } +} +func (cfg *FabridConfig) Sample(dst io.Writer, _ config.Path, _ config.CtxMap) { + config.WriteString(dst, fabridConfigSample) +} + +func (cfg *FabridConfig) ConfigName() string { + return "fabrid" +} diff --git a/control/config/fabrid.go b/control/config/fabrid.go new file mode 100644 index 0000000000..5baa0e408d --- /dev/null +++ b/control/config/fabrid.go @@ -0,0 +1,136 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import ( + "io" + "net" + "strings" + + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" + "github.com/scionproto/scion/private/config" +) + +type FABRIDPolicy struct { + IsLocalPolicy bool `yaml:"local,omitempty"` + LocalIdentifier uint32 `yaml:"local_identifier,omitempty"` + LocalDescription string `yaml:"local_description,omitempty"` + GlobalIdentifier uint32 `yaml:"global_identifier,omitempty"` + SupportedBy []FABRIDConnectionPoints `yaml:"connections,omitempty"` +} + +// Validate validates that all values are parsable. +func (cfg *FABRIDPolicy) Validate(asInterfaceIDs []uint16) error { + for _, connectionPoint := range cfg.SupportedBy { + connectionPoint.asInterfaceIDs = asInterfaceIDs + if err := config.ValidateAll(&connectionPoint); err != nil { + return serrors.WrapStr("Validating supported interfaces failed", err) + } + connectionPoint.asInterfaceIDs = nil + } + if cfg.IsLocalPolicy && (cfg.LocalIdentifier == 0 || cfg.LocalDescription == "") { + return serrors.New("Local policy configuration must not be empty.") + } else if !cfg.IsLocalPolicy && cfg.GlobalIdentifier == 0 { + return serrors.New("Global policy identifier must be valid.") + } + + return nil +} + +// Sample writes a config sample to the writer. +func (cfg *FABRIDPolicy) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) { + config.WriteString(dst, fabridLocalPolicySample) +} + +type FABRIDConnectionPoints struct { + Ingress FABRIDConnectionPoint `yaml:"ingress,omitempty"` + Egress FABRIDConnectionPoint `yaml:"egress,omitempty"` + MPLSLabel uint32 `yaml:"mpls_label,omitempty"` + // asInterfaceIDs is manually set to verify that both the provided + // ingress and egress actually belong to valid AS interfaces if their + // type is interface + asInterfaceIDs []uint16 +} + +// Validate validates that all values are parsable. +func (cfg *FABRIDConnectionPoints) Validate() error { + doInterfacesExist := func(connectionPoints ...*FABRIDConnectionPoint) bool { + for _, cp := range connectionPoints { + if cp.Type == fabrid.Interface { + found := cp.Interface == 0 + for i := 0; i < len(cfg.asInterfaceIDs); i++ { + if cp.Interface == cfg.asInterfaceIDs[i] { + found = true + break + } + } + if !found { + return false + } + } + } + return true + } + if cfg.Ingress.Type != fabrid.Interface && cfg.Ingress.Type != fabrid.Wildcard { + return serrors.New("FABRID policies are only supported from an interface to an IP" + + " range or other interface.") + } else if cfg.Ingress.Type == fabrid.Interface && cfg.Ingress.Interface == 0 { + return serrors.New("Invalid interface for connection point") + } else if cfg.Ingress.Type == fabrid.Interface && cfg.Egress.Type == fabrid.Interface && cfg. + Ingress.Interface == cfg.Egress.Interface { + return serrors.New("Interfaces should be distinct") + } + if !doInterfacesExist(&cfg.Ingress, &cfg.Egress) { + return serrors.New("Interfaces do not exist") + } + + return config.ValidateAll(&cfg.Ingress, &cfg.Egress) +} + +// A connection point describes a specific interface, or an IP range. A FABRID policy can be valid +// for a pair of connection points. +type FABRIDConnectionPoint struct { + Type fabrid.ConnectionPointType `yaml:"type,omitempty"` + IPAddress string `yaml:"ip,omitempty"` + Prefix uint8 `yaml:"prefix,omitempty"` + Interface uint16 `yaml:"interface,omitempty"` +} + +// Validate validates that all values are parsable. +func (cfg *FABRIDConnectionPoint) Validate() error { + switch strings.ToLower(string(cfg.Type)) { + case string(fabrid.Wildcard): + cfg.Type = fabrid.Wildcard + case string(fabrid.IPv4Range): + cfg.Type = fabrid.IPv4Range + case string(fabrid.IPv6Range): + cfg.Type = fabrid.IPv6Range + case string(fabrid.Interface): + cfg.Type = fabrid.Interface + default: + return serrors.New("unknown FABRID connection point", "type", cfg.Type) + } + + if cfg.Type == fabrid.IPv6Range && (net.ParseIP(cfg.IPAddress) == nil || cfg.Prefix > 128) { + return serrors.New("Invalid IPv6 Address range for connection point", + "ip", cfg.IPAddress, "prefix", cfg.Prefix) + } else if cfg.Type == fabrid.IPv4Range && + (net.ParseIP(cfg.IPAddress) == nil || cfg.Prefix > 32) { + return serrors.New("Invalid IPv4 Address range for connection point", + "ip", cfg.IPAddress, "prefix", cfg.Prefix) + } + return nil +} diff --git a/control/config/fabrid_test.go b/control/config/fabrid_test.go new file mode 100644 index 0000000000..e4e2a28d83 --- /dev/null +++ b/control/config/fabrid_test.go @@ -0,0 +1,136 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config_test + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" + + "github.com/scionproto/scion/control/config" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +func TestFabridSample(t *testing.T) { + var sample bytes.Buffer + pol := &config.FABRIDPolicy{} + pol.Sample(&sample, nil, nil) + err := yaml.UnmarshalStrict(sample.Bytes(), pol) + fmt.Println(sample.String()) + assert.NoError(t, err) + err = pol.Validate([]uint16{1}) + assert.NoError(t, err) +} + +func TestIPRangePolicyWithInvalidIP(t *testing.T) { + cp := config.FABRIDConnectionPoint{ + Type: fabrid.IPv4Range, + IPAddress: "192.168.5", + Prefix: 24, + } + err := cp.Validate() + assert.ErrorContains(t, err, "Invalid IPv4 Address range for connection point") +} + +func TestFabridPolicyValidation(t *testing.T) { + tests := map[string]struct { + Policy string + assert assert.ErrorAssertionFunc + }{ + "valid": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv4 + ip: 192.168.2.1 + prefix: 24 +local: true +local_identifier: 55 +local_description: Fabrid Example Policy`, + assert: assert.NoError, + }, + "invalid interface": { + Policy: `connections: + - ingress: + type: interface + interface: 0 + egress: + type: ipv4 + ip: 192.168.2.1 + prefix: 24 +local: true +local_identifier: 55 +local_description: Fabrid Example Policy`, + assert: assert.Error, + }, + "invalid prefix ipv4": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv4 + ip: 192.168.2.1 + prefix: 33 +local: true +local_identifier: 55 +local_description: Fabrid Example Policy`, + assert: assert.Error, + }, + "valid prefix ipv6": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv6 + ip: 2001::1a2b + prefix: 33 +local: true +local_identifier: 55 +local_description: Fabrid Example Policy`, + assert: assert.NoError, + }, + "invalid prefix ipv6": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv6 + ip: 2001::1a2b + prefix: 129 +local: true +local_identifier: 55 +local_description: Fabrid Example Policy`, + assert: assert.Error, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + pol := &config.FABRIDPolicy{} + err := yaml.UnmarshalStrict([]byte(tc.Policy), pol) + require.NoError(t, err) + err = pol.Validate([]uint16{1}) + tc.assert(t, err) + }) + } +} diff --git a/control/config/sample.go b/control/config/sample.go index 54f9181f64..81f7210bb8 100644 --- a/control/config/sample.go +++ b/control/config/sample.go @@ -72,3 +72,39 @@ const drkeySecretValueHostListSample = ` # The list of hosts authorized to get a SV per protocol. scmp = [ "127.0.0.1", "127.0.0.2"] ` + +const fabridLocalPolicySample = ` +# Bool indicating whether the policy is a global or local policy. +local: true +# The identifier that the policy has locally in the AS +local_identifier: 55 +# A description which other ASes can fetch, describing the policy +local_description: Fabrid Example Policy +# A list of connections to which this policy applies +connections: + # Every connection has an ingress and an egress point: + - ingress: + # The type of the connection point, can be "ipv4", "ipv6" or "interface" + type: interface + # If the type is set to "interface", specify the specific interface + interface: 1 + egress: + # The type of the connection point, can be "ipv4", "ipv6" or "interface" + type: ipv6 + # If the type is set to "ipv4" or "ipv6", specify the IP range using a IP and prefix + ip: 2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b + # The prefix of the IP mask, has to be smaller than 32 for IPv4, smaller than 128 for + # IPv6 + prefix: 100 + # If the type is set to "interface", specify the specific interface, e.g. + # interface: 1 + # Every connnection can have a different mpls label they use to enable the policy: + mpls_label: 1 +` + +const fabridConfigSample = ` +# Whether Fabrid is enabled on this AS +enabled = true +# Folder in which the fabrid policies are stored +path = "gen/ASff00_0_110/fabrid/" +` diff --git a/control/fabrid/BUILD.bazel b/control/fabrid/BUILD.bazel new file mode 100644 index 0000000000..9a6597c720 --- /dev/null +++ b/control/fabrid/BUILD.bazel @@ -0,0 +1,33 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "fabrid_manager.go", + "mpls_map.go", + ], + importpath = "github.com/scionproto/scion/control/fabrid", + visibility = ["//visibility:public"], + deps = [ + "//control/config:go_default_library", + "//pkg/log:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", + "@in_gopkg_yaml_v2//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "fabrid_manager_test.go", + "mpls_map_test.go", + ], + data = glob(["testdata/**"]), + embed = [":go_default_library"], + deps = [ + "//control/config:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], +) diff --git a/control/fabrid/fabrid_manager.go b/control/fabrid/fabrid_manager.go new file mode 100644 index 0000000000..3ad5b47235 --- /dev/null +++ b/control/fabrid/fabrid_manager.go @@ -0,0 +1,165 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "os" + "path/filepath" + "time" + + "gopkg.in/yaml.v2" + + "github.com/scionproto/scion/control/config" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +const MaxFabridPolicies = 255 + +type RemotePolicyIdentifier struct { + ISDAS uint64 + Identifier uint32 +} + +type RemotePolicyDescription struct { + Description string + Expires time.Time +} + +type FabridManager struct { + autoIncrIndex int + asInterfaceIDs []uint16 + SupportedIndicesMap fabrid_ext.SupportedIndicesMap + IndexIdentifierMap fabrid_ext.IndexIdentifierMap + IdentifierDescriptionMap map[uint32]string + MPLSMap *MplsMaps + RemotePolicyCache map[RemotePolicyIdentifier]RemotePolicyDescription + RemoteCacheValidity time.Duration +} + +func NewFabridManager(asInterfaceIDs []uint16, remoteCacheValidity time.Duration) *FabridManager { + fb := &FabridManager{ + SupportedIndicesMap: map[fabrid_ext.ConnectionPair][]uint8{}, + IndexIdentifierMap: map[uint8]*fabrid_ext.PolicyIdentifier{}, + IdentifierDescriptionMap: map[uint32]string{}, + MPLSMap: NewMplsMaps(), + RemotePolicyCache: map[RemotePolicyIdentifier]RemotePolicyDescription{}, + RemoteCacheValidity: remoteCacheValidity, + autoIncrIndex: 1, + asInterfaceIDs: asInterfaceIDs, + } + return fb +} + +func (f *FabridManager) Reload(policiesPath string) error { + f.IndexIdentifierMap = make(map[uint8]*fabrid_ext.PolicyIdentifier) + f.SupportedIndicesMap = make(map[fabrid_ext.ConnectionPair][]uint8) + f.MPLSMap = NewMplsMaps() + f.autoIncrIndex = 1 + return f.Load(policiesPath) +} + +func (f *FabridManager) Load(policiesPath string) error { + if err := filepath.Walk(policiesPath, f.parseAndAdd); err != nil { + return serrors.WrapStr("Unable to read the fabrid policies in folder", err, + "path", policiesPath) + } + f.MPLSMap.UpdateHash() + return nil +} + +func (f *FabridManager) parseAndAdd(path string, fi os.FileInfo, err error) error { + if err != nil { + return nil + } + if fi.IsDir() { // Makes sure that the current file is not a directory + return nil + } + + if f.autoIncrIndex > MaxFabridPolicies { + return serrors.New("Amount of FABRID policies exceeds limit.") + } + b, err := os.ReadFile(path) + if err != nil { + return serrors.WrapStr("Unable to read the fabrid policy in file", err, "path", path) + } + pol := &config.FABRIDPolicy{} + if err := yaml.UnmarshalStrict(b, pol); err != nil { + return serrors.WrapStr("Unable to parse policy", err) + } + + if err := pol.Validate(f.asInterfaceIDs); err != nil { + return serrors.WrapStr("Unable to validate policy", err, "path", path) + } + + return f.addPolicy(pol) +} + +func (f *FabridManager) addPolicy(pol *config.FABRIDPolicy) error { + policyIdx := uint8(f.autoIncrIndex) + f.autoIncrIndex++ + + if pol.IsLocalPolicy { + f.IndexIdentifierMap[policyIdx] = &fabrid_ext.PolicyIdentifier{ + IsLocal: true, + Identifier: pol.LocalIdentifier, + } + f.IdentifierDescriptionMap[pol.LocalIdentifier] = pol.LocalDescription + } else { + f.IndexIdentifierMap[policyIdx] = &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: pol.GlobalIdentifier, + } + } + + for _, connection := range pol.SupportedBy { + ig, err := createConnectionPoint(connection.Ingress) + if err != nil { + return err + } + eg, err := createConnectionPoint(connection.Egress) + if err != nil { + return err + } + ie := fabrid_ext.ConnectionPair{ + Ingress: ig, + Egress: eg, + } + f.MPLSMap.AddConnectionPoint(ie, connection.MPLSLabel, policyIdx) + f.SupportedIndicesMap[ie] = append(f.SupportedIndicesMap[ie], policyIdx) + } + + log.Debug("Loaded FABRID policy", "pol", pol) + return nil +} + +func createConnectionPoint(connection config.FABRIDConnectionPoint) (fabrid_ext.ConnectionPoint, + error) { + if connection.Type == fabrid_ext.Interface { + return fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Interface, + InterfaceId: connection.Interface, + }, nil + } else if connection.Type == fabrid_ext.IPv4Range || connection.Type == fabrid_ext.IPv6Range { + return fabrid_ext.IPConnectionPointFromString(connection.IPAddress, + uint32(connection.Prefix), connection.Type), nil + } else if connection.Type == fabrid_ext.Wildcard { + return fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Wildcard, + }, nil + } + return fabrid_ext.ConnectionPoint{}, serrors.New("Unsupported connection type") +} diff --git a/control/fabrid/fabrid_manager_test.go b/control/fabrid/fabrid_manager_test.go new file mode 100644 index 0000000000..53f9d9f074 --- /dev/null +++ b/control/fabrid/fabrid_manager_test.go @@ -0,0 +1,368 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/control/config" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +func TestLoadInvalidPolicies(t *testing.T) { + fm := NewFabridManager([]uint16{1, 2}, 5*time.Second) + err := fm.Load("testdata/mixed") + require.ErrorContains(t, err, "Unable to parse policy") +} + +func TestLoadPolicyWithNonExistingInterfaces(t *testing.T) { + fm := NewFabridManager([]uint16{1}, 5*time.Second) + err := fm.Load("testdata/correct") + require.ErrorContains(t, err, "Interfaces do not exist") +} + +func TestLoadPolicies(t *testing.T) { + testcases := map[string]struct { + CP []config.FABRIDConnectionPoints + Local bool + Description string + Identifier uint32 + }{ + "1-global_example.yml": { + Local: false, + Identifier: 1102, + CP: []config.FABRIDConnectionPoints{{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 2, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 1, + }, + MPLSLabel: 1, + }}, + }, + "2-global_example.yml": { + Local: false, + Identifier: 1102, + CP: []config.FABRIDConnectionPoints{{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 2, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 1, + }, + MPLSLabel: 2, + }}, + }, + "3-local_example.yml": { + Local: true, + Description: "Fabrid Example Policy", + Identifier: 1103, + CP: []config.FABRIDConnectionPoints{{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 2, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 1, + }, + MPLSLabel: 5, + }, { + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 2, + }, + MPLSLabel: 3, + }}, + }, + "55-local_example.yml": { + Local: true, + Description: "Fabrid Example Policy 2", + Identifier: 11055, + CP: []config.FABRIDConnectionPoints{{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 2, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.IPv4Range, + IPAddress: "192.168.5.1", + Prefix: 24, + }, + MPLSLabel: 55, + }}, + }, + } + + fm := NewFabridManager([]uint16{1, 2}, 5*time.Second) + fm.autoIncrIndex = 1 + err := fm.Load("testdata/correct") + require.NoError(t, err) + require.Equal(t, 4, len(fm.IndexIdentifierMap)) + + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + + if tc.Local { + require.Equal(t, tc.Description, fm.IdentifierDescriptionMap[tc.Identifier]) + } + policyIdx := uint8(0) + for k, v := range fm.IndexIdentifierMap { + if ((tc.Local && v.IsLocal) || (!tc.Local && !v. + IsLocal)) && v.Identifier == tc.Identifier { + policyIdx = k + } + } + require.NotEqual(t, 0, policyIdx) + for _, cp := range tc.CP { + ig, err := createConnectionPoint(cp.Ingress) + require.NoError(t, err) + eg, err := createConnectionPoint(cp.Egress) + require.NoError(t, err) + ie := fabrid.ConnectionPair{ + Ingress: ig, + Egress: eg, + } + fmt.Println(ie) + fmt.Println(fm.SupportedIndicesMap) + require.Contains(t, fm.SupportedIndicesMap[ie], policyIdx) + } + }) + } + +} + +func TestAddPolicy(t *testing.T) { + cp1 := config.FABRIDConnectionPoints{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.IPv4Range, + IPAddress: "192.168.1.1", + Prefix: 24, + }, + MPLSLabel: 12, + } + cp2 := config.FABRIDConnectionPoints{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 3, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 5, + }, + MPLSLabel: 13, + } + cp3 := config.FABRIDConnectionPoints{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 7, + }, + MPLSLabel: 14, + } + + cp4 := config.FABRIDConnectionPoints{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + MPLSLabel: 15, + } + cp5 := config.FABRIDConnectionPoints{ + Ingress: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 5, + }, + Egress: config.FABRIDConnectionPoint{ + Type: fabrid.IPv4Range, + IPAddress: "192.168.1.1", + Prefix: 24, + }, + MPLSLabel: 16, + } + testCases := map[string]struct { + Policy config.FABRIDPolicy + Local bool + }{ + "Global Policy": { + Policy: config.FABRIDPolicy{ + IsLocalPolicy: false, + GlobalIdentifier: 1, + SupportedBy: []config.FABRIDConnectionPoints{ + cp1, cp2, cp3, cp4, cp5, + }, + }, + Local: false, + }, + "Local Policy": { + Policy: config.FABRIDPolicy{ + IsLocalPolicy: true, + LocalIdentifier: 4, + LocalDescription: "test policy", + SupportedBy: []config.FABRIDConnectionPoints{ + cp1, cp2, cp3, cp4, cp5, + }, + }, + Local: true, + }, + } + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + fm := NewFabridManager([]uint16{3, 5, 7}, 5*time.Second) + oldIndex := fm.autoIncrIndex + err := fm.addPolicy(&tc.Policy) + newIndex := fm.autoIncrIndex + require.NoError(t, err) + //Check if the policy index has updated: + require.NotEqual(t, oldIndex, newIndex) + if tc.Local { + //Check if the policy is in the IdentifierDescriptionMap + require.Equal(t, fm.IdentifierDescriptionMap[tc.Policy.LocalIdentifier], + tc.Policy.LocalDescription) + } + // Check if the policy has been correctly inserted into the IndexIdentifierMap + indexIdentifierMapEntry := fm.IndexIdentifierMap[uint8(oldIndex)] + if tc.Local { + require.Equal(t, tc.Policy.LocalIdentifier, indexIdentifierMapEntry.Identifier) + require.True(t, indexIdentifierMapEntry.IsLocal) + } else { + + require.Equal(t, tc.Policy.GlobalIdentifier, indexIdentifierMapEntry.Identifier) + require.False(t, indexIdentifierMapEntry.IsLocal) + } + //Check if the policy has been inserted correctly into the MPLS Maps: + cp1_mpls_key := 1<<31 + uint32(oldIndex) // IP + cp2_mpls_key := uint64(cp2.Ingress.Interface)<<24 + uint64(cp2.Egress. + Interface)<<8 + uint64(oldIndex) + cp3_mpls_key := uint64(1)<<63 + uint64(cp3.Egress.Interface)<<8 + uint64(oldIndex) + cp4_mpls_key := uint64(1)<<63 + uint64(oldIndex) + cp5_mpls_key := uint32(cp5.Ingress.Interface)<<8 + uint32(oldIndex) // IP + + require.Equal(t, fm.MPLSMap.IPPoliciesMap[cp1_mpls_key][0].MPLSLabel, cp1.MPLSLabel) + require.Equal(t, fm.MPLSMap.InterfacePoliciesMap[cp2_mpls_key], cp2.MPLSLabel) + require.Equal(t, fm.MPLSMap.InterfacePoliciesMap[cp3_mpls_key], cp3.MPLSLabel) + require.Equal(t, fm.MPLSMap.InterfacePoliciesMap[cp4_mpls_key], cp4.MPLSLabel) + require.Equal(t, fm.MPLSMap.IPPoliciesMap[cp5_mpls_key][0].MPLSLabel, cp5.MPLSLabel) + + //Check if the policy has been added to the SupportedIndicesMap + for _, cp := range tc.Policy.SupportedBy { + ig, err := createConnectionPoint(cp.Ingress) + require.NoError(t, err) + eg, err := createConnectionPoint(cp.Egress) + require.NoError(t, err) + require.Contains(t, fm.SupportedIndicesMap, fabrid.ConnectionPair{ + Ingress: ig, Egress: eg, + }) + require.Equal(t, uint8(oldIndex), fm.SupportedIndicesMap[fabrid.ConnectionPair{ + Ingress: ig, Egress: eg, + }][0]) + } + }) + } + +} +func TestCreateConnectionPoint(t *testing.T) { + testCases := map[string]struct { + connection config.FABRIDConnectionPoint + expectedType fabrid.ConnectionPointType + expectedIP string + expectedPrefix uint32 + expectedInterface uint16 + isError bool + }{ + "ValidInterfaceType": { + connection: config.FABRIDConnectionPoint{ + Type: fabrid.Interface, + Interface: 15, + }, + expectedType: fabrid.Interface, + expectedInterface: 15, + isError: false, + }, + "ValidIPv4Range": { + connection: config.FABRIDConnectionPoint{ + Type: fabrid.IPv4Range, + IPAddress: "192.168.1.1", + Prefix: 24, + }, + expectedType: fabrid.IPv4Range, + expectedIP: "192.168.1.0", + expectedPrefix: 24, + isError: false, + }, + "ValidIPv6Range": { + connection: config.FABRIDConnectionPoint{ + Type: fabrid.IPv6Range, + IPAddress: "2001:db8::2", + Prefix: 56, + }, + expectedType: fabrid.IPv6Range, + expectedIP: "2001:db8::", + expectedPrefix: 56, + isError: false, + }, + "ValidWildcard": { + connection: config.FABRIDConnectionPoint{ + Type: fabrid.Wildcard, + }, + expectedType: fabrid.Wildcard, + isError: false, + }, + "Invalid": { + connection: config.FABRIDConnectionPoint{ + Type: "Invalid", + }, + isError: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + result, err := createConnectionPoint(tc.connection) + if tc.isError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tc.expectedType, result.Type) + if result.Type == fabrid.IPv4Range || result.Type == fabrid.IPv6Range { + require.Equal(t, tc.expectedIP, result.IP) + require.Equal(t, tc.expectedPrefix, result.Prefix) + } else if result.Type == fabrid.Interface { + require.Equal(t, tc.expectedInterface, result.InterfaceId) + } + + }) + } +} diff --git a/control/fabrid/grpc/BUILD.bazel b/control/fabrid/grpc/BUILD.bazel new file mode 100644 index 0000000000..cf41f516aa --- /dev/null +++ b/control/fabrid/grpc/BUILD.bazel @@ -0,0 +1,43 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "fabrid_service.go", + "fetcher.go", + ], + importpath = "github.com/scionproto/scion/control/fabrid/grpc", + visibility = ["//visibility:public"], + deps = [ + "//control/fabrid:go_default_library", + "//pkg/addr:go_default_library", + "//pkg/grpc:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", + "//pkg/snet:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "fabrid_service_test.go", + "fetcher_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//control/fabrid:go_default_library", + "//control/fabrid/grpc/mock_grpc:go_default_library", + "//pkg/addr:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/private/xtest:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", + "//pkg/snet:go_default_library", + "//pkg/snet/mock_snet:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], +) diff --git a/control/fabrid/grpc/fabrid_service.go b/control/fabrid/grpc/fabrid_service.go new file mode 100644 index 0000000000..695a3ac474 --- /dev/null +++ b/control/fabrid/grpc/fabrid_service.go @@ -0,0 +1,115 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpc + +import ( + "bytes" + "context" + "time" + + "github.com/scionproto/scion/control/fabrid" + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + fabridext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +type Server struct { + FabridManager *fabrid.FabridManager + Fetcher PolicyFetcher +} + +func (s Server) mplsIPMapToPB() map[uint32]*experimental.MPLSIPArray { + mplsIpMap := make(map[uint32]*experimental.MPLSIPArray) + for i, entry := range s.FabridManager.MPLSMap.IPPoliciesMap { + if _, exists := mplsIpMap[i]; !exists { + mplsIpMap[i] = &experimental.MPLSIPArray{Entry: make([]*experimental.MPLSIP, 0, + len(entry))} + } + for _, iprange := range entry { + mplsIpMap[i].Entry = append(mplsIpMap[i].Entry, &experimental.MPLSIP{ + MplsLabel: iprange.MPLSLabel, + Ip: iprange.IP, + Prefix: iprange.Prefix, + }) + } + } + return mplsIpMap +} + +func (s Server) MPLSMap(ctx context.Context, request *experimental.MPLSMapRequest) (*experimental. + MPLSMapResponse, error) { + if bytes.Equal(request.Hash, s.FabridManager.MPLSMap.CurrentHash) { + return &experimental.MPLSMapResponse{Update: false}, nil + } + // Create the map of mpls labelks for + return &experimental.MPLSMapResponse{ + Update: true, + Hash: s.FabridManager.MPLSMap.CurrentHash, + MplsInterfacePoliciesMap: s.FabridManager.MPLSMap.InterfacePoliciesMap, + MplsIpMap: s.mplsIPMapToPB(), + }, nil +} + +func (s Server) RemotePolicyDescription(ctx context.Context, + request *experimental.RemotePolicyDescriptionRequest) ( + *experimental.RemotePolicyDescriptionResponse, error) { + //TODO(jvanbommel): signature / hash? + identifier := fabrid.RemotePolicyIdentifier{ + ISDAS: request.IsdAs, + Identifier: request.PolicyIdentifier, + } + if val, ok := s.FabridManager.RemotePolicyCache[identifier]; ok && val.Expires.After( + time.Now()) { + return &experimental.RemotePolicyDescriptionResponse{Description: val.Description}, nil + } + + policy, err := s.Fetcher.GetRemotePolicy(ctx, addr.IA(request.IsdAs), request.PolicyIdentifier) + if err != nil { + return &experimental.RemotePolicyDescriptionResponse{}, err + } + + s.FabridManager.RemotePolicyCache[identifier] = fabrid.RemotePolicyDescription{ + Description: policy.Description, + Expires: time.Now().Add(s.FabridManager.RemoteCacheValidity), + } + + return &experimental.RemotePolicyDescriptionResponse{Description: policy.Description}, nil +} + +func (s Server) SupportedIndicesMap(_ context.Context, + _ *experimental.SupportedIndicesMapRequest) (*experimental.SupportedIndicesMapResponse, error) { + return &experimental.SupportedIndicesMapResponse{ + SupportedIndicesMap: fabridext.SupportedIndicesMapToPB(s.FabridManager.SupportedIndicesMap), + }, nil +} + +func (s Server) IndexIdentifierMap(_ context.Context, _ *experimental.IndexIdentifierMapRequest) ( + *experimental.IndexIdentifierMapResponse, error) { + + return &experimental.IndexIdentifierMapResponse{ + IndexIdentifierMap: fabridext.IndexIdentifierMapToPB(s.FabridManager.IndexIdentifierMap), + }, nil +} + +func (s Server) LocalPolicyDescription(_ context.Context, + request *experimental.LocalPolicyDescriptionRequest) ( + *experimental.LocalPolicyDescriptionResponse, error) { + + if descr, ok := s.FabridManager.IdentifierDescriptionMap[request.PolicyIdentifier]; ok { + return &experimental.LocalPolicyDescriptionResponse{ + Description: descr}, nil + } + return &experimental.LocalPolicyDescriptionResponse{}, errNotFound +} diff --git a/control/fabrid/grpc/fabrid_service_test.go b/control/fabrid/grpc/fabrid_service_test.go new file mode 100644 index 0000000000..383ffa7f9d --- /dev/null +++ b/control/fabrid/grpc/fabrid_service_test.go @@ -0,0 +1,282 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpc + +import ( + "context" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/control/fabrid" + "github.com/scionproto/scion/control/fabrid/grpc/mock_grpc" + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +func TestRemotePolicyDescription(t *testing.T) { + ia := xtest.MustParseIA("1-ff00:00:100") + // Separating these out, as otherwise the line length is too much for the linter. + rpi1 := fabrid.RemotePolicyIdentifier{ISDAS: uint64(ia), Identifier: 56} + rpi2 := fabrid.RemotePolicyIdentifier{ISDAS: uint64(ia), Identifier: 57} + notPresentCache := map[fabrid.RemotePolicyIdentifier]fabrid.RemotePolicyDescription{} + presentExpiredCache := map[fabrid.RemotePolicyIdentifier]fabrid.RemotePolicyDescription{ + rpi1: { + Description: "Test Policy Cached", + Expires: time.Now().Add(-5 * time.Hour), + }, + } + presentNotExpiredCache := map[fabrid.RemotePolicyIdentifier]fabrid.RemotePolicyDescription{ + rpi2: { + Description: "Test Policy Cached", + Expires: time.Now().Add(10 * time.Hour), + }} + tests := map[string]struct { + LocalCache map[fabrid.RemotePolicyIdentifier]fabrid.RemotePolicyDescription + PolicyIdentifier uint32 + PolicyAtRemote bool + ExpectedFetcherCalls int + ExpectedAssert assert.ErrorAssertionFunc + ExpectedResult string + }{ + "not present in cache": { + LocalCache: notPresentCache, + PolicyIdentifier: 55, + PolicyAtRemote: true, + ExpectedFetcherCalls: 1, + ExpectedAssert: assert.NoError, + ExpectedResult: "Test Policy", + }, + "present in cache but expired": { + LocalCache: presentExpiredCache, + PolicyIdentifier: 56, + PolicyAtRemote: true, + ExpectedFetcherCalls: 1, + ExpectedAssert: assert.NoError, + ExpectedResult: "Test Policy 2", + }, + "present in cache and not expired": { + LocalCache: presentNotExpiredCache, + PolicyIdentifier: 57, + PolicyAtRemote: true, + ExpectedFetcherCalls: 0, + ExpectedAssert: assert.NoError, + ExpectedResult: "Test Policy Cached", + }, + "not present at remote": { + LocalCache: notPresentCache, + PolicyIdentifier: 58, + PolicyAtRemote: false, + ExpectedFetcherCalls: 1, + ExpectedAssert: assert.Error, + ExpectedResult: "", + }, + } + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + fetcher := mock_grpc.NewMockPolicyFetcher(ctrl) + fetcher.EXPECT().GetRemotePolicy(gomock.Any(), ia, + tc.PolicyIdentifier).Times(tc.ExpectedFetcherCalls).DoAndReturn( + func(ctx context.Context, + remoteIA addr.IA, + remotePolicyIdentifier uint32) (*experimental.RemotePolicyDescriptionResponse, + error) { + if tc.PolicyAtRemote { + return &experimental.RemotePolicyDescriptionResponse{ + Description: tc.ExpectedResult}, nil + } + return &experimental.RemotePolicyDescriptionResponse{}, serrors.New( + "remote policy fetch fetch failed", + "try", 1, + "peer", remoteIA, + "err", errNotFound, + ) + }) + server := Server{ + FabridManager: &fabrid.FabridManager{ + RemotePolicyCache: tc.LocalCache, + }, + Fetcher: fetcher, + } + descr, err := server.RemotePolicyDescription(context.Background(), + &experimental.RemotePolicyDescriptionRequest{ + PolicyIdentifier: tc.PolicyIdentifier, + IsdAs: uint64(ia), + }) + + tc.ExpectedAssert(t, err) + if tc.ExpectedResult != "" { + require.Equal(t, tc.ExpectedResult, descr.Description) + } + }) + } +} + +func TestSupportedIndicesMap(t *testing.T) { + supportedIndices := fabrid_ext.SupportedIndicesMap{ + fabrid_ext.ConnectionPair{ + Ingress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}} + + server := Server{ + FabridManager: &fabrid.FabridManager{ + SupportedIndicesMap: supportedIndices, + }, + } + indices, err := server.SupportedIndicesMap( + context.Background(), + &experimental.SupportedIndicesMapRequest{}, + ) + require.NoError(t, err) + require.Equal(t, supportedIndices, + fabrid_ext.SupportedIndicesMapFromPB(indices.SupportedIndicesMap)) +} + +func TestIndexIdentifierMap(t *testing.T) { + indexIdentifierMap := fabrid_ext.IndexIdentifierMap{ + 2: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &fabrid_ext.PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + } + + server := Server{ + FabridManager: &fabrid.FabridManager{ + IndexIdentifierMap: indexIdentifierMap, + }, + } + identifiers, err := server.IndexIdentifierMap( + context.Background(), + &experimental.IndexIdentifierMapRequest{}, + ) + require.NoError(t, err) + require.Equal(t, indexIdentifierMap, + fabrid_ext.IndexIdentifierMapFromPB(identifiers.IndexIdentifierMap)) +} + +func TestLocalPolicyDescription(t *testing.T) { + tests := map[string]struct { + Identifier uint32 + IdentifierDescriptionMap map[uint32]string + ExpectedDescription string + Assert assert.ErrorAssertionFunc + }{ + "nonexistent local policy": { + Identifier: 56, + IdentifierDescriptionMap: map[uint32]string{ + 56: "Test Policy", + }, + ExpectedDescription: "Test Policy", + Assert: assert.NoError, + }, + "existent local policy": { + Identifier: 56, + IdentifierDescriptionMap: map[uint32]string{}, + ExpectedDescription: "", + Assert: assert.Error, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + server := Server{ + FabridManager: &fabrid.FabridManager{ + IdentifierDescriptionMap: tc.IdentifierDescriptionMap, + }, + } + description, err := server.LocalPolicyDescription(context.Background(), + &experimental.LocalPolicyDescriptionRequest{ + PolicyIdentifier: tc.Identifier, + }) + tc.Assert(t, err) + if err == nil { + require.Equal(t, tc.ExpectedDescription, description.Description) + } + }) + } +} + +func TestMPLSMap(t *testing.T) { + baseMPLSMap := fabrid.MplsMaps{ + InterfacePoliciesMap: map[uint64]uint32{1: 3001, 2: 2030, 3: 200, 255: 1999}, + CurrentHash: nil, + } + baseMPLSMap.UpdateHash() + + tests := map[string]struct { + RequesterHash []byte + ExpectedUpdate bool + }{ + "no hash": { + RequesterHash: nil, + ExpectedUpdate: true, + }, + "outdated hash": { + RequesterHash: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x30, 0x31, 0x32}, + ExpectedUpdate: true, + }, + "up to date hash": { + RequesterHash: baseMPLSMap.CurrentHash, + ExpectedUpdate: false, + }, + } + + server := Server{ + FabridManager: &fabrid.FabridManager{ + MPLSMap: &baseMPLSMap, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + resp, err := server.MPLSMap(context.Background(), + &experimental.MPLSMapRequest{ + Hash: tc.RequesterHash, + }) + require.NoError(t, err) + require.Equal(t, tc.ExpectedUpdate, resp.Update) + if resp.Update { + require.Equal(t, server.FabridManager.MPLSMap.InterfacePoliciesMap, + resp.MplsInterfacePoliciesMap) + } + }) + } +} diff --git a/control/fabrid/grpc/fetcher.go b/control/fabrid/grpc/fetcher.go new file mode 100644 index 0000000000..6b1c4fbb3c --- /dev/null +++ b/control/fabrid/grpc/fetcher.go @@ -0,0 +1,131 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpc + +import ( + "context" + "errors" + "strings" + "time" + + "github.com/scionproto/scion/pkg/addr" + libgrpc "github.com/scionproto/scion/pkg/grpc" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + "github.com/scionproto/scion/pkg/snet" +) + +const ( + defaultRPCDialTimeout time.Duration = 2 * time.Second +) + +var errNotReachable = serrors.New("remote not reachable") +var errNotFound = serrors.New("FABRID local policy is not found") + +type PolicyFetcher interface { + GetRemotePolicy(ctx context.Context, remoteIA addr.IA, + remotePolicyIdentifier uint32) (*experimental.RemotePolicyDescriptionResponse, error) +} + +type BasicPolicyFetcher struct { + Dialer libgrpc.Dialer + Router snet.Router + MaxRetries int + + errorPaths map[snet.PathFingerprint]struct{} +} + +func (f *BasicPolicyFetcher) GetRemotePolicy( + ctx context.Context, + remoteIA addr.IA, + remotePolicyIdentifier uint32, +) (*experimental.RemotePolicyDescriptionResponse, error) { + var errList serrors.List + f.errorPaths = make(map[snet.PathFingerprint]struct{}) + for i := 0; i < f.MaxRetries; i++ { + rep, err := f.attemptFetchRemotePolicy(ctx, remoteIA, remotePolicyIdentifier) + if errors.Is(err, errNotReachable) || (err != nil && strings.Contains(err.Error(), + errNotFound.Error())) { + return &experimental.RemotePolicyDescriptionResponse{}, serrors.New( + "remote policy fetch fetch failed", + "try", i+1, + "peer", remoteIA, + "err", err, + ) + } + if err == nil { + return rep, nil + } + errList = append(errList, + serrors.WrapStr("fetching policy", err, "try", i+1, "peer", remoteIA), + ) + } + return &experimental.RemotePolicyDescriptionResponse{}, serrors.WrapStr( + "reached max retry attempts fetching remote policy", + errList, + ) +} + +func (f *BasicPolicyFetcher) attemptFetchRemotePolicy( + ctx context.Context, + srcIA addr.IA, + remotePolicyIdentifier uint32, +) (*experimental.RemotePolicyDescriptionResponse, error) { + + path, err := f.pathToDst(ctx, srcIA) + if err != nil { + return nil, err + } + remote := &snet.SVCAddr{ + IA: srcIA, + Path: path.Dataplane(), + NextHop: path.UnderlayNextHop(), + SVC: addr.SvcCS, + } + dialCtx, cancelF := context.WithTimeout(ctx, defaultRPCDialTimeout) + defer cancelF() + conn, err := f.Dialer.Dial(dialCtx, remote) + if err != nil { + return nil, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := experimental.NewFABRIDInterServiceClient(conn) + rep, err := client.LocalPolicyDescription(ctx, + &experimental.LocalPolicyDescriptionRequest{PolicyIdentifier: remotePolicyIdentifier}) + if err != nil { + return nil, serrors.WrapStr("requesting policy", err) + } + return &experimental.RemotePolicyDescriptionResponse{Description: rep.Description}, nil +} + +func (f *BasicPolicyFetcher) pathToDst(ctx context.Context, dst addr.IA) (snet.Path, error) { + paths, err := f.Router.AllRoutes(ctx, dst) + if err != nil { + return nil, serrors.Wrap(errNotReachable, err) + } + if len(paths) == 0 { + return nil, errNotReachable + } + for _, p := range paths { + if _, ok := f.errorPaths[snet.Fingerprint(p)]; ok { + continue + } + f.errorPaths[snet.Fingerprint(p)] = struct{}{} + return p, nil + } + // we've tried out all the paths; we reset the map to retry them. + f.errorPaths = make(map[snet.PathFingerprint]struct{}) + return paths[0], nil +} diff --git a/control/fabrid/grpc/fetcher_test.go b/control/fabrid/grpc/fetcher_test.go new file mode 100644 index 0000000000..8f3308b04a --- /dev/null +++ b/control/fabrid/grpc/fetcher_test.go @@ -0,0 +1,100 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpc_test + +import ( + "context" + "net" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/control/fabrid" + "github.com/scionproto/scion/control/fabrid/grpc" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/pkg/snet/mock_snet" +) + +func TestFetchRemotePolicy(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + path := mock_snet.NewMockPath(ctrl) + path.EXPECT().Metadata().AnyTimes().Return(&snet.PathMetadata{ + Interfaces: []snet.PathInterface{}, + }) + path.EXPECT().Dataplane().AnyTimes().Return(nil) + path.EXPECT().UnderlayNextHop().AnyTimes().Return(&net.UDPAddr{}) + + router := mock_snet.NewMockRouter(ctrl) + router.EXPECT().AllRoutes(gomock.Any(), gomock.Any()).AnyTimes().Return([]snet.Path{path}, nil) + tests := map[string]struct { + IdentifierDescriptions map[uint32]string + RequestedPolicy uint32 + Assert assert.ErrorAssertionFunc + PostCheck func(t *testing.T, + response *experimental.RemotePolicyDescriptionResponse) + }{ + "existing": { + IdentifierDescriptions: map[uint32]string{ + 33: "Test Policy", + 45: "Second Test Policy", + }, + RequestedPolicy: 33, + Assert: assert.NoError, + PostCheck: func(t *testing.T, response *experimental.RemotePolicyDescriptionResponse) { + require.Equal(t, response.Description, "Test Policy") + }, + }, + "nonexistent": { + IdentifierDescriptions: map[uint32]string{ + 33: "Test Policy", + 45: "Second Test Policy", + }, + RequestedPolicy: 55, + Assert: assert.Error, + PostCheck: func(t *testing.T, + response *experimental.RemotePolicyDescriptionResponse) { + }, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + server := xtest.NewGRPCService() + experimental.RegisterFABRIDInterServiceServer(server.Server(), grpc.Server{ + FabridManager: &fabrid.FabridManager{ + IdentifierDescriptionMap: tc.IdentifierDescriptions, + }, + Fetcher: &grpc.BasicPolicyFetcher{}, + }) + server.Start(t) + + fetcher := grpc.BasicPolicyFetcher{ + Dialer: server, + Router: router, + MaxRetries: 1, + } + + policy, err := fetcher.GetRemotePolicy(context.Background(), + xtest.MustParseIA("1-ff00:0:111"), tc.RequestedPolicy) + tc.Assert(t, err) + tc.PostCheck(t, policy) + }) + } +} diff --git a/control/fabrid/grpc/mock_grpc/BUILD.bazel b/control/fabrid/grpc/mock_grpc/BUILD.bazel new file mode 100644 index 0000000000..c058a516c7 --- /dev/null +++ b/control/fabrid/grpc/mock_grpc/BUILD.bazel @@ -0,0 +1,22 @@ +load("//tools/lint:go.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "gomock") + +gomock( + name = "go_default_mock", + out = "mock.go", + interfaces = ["PolicyFetcher"], + library = "//control/fabrid/grpc:go_default_library", + package = "mock_grpc", +) + +go_library( + name = "go_default_library", + srcs = ["mock.go"], + importpath = "github.com/scionproto/scion/control/fabrid/grpc/mock_grpc", + visibility = ["//visibility:public"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + ], +) diff --git a/control/fabrid/grpc/mock_grpc/mock.go b/control/fabrid/grpc/mock_grpc/mock.go new file mode 100644 index 0000000000..b6056b9d06 --- /dev/null +++ b/control/fabrid/grpc/mock_grpc/mock.go @@ -0,0 +1,53 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/scionproto/scion/control/fabrid/grpc (interfaces: PolicyFetcher) + +// Package mock_grpc is a generated GoMock package. +package mock_grpc + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + addr "github.com/scionproto/scion/pkg/addr" + experimental "github.com/scionproto/scion/pkg/proto/control_plane/experimental" +) + +// MockPolicyFetcher is a mock of PolicyFetcher interface. +type MockPolicyFetcher struct { + ctrl *gomock.Controller + recorder *MockPolicyFetcherMockRecorder +} + +// MockPolicyFetcherMockRecorder is the mock recorder for MockPolicyFetcher. +type MockPolicyFetcherMockRecorder struct { + mock *MockPolicyFetcher +} + +// NewMockPolicyFetcher creates a new mock instance. +func NewMockPolicyFetcher(ctrl *gomock.Controller) *MockPolicyFetcher { + mock := &MockPolicyFetcher{ctrl: ctrl} + mock.recorder = &MockPolicyFetcherMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPolicyFetcher) EXPECT() *MockPolicyFetcherMockRecorder { + return m.recorder +} + +// GetRemotePolicy mocks base method. +func (m *MockPolicyFetcher) GetRemotePolicy(arg0 context.Context, arg1 addr.IA, + arg2 uint32) (*experimental.RemotePolicyDescriptionResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRemotePolicy", arg0, arg1, arg2) + ret0, _ := ret[0].(*experimental.RemotePolicyDescriptionResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRemotePolicy indicates an expected call of GetRemotePolicy. +func (mr *MockPolicyFetcherMockRecorder) GetRemotePolicy(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemotePolicy", reflect.TypeOf((*MockPolicyFetcher)(nil).GetRemotePolicy), arg0, arg1, arg2) +} diff --git a/control/fabrid/mpls_map.go b/control/fabrid/mpls_map.go new file mode 100644 index 0000000000..607c2abe89 --- /dev/null +++ b/control/fabrid/mpls_map.go @@ -0,0 +1,105 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "encoding/binary" + "hash/fnv" + "sort" + + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +type PolicyIPRange struct { + MPLSLabel uint32 + IP []byte + Prefix uint32 +} + +type MplsMaps struct { + IPPoliciesMap map[uint32][]PolicyIPRange + InterfacePoliciesMap map[uint64]uint32 + CurrentHash []byte +} + +func NewMplsMaps() *MplsMaps { + return &MplsMaps{ + IPPoliciesMap: make(map[uint32][]PolicyIPRange), + InterfacePoliciesMap: make(map[uint64]uint32), + CurrentHash: []byte{}, + } +} + +func (m *MplsMaps) AddConnectionPoint(ie fabrid.ConnectionPair, mplsLabel uint32, policyIdx uint8) { + if mplsLabel == 0 { + return + } + if ie.Egress.Type == fabrid.IPv4Range || ie.Egress. + Type == fabrid.IPv6Range { // Egress is IP network: + key := 1<<31 + uint32(policyIdx) // Wildcard ingress interface + if ie.Ingress.Type == fabrid.Interface { // Specified ingress interface + key = uint32(ie.Ingress.InterfaceId)<<8 + uint32(policyIdx) + } + m.IPPoliciesMap[key] = append(m.IPPoliciesMap[key], PolicyIPRange{ + IP: ie.Egress.IPNetwork().IP, + Prefix: ie.Egress.Prefix, + MPLSLabel: mplsLabel}) + } else { + egIf := uint64(0) + if ie.Egress.Type == fabrid.Interface { + egIf = uint64(ie.Egress.InterfaceId) + } + // Wildcard ingress interface: + key := 1<<63 + egIf<<8 + uint64(policyIdx) + if ie.Ingress.Type == fabrid.Interface { // Specified ingress interface + key = uint64(ie.Ingress.InterfaceId)<<24 + egIf<<8 + uint64(policyIdx) + } + m.InterfacePoliciesMap[key] = mplsLabel + } +} + +func sortedKeys[K uint32 | uint64, V any](m map[K]V) []K { + keys := make([]K, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + + sort.Slice(keys, func(i, j int) bool { + return keys[i] < keys[j] + }) + + return keys +} + +// This method is to be called after all inserts and removes from the internal map +// TODO(jvanbommel): this feels too expensive for what a relatively simple synchronization need. +// Revise? +func (m *MplsMaps) UpdateHash() { + h := fnv.New64() + for _, polIdx := range sortedKeys(m.IPPoliciesMap) { + _ = binary.Write(h, binary.BigEndian, polIdx) + for _, ipRange := range m.IPPoliciesMap[polIdx] { + _ = binary.Write(h, binary.BigEndian, ipRange.MPLSLabel) + _, _ = h.Write(ipRange.IP) + _ = binary.Write(h, binary.BigEndian, ipRange.Prefix) + } + } + + for _, polIdx := range sortedKeys(m.InterfacePoliciesMap) { + _ = binary.Write(h, binary.BigEndian, polIdx) + _ = binary.Write(h, binary.BigEndian, m.InterfacePoliciesMap[polIdx]) + } + m.CurrentHash = h.Sum(nil) +} diff --git a/control/fabrid/mpls_map_test.go b/control/fabrid/mpls_map_test.go new file mode 100644 index 0000000000..3a7c5d48b8 --- /dev/null +++ b/control/fabrid/mpls_map_test.go @@ -0,0 +1,236 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" +) + +func TestEqualHashDifferentInsertionOrders(t *testing.T) { + type insertionInput struct { + CP fabrid.ConnectionPair + mplsLabel uint32 + polIdx uint8 + } + + input := []insertionInput{ + { + CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 10, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 20, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.1.0", + Prefix: 24, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.1.0", + Prefix: 24, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + } + + m := NewMplsMaps() + for _, i := range input { + m.AddConnectionPoint(i.CP, i.mplsLabel, i.polIdx) + } + m.UpdateHash() + baseHash := m.CurrentHash + rand.New(rand.NewSource(42)) + + for round := 0; round < 10; round++ { + m = NewMplsMaps() + rand.Shuffle(len(input), func(i, j int) { input[i], input[j] = input[j], input[i] }) + for _, i := range input { + m.AddConnectionPoint(i.CP, i.mplsLabel, i.polIdx) + } + + m.UpdateHash() + require.Equal(t, baseHash, m.CurrentHash) + } +} + +func TestHashChanges(t *testing.T) { + + type insertionInput struct { + CP fabrid.ConnectionPair + mplsLabel uint32 + polIdx uint8 + } + + input := []insertionInput{ + { + CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 10, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 20, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 3, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.1.0", + Prefix: 24, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.1.0", + Prefix: 24, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + + {CP: fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Wildcard, + }, + }, + mplsLabel: 21902, + polIdx: 20, + }, + } + + rand.New(rand.NewSource(42)) + + for round := 0; round < 10; round++ { + m := NewMplsMaps() + rand.Shuffle(len(input), func(i, j int) { input[i], input[j] = input[j], input[i] }) + prevHashes := make([][]byte, len(input)) + for j, i := range input { + m.AddConnectionPoint(i.CP, i.mplsLabel, i.polIdx) + m.UpdateHash() + require.NotContains(t, prevHashes, m.CurrentHash) + prevHashes[j] = m.CurrentHash + } + } +} diff --git a/control/fabrid/testdata/correct/1-global_example.yml b/control/fabrid/testdata/correct/1-global_example.yml new file mode 100644 index 0000000000..6e8a60e756 --- /dev/null +++ b/control/fabrid/testdata/correct/1-global_example.yml @@ -0,0 +1,11 @@ +connections: + - ingress: + type: interface + interface: 2 + egress: + type: interface + interface: 1 + mpls_label: 1 +local: false +global_identifier: 1101 + diff --git a/control/fabrid/testdata/correct/2-global_example.yml b/control/fabrid/testdata/correct/2-global_example.yml new file mode 100644 index 0000000000..83d25f3d17 --- /dev/null +++ b/control/fabrid/testdata/correct/2-global_example.yml @@ -0,0 +1,10 @@ +connections: + - ingress: + type: interface + interface: 2 + egress: + type: interface + interface: 1 + mpls_label: 2 +local: false +global_identifier: 1102 diff --git a/control/fabrid/testdata/correct/3-local_example.yml b/control/fabrid/testdata/correct/3-local_example.yml new file mode 100644 index 0000000000..9ed9ae0faa --- /dev/null +++ b/control/fabrid/testdata/correct/3-local_example.yml @@ -0,0 +1,17 @@ +connections: + - ingress: + type: interface + interface: 2 + egress: + type: interface + interface: 1 + mpls_label: 5 + - ingress: + type: wildcard + egress: + type: interface + interface: 2 + mpls_label: 3 +local: true +local_identifier: 1103 +local_description: Fabrid Example Policy diff --git a/control/fabrid/testdata/correct/55-local_example.yml b/control/fabrid/testdata/correct/55-local_example.yml new file mode 100644 index 0000000000..5c82dc9a9f --- /dev/null +++ b/control/fabrid/testdata/correct/55-local_example.yml @@ -0,0 +1,13 @@ +connections: + - ingress: + type: interface + interface: 2 + egress: + type: ipv4 + ip: 192.168.5.1 + prefix: 24 + mpls_label: 55 +local: true +local_identifier: 11055 +local_description: Fabrid Example Policy 2 + diff --git a/control/fabrid/testdata/mixed/1-global_example.yml b/control/fabrid/testdata/mixed/1-global_example.yml new file mode 100644 index 0000000000..6e8a60e756 --- /dev/null +++ b/control/fabrid/testdata/mixed/1-global_example.yml @@ -0,0 +1,11 @@ +connections: + - ingress: + type: interface + interface: 2 + egress: + type: interface + interface: 1 + mpls_label: 1 +local: false +global_identifier: 1101 + diff --git a/control/fabrid/testdata/mixed/invalid.yml b/control/fabrid/testdata/mixed/invalid.yml new file mode 100644 index 0000000000..fdcf008db7 --- /dev/null +++ b/control/fabrid/testdata/mixed/invalid.yml @@ -0,0 +1 @@ +invalid policy diff --git a/control/mgmtapi/testdata/TestAPI_beacon_blob b/control/mgmtapi/testdata/TestAPI_beacon_blob index dd0286378c..77fe6406c6 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon_blob +++ b/control/mgmtapi/testdata/TestAPI_beacon_blob @@ -1,3 +1,3 @@ -----BEGIN PATH SEGMENT----- -EgASAA== +EgISABICEgA= -----END PATH SEGMENT----- diff --git a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix_blob b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix_blob index dd0286378c..77fe6406c6 100644 --- a/control/mgmtapi/testdata/TestAPI_beacon_id_prefix_blob +++ b/control/mgmtapi/testdata/TestAPI_beacon_id_prefix_blob @@ -1,3 +1,3 @@ -----BEGIN PATH SEGMENT----- -EgASAA== +EgISABICEgA= -----END PATH SEGMENT----- diff --git a/control/tasks.go b/control/tasks.go index 4de2588cc6..9db370f6b2 100644 --- a/control/tasks.go +++ b/control/tasks.go @@ -23,6 +23,7 @@ import ( "github.com/scionproto/scion/control/beacon" "github.com/scionproto/scion/control/beaconing" "github.com/scionproto/scion/control/drkey" + "github.com/scionproto/scion/control/fabrid" "github.com/scionproto/scion/control/ifstate" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/experimental/hiddenpath" @@ -60,6 +61,7 @@ type TasksConfig struct { Inspector trust.Inspector Metrics *Metrics DRKeyEngine *drkey.ServiceEngine + Fabrid *fabrid.FabridManager MACGen func() hash.Hash StaticInfo func() *beaconing.StaticInfoCfg @@ -217,6 +219,7 @@ func (t *TasksConfig) extender( MTU: mtu, MaxExpTime: func() uint8 { return maxExp() }, StaticInfo: t.StaticInfo, + Fabrid: t.Fabrid, Task: task, EPIC: t.EPIC, SegmentExpirationDeficient: func() metrics.Gauge { diff --git a/doc/dev/design/FABRID.rst b/doc/dev/design/FABRID.rst index 73ea04cc76..9a8e0c361c 100644 --- a/doc/dev/design/FABRID.rst +++ b/doc/dev/design/FABRID.rst @@ -20,7 +20,7 @@ This can also be seen as an enhancement for keeping traffic within a certain jur only along devices located in a specific country, because a single AS could cover multiple countries. .. figure:: fig/FABRID/NetworkTopology.png - + Example network topology. Different colors for intra-AS routers indicate different manufacturers. H01 in AS01 and H02 in AS02 want to communicate with each other. @@ -128,7 +128,7 @@ The Identifier Option always has a length of 8 bytes and looks like: Timestamp The 27 bit timestamp referring to the packet's transmission time with 1 millisecond precision relative to the timestamp of the first :ref:`InfoField ` of the SCION header. - + Packet ID The 32 bit packet ID that, together with the timestamp, uniquely identifies a source endhost's packet. @@ -315,7 +315,7 @@ The following list explains the most important maps used in the FABRID service: Prefix uint32 InterfaceID uint16 } - + - Index identifiers A policy index is to be embedded in the HBH extension and therefore has to be minimal in size. The size of a policy index is 8 bits, whereas identifiers can be a multiple of this (especially global identifiers). @@ -370,9 +370,9 @@ A custom language is used to make a selection out of the available paths and pol Applying a policy refers to selecting that specific policy for that hop when sending a FABRID packet. In case of multiple matches, the first match (from left to right) will be selected. Parts of this hop identifier may be a wildcard, such that the identifier can match with multiple hops in the path. - An identifier is structured as follows: + An identifier is structured as follows: ``ISD-AS#IGIF,EGIF@POLICY``, - where + where * ISD can be either the ISD number (e.g. ``1``), or a wildcard (``0``). * AS can be either the AS number seperated by underscores (e.g. ``ff00_0_110``) or a wildcard (``0``). @@ -380,11 +380,11 @@ A custom language is used to make a selection out of the available paths and pol * EGIF can be either the egress interface number (e.g. ``41``), or a wildcard (``0``). * POLICY can be either the policy to apply, where a local policy is denoted as ``L`` + the policy identifier (e.g. ``L100``) and a global policy is denoted by ``G`` + the policy identifier (e.g. ``G100``), a wildcard (``0``), or a rejection ``REJECT``. - Rejection means that this path should not be chosen. + Rejection means that this path should not be chosen. * **Concatenations** - Multiple identifiers can be combined by using a concatenation. Concatenations are created by the ``+`` symbol. + Multiple identifiers can be combined by using a concatenation. Concatenations are created by the ``+`` symbol. Example: @@ -418,18 +418,18 @@ A custom language is used to make a selection out of the available paths and pol The same applies for the ``EXPRESSION_IF_FALSE`` branch. Example: - + There is a specific policy that signals that the middleboxes in this AS are from a specific manufacturer, e.g. ``G150``. This manufacturer is known to have a security vulnerability that allows malicious users to intercept traffic. The traffic to be sent is highly confidential, so the path should not be used. In this case the query ``{0-0#0,0@G150 ? 0-0#0,0@REJECT : 0-0#0,0@0}`` can be used. - ``G150`` in this case is a blacklisted policy. + ``G150`` in this case is a blacklisted policy. (An alternative is a whitelist, where a user would specify all manufacturers that are allowed, i.e. ``G151``, ``G152``, ``G153``: ``0-0#0,0@G151 + 0-0#0,0@G152 + 0-0#0,0@G153 + 0-0#0,0@REJECT}``) **Evaluation Order** The language is evaluated left to right, for each hop only a single policy can be applied. -The first identifier match applies the policy, so the order of the query is important. +The first identifier match applies the policy, so the order of the query is important. Example: @@ -529,7 +529,7 @@ Example of a list of connection points: egress: type: interface interface: 1 - mpls_label: 1 + mpls_label: 1 - ingress: type: interface interface: 2 @@ -671,4 +671,4 @@ And in a second stage: - Full FABRID with path validation also at source -- FABRID Intra-AS emulation for SCIONLab \ No newline at end of file +- FABRID Intra-AS emulation for SCIONLab diff --git a/pkg/experimental/fabrid/BUILD.bazel b/pkg/experimental/fabrid/BUILD.bazel new file mode 100644 index 0000000000..a279593881 --- /dev/null +++ b/pkg/experimental/fabrid/BUILD.bazel @@ -0,0 +1,8 @@ +load("//tools/lint:go.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["defs.go"], + importpath = "github.com/scionproto/scion/pkg/experimental/fabrid", + visibility = ["//visibility:public"], +) diff --git a/pkg/experimental/fabrid/defs.go b/pkg/experimental/fabrid/defs.go new file mode 100644 index 0000000000..23a6ca3269 --- /dev/null +++ b/pkg/experimental/fabrid/defs.go @@ -0,0 +1,33 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import "fmt" + +type PolicyID uint8 + +type Policy struct { + IsLocal bool + Identifier uint32 + Index PolicyID +} + +func (fpi *Policy) String() string { + if fpi.IsLocal { + return fmt.Sprintf("L%d", fpi.Identifier) + } else { + return fmt.Sprintf("G%d", fpi.Identifier) + } +} diff --git a/pkg/private/xtest/graph/graph.go b/pkg/private/xtest/graph/graph.go index 1672cbf684..bc34543665 100644 --- a/pkg/private/xtest/graph/graph.go +++ b/pkg/private/xtest/graph/graph.go @@ -654,7 +654,8 @@ func generateStaticInfo(g *Graph, ia addr.IA, inIF, outIF uint16) *staticinfo.Ex carbonIntensity.Intra[common.IFIDType(ifid)] = g.CarbonIntensity(ifid, outIF) } if ifid == outIF || g.isPeer[ifid] { - carbonIntensity.Inter[common.IFIDType(ifid)] = g.CarbonIntensity(ifid, g.links[ifid]) + carbonIntensity.Inter[common.IFIDType(ifid)] = + g.CarbonIntensity(ifid, g.links[ifid]) } } } diff --git a/pkg/proto/control_plane/experimental/fabrid.pb.go b/pkg/proto/control_plane/experimental/fabrid.pb.go new file mode 100755 index 0000000000..c9b8037b8a --- /dev/null +++ b/pkg/proto/control_plane/experimental/fabrid.pb.go @@ -0,0 +1,1274 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.10 +// source: proto/control_plane/experimental/v1/fabrid.proto + +package experimental + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type MPLSIPArray struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Entry []*MPLSIP `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"` +} + +func (x *MPLSIPArray) Reset() { + *x = MPLSIPArray{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MPLSIPArray) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MPLSIPArray) ProtoMessage() {} + +func (x *MPLSIPArray) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MPLSIPArray.ProtoReflect.Descriptor instead. +func (*MPLSIPArray) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{0} +} + +func (x *MPLSIPArray) GetEntry() []*MPLSIP { + if x != nil { + return x.Entry + } + return nil +} + +type MPLSIP struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MplsLabel uint32 `protobuf:"varint,1,opt,name=mpls_label,json=mplsLabel,proto3" json:"mpls_label,omitempty"` + Ip []byte `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"` + Prefix uint32 `protobuf:"varint,3,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *MPLSIP) Reset() { + *x = MPLSIP{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MPLSIP) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MPLSIP) ProtoMessage() {} + +func (x *MPLSIP) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MPLSIP.ProtoReflect.Descriptor instead. +func (*MPLSIP) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{1} +} + +func (x *MPLSIP) GetMplsLabel() uint32 { + if x != nil { + return x.MplsLabel + } + return 0 +} + +func (x *MPLSIP) GetIp() []byte { + if x != nil { + return x.Ip + } + return nil +} + +func (x *MPLSIP) GetPrefix() uint32 { + if x != nil { + return x.Prefix + } + return 0 +} + +type MPLSMapRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` +} + +func (x *MPLSMapRequest) Reset() { + *x = MPLSMapRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MPLSMapRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MPLSMapRequest) ProtoMessage() {} + +func (x *MPLSMapRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MPLSMapRequest.ProtoReflect.Descriptor instead. +func (*MPLSMapRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{2} +} + +func (x *MPLSMapRequest) GetHash() []byte { + if x != nil { + return x.Hash + } + return nil +} + +type MPLSMapResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Update bool `protobuf:"varint,1,opt,name=update,proto3" json:"update,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + MplsInterfacePoliciesMap map[uint64]uint32 `protobuf:"bytes,3,rep,name=mpls_interface_policies_map,json=mplsInterfacePoliciesMap,proto3" json:"mpls_interface_policies_map,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + MplsIpMap map[uint32]*MPLSIPArray `protobuf:"bytes,4,rep,name=mpls_ip_map,json=mplsIpMap,proto3" json:"mpls_ip_map,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *MPLSMapResponse) Reset() { + *x = MPLSMapResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MPLSMapResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MPLSMapResponse) ProtoMessage() {} + +func (x *MPLSMapResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MPLSMapResponse.ProtoReflect.Descriptor instead. +func (*MPLSMapResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{3} +} + +func (x *MPLSMapResponse) GetUpdate() bool { + if x != nil { + return x.Update + } + return false +} + +func (x *MPLSMapResponse) GetHash() []byte { + if x != nil { + return x.Hash + } + return nil +} + +func (x *MPLSMapResponse) GetMplsInterfacePoliciesMap() map[uint64]uint32 { + if x != nil { + return x.MplsInterfacePoliciesMap + } + return nil +} + +func (x *MPLSMapResponse) GetMplsIpMap() map[uint32]*MPLSIPArray { + if x != nil { + return x.MplsIpMap + } + return nil +} + +type SupportedIndicesMapRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SupportedIndicesMapRequest) Reset() { + *x = SupportedIndicesMapRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SupportedIndicesMapRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SupportedIndicesMapRequest) ProtoMessage() {} + +func (x *SupportedIndicesMapRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SupportedIndicesMapRequest.ProtoReflect.Descriptor instead. +func (*SupportedIndicesMapRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{4} +} + +type SupportedIndicesMapResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SupportedIndicesMap []*FABRIDIndexMapEntry `protobuf:"bytes,1,rep,name=supported_indices_map,json=supportedIndicesMap,proto3" json:"supported_indices_map,omitempty"` +} + +func (x *SupportedIndicesMapResponse) Reset() { + *x = SupportedIndicesMapResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SupportedIndicesMapResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SupportedIndicesMapResponse) ProtoMessage() {} + +func (x *SupportedIndicesMapResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SupportedIndicesMapResponse.ProtoReflect.Descriptor instead. +func (*SupportedIndicesMapResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{5} +} + +func (x *SupportedIndicesMapResponse) GetSupportedIndicesMap() []*FABRIDIndexMapEntry { + if x != nil { + return x.SupportedIndicesMap + } + return nil +} + +type IndexIdentifierMapRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *IndexIdentifierMapRequest) Reset() { + *x = IndexIdentifierMapRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IndexIdentifierMapRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IndexIdentifierMapRequest) ProtoMessage() {} + +func (x *IndexIdentifierMapRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IndexIdentifierMapRequest.ProtoReflect.Descriptor instead. +func (*IndexIdentifierMapRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{6} +} + +type IndexIdentifierMapResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IndexIdentifierMap map[uint32]*FABRIDPolicyIdentifier `protobuf:"bytes,1,rep,name=index_identifier_map,json=indexIdentifierMap,proto3" json:"index_identifier_map,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *IndexIdentifierMapResponse) Reset() { + *x = IndexIdentifierMapResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IndexIdentifierMapResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IndexIdentifierMapResponse) ProtoMessage() {} + +func (x *IndexIdentifierMapResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IndexIdentifierMapResponse.ProtoReflect.Descriptor instead. +func (*IndexIdentifierMapResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{7} +} + +func (x *IndexIdentifierMapResponse) GetIndexIdentifierMap() map[uint32]*FABRIDPolicyIdentifier { + if x != nil { + return x.IndexIdentifierMap + } + return nil +} + +type RemotePolicyDescriptionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PolicyIdentifier uint32 `protobuf:"varint,1,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` + IsdAs uint64 `protobuf:"varint,2,opt,name=isd_as,json=isdAs,proto3" json:"isd_as,omitempty"` +} + +func (x *RemotePolicyDescriptionRequest) Reset() { + *x = RemotePolicyDescriptionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemotePolicyDescriptionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemotePolicyDescriptionRequest) ProtoMessage() {} + +func (x *RemotePolicyDescriptionRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemotePolicyDescriptionRequest.ProtoReflect.Descriptor instead. +func (*RemotePolicyDescriptionRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{8} +} + +func (x *RemotePolicyDescriptionRequest) GetPolicyIdentifier() uint32 { + if x != nil { + return x.PolicyIdentifier + } + return 0 +} + +func (x *RemotePolicyDescriptionRequest) GetIsdAs() uint64 { + if x != nil { + return x.IsdAs + } + return 0 +} + +type RemotePolicyDescriptionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *RemotePolicyDescriptionResponse) Reset() { + *x = RemotePolicyDescriptionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemotePolicyDescriptionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemotePolicyDescriptionResponse) ProtoMessage() {} + +func (x *RemotePolicyDescriptionResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemotePolicyDescriptionResponse.ProtoReflect.Descriptor instead. +func (*RemotePolicyDescriptionResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{9} +} + +func (x *RemotePolicyDescriptionResponse) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +type LocalPolicyDescriptionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PolicyIdentifier uint32 `protobuf:"varint,1,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` +} + +func (x *LocalPolicyDescriptionRequest) Reset() { + *x = LocalPolicyDescriptionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalPolicyDescriptionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalPolicyDescriptionRequest) ProtoMessage() {} + +func (x *LocalPolicyDescriptionRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalPolicyDescriptionRequest.ProtoReflect.Descriptor instead. +func (*LocalPolicyDescriptionRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{10} +} + +func (x *LocalPolicyDescriptionRequest) GetPolicyIdentifier() uint32 { + if x != nil { + return x.PolicyIdentifier + } + return 0 +} + +type LocalPolicyDescriptionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` +} + +func (x *LocalPolicyDescriptionResponse) Reset() { + *x = LocalPolicyDescriptionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalPolicyDescriptionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalPolicyDescriptionResponse) ProtoMessage() {} + +func (x *LocalPolicyDescriptionResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocalPolicyDescriptionResponse.ProtoReflect.Descriptor instead. +func (*LocalPolicyDescriptionResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{11} +} + +func (x *LocalPolicyDescriptionResponse) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +var File_proto_control_plane_experimental_v1_fabrid_proto protoreflect.FileDescriptor + +var file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc = []byte{ + 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, + 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x50, 0x0a, 0x0b, 0x4d, 0x50, 0x4c, 0x53, 0x49, 0x50, 0x41, 0x72, + 0x72, 0x61, 0x79, 0x12, 0x41, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x50, 0x4c, 0x53, 0x49, 0x50, 0x52, + 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x4f, 0x0a, 0x06, 0x4d, 0x50, 0x4c, 0x53, 0x49, 0x50, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x70, 0x6c, 0x73, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6d, 0x70, 0x6c, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x24, 0x0a, 0x0e, 0x4d, 0x50, 0x4c, 0x53, 0x4d, + 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xf3, 0x03, + 0x0a, 0x0f, 0x4d, 0x50, 0x4c, 0x53, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x91, 0x01, + 0x0a, 0x1b, 0x6d, 0x70, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x52, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, + 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x50, 0x4c, 0x53, 0x4d, 0x61, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x70, 0x6c, 0x73, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x4d, + 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, 0x6d, 0x70, 0x6c, 0x73, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x4d, 0x61, + 0x70, 0x12, 0x63, 0x0a, 0x0b, 0x6d, 0x70, 0x6c, 0x73, 0x5f, 0x69, 0x70, 0x5f, 0x6d, 0x61, 0x70, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x50, 0x4c, + 0x53, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x70, 0x6c, + 0x73, 0x49, 0x70, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x6d, 0x70, 0x6c, + 0x73, 0x49, 0x70, 0x4d, 0x61, 0x70, 0x1a, 0x4b, 0x0a, 0x1d, 0x4d, 0x70, 0x6c, 0x73, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x4d, + 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x6e, 0x0a, 0x0e, 0x4d, 0x70, 0x6c, 0x73, 0x49, 0x70, 0x4d, 0x61, 0x70, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x50, 0x4c, + 0x53, 0x49, 0x50, 0x41, 0x72, 0x72, 0x61, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x1c, 0x0a, 0x1a, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x8b, 0x01, 0x0a, 0x1b, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6c, 0x0a, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x69, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x38, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x22, + 0x1b, 0x0a, 0x19, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xad, 0x02, 0x0a, + 0x1a, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x14, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x57, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x12, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x1a, 0x82, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x51, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, + 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, + 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x64, 0x0a, 0x1e, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, + 0x0a, 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x15, 0x0a, 0x06, 0x69, + 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, + 0x41, 0x73, 0x22, 0x43, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, 0x1d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x42, 0x0a, 0x1e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xf1, 0x03, 0x0a, 0x12, 0x46, 0x41, + 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x9a, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, + 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x3f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, + 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, + 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x4d, 0x61, 0x70, 0x12, 0x3e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, + 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, + 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa3, 0x01, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x42, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0xb5, 0x02, + 0x0a, 0x12, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, + 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, + 0x07, 0x4d, 0x50, 0x4c, 0x53, 0x4d, 0x61, 0x70, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x50, 0x4c, 0x53, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x50, 0x4c, 0x53, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, + 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_proto_control_plane_experimental_v1_fabrid_proto_rawDescOnce sync.Once + file_proto_control_plane_experimental_v1_fabrid_proto_rawDescData = file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc +) + +func file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP() []byte { + file_proto_control_plane_experimental_v1_fabrid_proto_rawDescOnce.Do(func() { + file_proto_control_plane_experimental_v1_fabrid_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_control_plane_experimental_v1_fabrid_proto_rawDescData) + }) + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescData +} + +var file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_proto_control_plane_experimental_v1_fabrid_proto_goTypes = []interface{}{ + (*MPLSIPArray)(nil), // 0: proto.control_plane.experimental.v1.MPLSIPArray + (*MPLSIP)(nil), // 1: proto.control_plane.experimental.v1.MPLSIP + (*MPLSMapRequest)(nil), // 2: proto.control_plane.experimental.v1.MPLSMapRequest + (*MPLSMapResponse)(nil), // 3: proto.control_plane.experimental.v1.MPLSMapResponse + (*SupportedIndicesMapRequest)(nil), // 4: proto.control_plane.experimental.v1.SupportedIndicesMapRequest + (*SupportedIndicesMapResponse)(nil), // 5: proto.control_plane.experimental.v1.SupportedIndicesMapResponse + (*IndexIdentifierMapRequest)(nil), // 6: proto.control_plane.experimental.v1.IndexIdentifierMapRequest + (*IndexIdentifierMapResponse)(nil), // 7: proto.control_plane.experimental.v1.IndexIdentifierMapResponse + (*RemotePolicyDescriptionRequest)(nil), // 8: proto.control_plane.experimental.v1.RemotePolicyDescriptionRequest + (*RemotePolicyDescriptionResponse)(nil), // 9: proto.control_plane.experimental.v1.RemotePolicyDescriptionResponse + (*LocalPolicyDescriptionRequest)(nil), // 10: proto.control_plane.experimental.v1.LocalPolicyDescriptionRequest + (*LocalPolicyDescriptionResponse)(nil), // 11: proto.control_plane.experimental.v1.LocalPolicyDescriptionResponse + nil, // 12: proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry + nil, // 13: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry + nil, // 14: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry + (*FABRIDIndexMapEntry)(nil), // 15: proto.control_plane.experimental.v1.FABRIDIndexMapEntry + (*FABRIDPolicyIdentifier)(nil), // 16: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier +} +var file_proto_control_plane_experimental_v1_fabrid_proto_depIdxs = []int32{ + 1, // 0: proto.control_plane.experimental.v1.MPLSIPArray.entry:type_name -> proto.control_plane.experimental.v1.MPLSIP + 12, // 1: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_interface_policies_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry + 13, // 2: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_ip_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry + 15, // 3: proto.control_plane.experimental.v1.SupportedIndicesMapResponse.supported_indices_map:type_name -> proto.control_plane.experimental.v1.FABRIDIndexMapEntry + 14, // 4: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.index_identifier_map:type_name -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry + 0, // 5: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry.value:type_name -> proto.control_plane.experimental.v1.MPLSIPArray + 16, // 6: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry.value:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 4, // 7: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:input_type -> proto.control_plane.experimental.v1.SupportedIndicesMapRequest + 6, // 8: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:input_type -> proto.control_plane.experimental.v1.IndexIdentifierMapRequest + 10, // 9: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:input_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionRequest + 8, // 10: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:input_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionRequest + 2, // 11: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:input_type -> proto.control_plane.experimental.v1.MPLSMapRequest + 5, // 12: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:output_type -> proto.control_plane.experimental.v1.SupportedIndicesMapResponse + 7, // 13: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:output_type -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse + 11, // 14: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:output_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionResponse + 9, // 15: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:output_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionResponse + 3, // 16: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:output_type -> proto.control_plane.experimental.v1.MPLSMapResponse + 12, // [12:17] is the sub-list for method output_type + 7, // [7:12] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_proto_control_plane_experimental_v1_fabrid_proto_init() } +func file_proto_control_plane_experimental_v1_fabrid_proto_init() { + if File_proto_control_plane_experimental_v1_fabrid_proto != nil { + return + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MPLSIPArray); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MPLSIP); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MPLSMapRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MPLSMapResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SupportedIndicesMapRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SupportedIndicesMapResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IndexIdentifierMapRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IndexIdentifierMapResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemotePolicyDescriptionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemotePolicyDescriptionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalPolicyDescriptionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalPolicyDescriptionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc, + NumEnums: 0, + NumMessages: 15, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_proto_control_plane_experimental_v1_fabrid_proto_goTypes, + DependencyIndexes: file_proto_control_plane_experimental_v1_fabrid_proto_depIdxs, + MessageInfos: file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes, + }.Build() + File_proto_control_plane_experimental_v1_fabrid_proto = out.File + file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc = nil + file_proto_control_plane_experimental_v1_fabrid_proto_goTypes = nil + file_proto_control_plane_experimental_v1_fabrid_proto_depIdxs = nil +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConnInterface + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion6 + +// FABRIDInterServiceClient is the client API for FABRIDInterService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type FABRIDInterServiceClient interface { + SupportedIndicesMap(ctx context.Context, in *SupportedIndicesMapRequest, opts ...grpc.CallOption) (*SupportedIndicesMapResponse, error) + IndexIdentifierMap(ctx context.Context, in *IndexIdentifierMapRequest, opts ...grpc.CallOption) (*IndexIdentifierMapResponse, error) + LocalPolicyDescription(ctx context.Context, in *LocalPolicyDescriptionRequest, opts ...grpc.CallOption) (*LocalPolicyDescriptionResponse, error) +} + +type fABRIDInterServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewFABRIDInterServiceClient(cc grpc.ClientConnInterface) FABRIDInterServiceClient { + return &fABRIDInterServiceClient{cc} +} + +func (c *fABRIDInterServiceClient) SupportedIndicesMap(ctx context.Context, in *SupportedIndicesMapRequest, opts ...grpc.CallOption) (*SupportedIndicesMapResponse, error) { + out := new(SupportedIndicesMapResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDInterService/SupportedIndicesMap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *fABRIDInterServiceClient) IndexIdentifierMap(ctx context.Context, in *IndexIdentifierMapRequest, opts ...grpc.CallOption) (*IndexIdentifierMapResponse, error) { + out := new(IndexIdentifierMapResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDInterService/IndexIdentifierMap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *fABRIDInterServiceClient) LocalPolicyDescription(ctx context.Context, in *LocalPolicyDescriptionRequest, opts ...grpc.CallOption) (*LocalPolicyDescriptionResponse, error) { + out := new(LocalPolicyDescriptionResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDInterService/LocalPolicyDescription", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// FABRIDInterServiceServer is the server API for FABRIDInterService service. +type FABRIDInterServiceServer interface { + SupportedIndicesMap(context.Context, *SupportedIndicesMapRequest) (*SupportedIndicesMapResponse, error) + IndexIdentifierMap(context.Context, *IndexIdentifierMapRequest) (*IndexIdentifierMapResponse, error) + LocalPolicyDescription(context.Context, *LocalPolicyDescriptionRequest) (*LocalPolicyDescriptionResponse, error) +} + +// UnimplementedFABRIDInterServiceServer can be embedded to have forward compatible implementations. +type UnimplementedFABRIDInterServiceServer struct { +} + +func (*UnimplementedFABRIDInterServiceServer) SupportedIndicesMap(context.Context, *SupportedIndicesMapRequest) (*SupportedIndicesMapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SupportedIndicesMap not implemented") +} +func (*UnimplementedFABRIDInterServiceServer) IndexIdentifierMap(context.Context, *IndexIdentifierMapRequest) (*IndexIdentifierMapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IndexIdentifierMap not implemented") +} +func (*UnimplementedFABRIDInterServiceServer) LocalPolicyDescription(context.Context, *LocalPolicyDescriptionRequest) (*LocalPolicyDescriptionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LocalPolicyDescription not implemented") +} + +func RegisterFABRIDInterServiceServer(s *grpc.Server, srv FABRIDInterServiceServer) { + s.RegisterService(&_FABRIDInterService_serviceDesc, srv) +} + +func _FABRIDInterService_SupportedIndicesMap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SupportedIndicesMapRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDInterServiceServer).SupportedIndicesMap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDInterService/SupportedIndicesMap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDInterServiceServer).SupportedIndicesMap(ctx, req.(*SupportedIndicesMapRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FABRIDInterService_IndexIdentifierMap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(IndexIdentifierMapRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDInterServiceServer).IndexIdentifierMap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDInterService/IndexIdentifierMap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDInterServiceServer).IndexIdentifierMap(ctx, req.(*IndexIdentifierMapRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FABRIDInterService_LocalPolicyDescription_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LocalPolicyDescriptionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDInterServiceServer).LocalPolicyDescription(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDInterService/LocalPolicyDescription", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDInterServiceServer).LocalPolicyDescription(ctx, req.(*LocalPolicyDescriptionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _FABRIDInterService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "proto.control_plane.experimental.v1.FABRIDInterService", + HandlerType: (*FABRIDInterServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SupportedIndicesMap", + Handler: _FABRIDInterService_SupportedIndicesMap_Handler, + }, + { + MethodName: "IndexIdentifierMap", + Handler: _FABRIDInterService_IndexIdentifierMap_Handler, + }, + { + MethodName: "LocalPolicyDescription", + Handler: _FABRIDInterService_LocalPolicyDescription_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/control_plane/experimental/v1/fabrid.proto", +} + +// FABRIDIntraServiceClient is the client API for FABRIDIntraService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type FABRIDIntraServiceClient interface { + RemotePolicyDescription(ctx context.Context, in *RemotePolicyDescriptionRequest, opts ...grpc.CallOption) (*RemotePolicyDescriptionResponse, error) + MPLSMap(ctx context.Context, in *MPLSMapRequest, opts ...grpc.CallOption) (*MPLSMapResponse, error) +} + +type fABRIDIntraServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewFABRIDIntraServiceClient(cc grpc.ClientConnInterface) FABRIDIntraServiceClient { + return &fABRIDIntraServiceClient{cc} +} + +func (c *fABRIDIntraServiceClient) RemotePolicyDescription(ctx context.Context, in *RemotePolicyDescriptionRequest, opts ...grpc.CallOption) (*RemotePolicyDescriptionResponse, error) { + out := new(RemotePolicyDescriptionResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDIntraService/RemotePolicyDescription", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *fABRIDIntraServiceClient) MPLSMap(ctx context.Context, in *MPLSMapRequest, opts ...grpc.CallOption) (*MPLSMapResponse, error) { + out := new(MPLSMapResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDIntraService/MPLSMap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// FABRIDIntraServiceServer is the server API for FABRIDIntraService service. +type FABRIDIntraServiceServer interface { + RemotePolicyDescription(context.Context, *RemotePolicyDescriptionRequest) (*RemotePolicyDescriptionResponse, error) + MPLSMap(context.Context, *MPLSMapRequest) (*MPLSMapResponse, error) +} + +// UnimplementedFABRIDIntraServiceServer can be embedded to have forward compatible implementations. +type UnimplementedFABRIDIntraServiceServer struct { +} + +func (*UnimplementedFABRIDIntraServiceServer) RemotePolicyDescription(context.Context, *RemotePolicyDescriptionRequest) (*RemotePolicyDescriptionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemotePolicyDescription not implemented") +} +func (*UnimplementedFABRIDIntraServiceServer) MPLSMap(context.Context, *MPLSMapRequest) (*MPLSMapResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MPLSMap not implemented") +} + +func RegisterFABRIDIntraServiceServer(s *grpc.Server, srv FABRIDIntraServiceServer) { + s.RegisterService(&_FABRIDIntraService_serviceDesc, srv) +} + +func _FABRIDIntraService_RemotePolicyDescription_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemotePolicyDescriptionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDIntraServiceServer).RemotePolicyDescription(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDIntraService/RemotePolicyDescription", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDIntraServiceServer).RemotePolicyDescription(ctx, req.(*RemotePolicyDescriptionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FABRIDIntraService_MPLSMap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MPLSMapRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDIntraServiceServer).MPLSMap(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDIntraService/MPLSMap", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDIntraServiceServer).MPLSMap(ctx, req.(*MPLSMapRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _FABRIDIntraService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "proto.control_plane.experimental.v1.FABRIDIntraService", + HandlerType: (*FABRIDIntraServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "RemotePolicyDescription", + Handler: _FABRIDIntraService_RemotePolicyDescription_Handler, + }, + { + MethodName: "MPLSMap", + Handler: _FABRIDIntraService_MPLSMap_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/control_plane/experimental/v1/fabrid.proto", +} diff --git a/pkg/proto/control_plane/experimental/fabrid_extensions.pb.go b/pkg/proto/control_plane/experimental/fabrid_extensions.pb.go new file mode 100755 index 0000000000..9c7a3ab80e --- /dev/null +++ b/pkg/proto/control_plane/experimental/fabrid_extensions.pb.go @@ -0,0 +1,590 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.10 +// source: proto/control_plane/experimental/v1/fabrid_extensions.proto + +package experimental + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FABRIDConnectionType int32 + +const ( + FABRIDConnectionType_FABRID_CONNECTION_TYPE_UNSPECIFIED FABRIDConnectionType = 0 + FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV4_RANGE FABRIDConnectionType = 1 + FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV6_RANGE FABRIDConnectionType = 2 + FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE FABRIDConnectionType = 3 + FABRIDConnectionType_FABRID_CONNECTION_TYPE_WILDCARD FABRIDConnectionType = 4 +) + +// Enum value maps for FABRIDConnectionType. +var ( + FABRIDConnectionType_name = map[int32]string{ + 0: "FABRID_CONNECTION_TYPE_UNSPECIFIED", + 1: "FABRID_CONNECTION_TYPE_IPV4_RANGE", + 2: "FABRID_CONNECTION_TYPE_IPV6_RANGE", + 3: "FABRID_CONNECTION_TYPE_INTERFACE", + 4: "FABRID_CONNECTION_TYPE_WILDCARD", + } + FABRIDConnectionType_value = map[string]int32{ + "FABRID_CONNECTION_TYPE_UNSPECIFIED": 0, + "FABRID_CONNECTION_TYPE_IPV4_RANGE": 1, + "FABRID_CONNECTION_TYPE_IPV6_RANGE": 2, + "FABRID_CONNECTION_TYPE_INTERFACE": 3, + "FABRID_CONNECTION_TYPE_WILDCARD": 4, + } +) + +func (x FABRIDConnectionType) Enum() *FABRIDConnectionType { + p := new(FABRIDConnectionType) + *p = x + return p +} + +func (x FABRIDConnectionType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FABRIDConnectionType) Descriptor() protoreflect.EnumDescriptor { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_enumTypes[0].Descriptor() +} + +func (FABRIDConnectionType) Type() protoreflect.EnumType { + return &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_enumTypes[0] +} + +func (x FABRIDConnectionType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FABRIDConnectionType.Descriptor instead. +func (FABRIDConnectionType) EnumDescriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{0} +} + +type FABRIDDetachableMaps struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SupportedIndicesMap []*FABRIDIndexMapEntry `protobuf:"bytes,1,rep,name=supported_indices_map,json=supportedIndicesMap,proto3" json:"supported_indices_map,omitempty"` + IndexIdentifierMap map[uint32]*FABRIDPolicyIdentifier `protobuf:"bytes,2,rep,name=index_identifier_map,json=indexIdentifierMap,proto3" json:"index_identifier_map,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *FABRIDDetachableMaps) Reset() { + *x = FABRIDDetachableMaps{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDDetachableMaps) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDDetachableMaps) ProtoMessage() {} + +func (x *FABRIDDetachableMaps) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDDetachableMaps.ProtoReflect.Descriptor instead. +func (*FABRIDDetachableMaps) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{0} +} + +func (x *FABRIDDetachableMaps) GetSupportedIndicesMap() []*FABRIDIndexMapEntry { + if x != nil { + return x.SupportedIndicesMap + } + return nil +} + +func (x *FABRIDDetachableMaps) GetIndexIdentifierMap() map[uint32]*FABRIDPolicyIdentifier { + if x != nil { + return x.IndexIdentifierMap + } + return nil +} + +type FABRIDPolicyIdentifier struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PolicyIsLocal bool `protobuf:"varint,1,opt,name=policy_is_local,json=policyIsLocal,proto3" json:"policy_is_local,omitempty"` + PolicyIdentifier uint32 `protobuf:"varint,2,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` +} + +func (x *FABRIDPolicyIdentifier) Reset() { + *x = FABRIDPolicyIdentifier{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDPolicyIdentifier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDPolicyIdentifier) ProtoMessage() {} + +func (x *FABRIDPolicyIdentifier) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDPolicyIdentifier.ProtoReflect.Descriptor instead. +func (*FABRIDPolicyIdentifier) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{1} +} + +func (x *FABRIDPolicyIdentifier) GetPolicyIsLocal() bool { + if x != nil { + return x.PolicyIsLocal + } + return false +} + +func (x *FABRIDPolicyIdentifier) GetPolicyIdentifier() uint32 { + if x != nil { + return x.PolicyIdentifier + } + return 0 +} + +type FABRIDIndexMapEntry struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IePair *FABRIDIngressEgressPair `protobuf:"bytes,1,opt,name=ie_pair,json=iePair,proto3" json:"ie_pair,omitempty"` + SupportedPolicyIndices []uint32 `protobuf:"varint,2,rep,packed,name=supported_policy_indices,json=supportedPolicyIndices,proto3" json:"supported_policy_indices,omitempty"` +} + +func (x *FABRIDIndexMapEntry) Reset() { + *x = FABRIDIndexMapEntry{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDIndexMapEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDIndexMapEntry) ProtoMessage() {} + +func (x *FABRIDIndexMapEntry) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDIndexMapEntry.ProtoReflect.Descriptor instead. +func (*FABRIDIndexMapEntry) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{2} +} + +func (x *FABRIDIndexMapEntry) GetIePair() *FABRIDIngressEgressPair { + if x != nil { + return x.IePair + } + return nil +} + +func (x *FABRIDIndexMapEntry) GetSupportedPolicyIndices() []uint32 { + if x != nil { + return x.SupportedPolicyIndices + } + return nil +} + +type FABRIDIngressEgressPair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ingress *FABRIDConnectionPoint `protobuf:"bytes,1,opt,name=ingress,proto3" json:"ingress,omitempty"` + Egress *FABRIDConnectionPoint `protobuf:"bytes,2,opt,name=egress,proto3" json:"egress,omitempty"` +} + +func (x *FABRIDIngressEgressPair) Reset() { + *x = FABRIDIngressEgressPair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDIngressEgressPair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDIngressEgressPair) ProtoMessage() {} + +func (x *FABRIDIngressEgressPair) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDIngressEgressPair.ProtoReflect.Descriptor instead. +func (*FABRIDIngressEgressPair) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{3} +} + +func (x *FABRIDIngressEgressPair) GetIngress() *FABRIDConnectionPoint { + if x != nil { + return x.Ingress + } + return nil +} + +func (x *FABRIDIngressEgressPair) GetEgress() *FABRIDConnectionPoint { + if x != nil { + return x.Egress + } + return nil +} + +type FABRIDConnectionPoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type FABRIDConnectionType `protobuf:"varint,1,opt,name=type,proto3,enum=proto.control_plane.experimental.v1.FABRIDConnectionType" json:"type,omitempty"` + IpAddress []byte `protobuf:"bytes,2,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"` + IpPrefix uint32 `protobuf:"varint,3,opt,name=ip_prefix,json=ipPrefix,proto3" json:"ip_prefix,omitempty"` + Interface uint64 `protobuf:"varint,4,opt,name=interface,proto3" json:"interface,omitempty"` +} + +func (x *FABRIDConnectionPoint) Reset() { + *x = FABRIDConnectionPoint{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDConnectionPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDConnectionPoint) ProtoMessage() {} + +func (x *FABRIDConnectionPoint) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDConnectionPoint.ProtoReflect.Descriptor instead. +func (*FABRIDConnectionPoint) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP(), []int{4} +} + +func (x *FABRIDConnectionPoint) GetType() FABRIDConnectionType { + if x != nil { + return x.Type + } + return FABRIDConnectionType_FABRID_CONNECTION_TYPE_UNSPECIFIED +} + +func (x *FABRIDConnectionPoint) GetIpAddress() []byte { + if x != nil { + return x.IpAddress + } + return nil +} + +func (x *FABRIDConnectionPoint) GetIpPrefix() uint32 { + if x != nil { + return x.IpPrefix + } + return 0 +} + +func (x *FABRIDConnectionPoint) GetInterface() uint64 { + if x != nil { + return x.Interface + } + return 0 +} + +var File_proto_control_plane_experimental_v1_fabrid_extensions_proto protoreflect.FileDescriptor + +var file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDesc = []byte{ + 0x0a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, + 0x76, 0x31, 0x22, 0x8f, 0x03, 0x0a, 0x14, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x6c, 0x0a, 0x15, 0x73, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x6d, + 0x61, 0x70, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x51, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4d, + 0x61, 0x70, 0x73, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x1a, + 0x82, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x51, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x6d, 0x0a, 0x16, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x26, + 0x0a, 0x0f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x73, 0x5f, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, + 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x22, 0xa6, 0x01, 0x0a, 0x13, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x55, 0x0a, 0x07, 0x69, + 0x65, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, 0x69, 0x65, 0x50, 0x61, + 0x69, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0d, 0x52, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0xc3, 0x01, 0x0a, + 0x17, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x12, 0x54, 0x0a, 0x07, 0x69, 0x6e, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x52, + 0x0a, 0x06, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x15, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x4d, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, + 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x70, + 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, + 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x2a, 0xd7, 0x01, 0x0a, 0x14, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, + 0x0a, 0x22, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, + 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x49, 0x50, 0x56, 0x34, 0x5f, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x01, 0x12, 0x25, 0x0a, + 0x21, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x50, 0x56, 0x36, 0x5f, 0x52, 0x41, 0x4e, + 0x47, 0x45, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x5f, 0x43, + 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, + 0x4e, 0x54, 0x45, 0x52, 0x46, 0x41, 0x43, 0x45, 0x10, 0x03, 0x12, 0x23, 0x0a, 0x1f, 0x46, 0x41, + 0x42, 0x52, 0x49, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x4c, 0x44, 0x43, 0x41, 0x52, 0x44, 0x10, 0x04, 0x42, + 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, + 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescOnce sync.Once + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescData = file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDesc +) + +func file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescGZIP() []byte { + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescOnce.Do(func() { + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescData) + }) + return file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDescData +} + +var file_proto_control_plane_experimental_v1_fabrid_extensions_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_proto_control_plane_experimental_v1_fabrid_extensions_proto_goTypes = []interface{}{ + (FABRIDConnectionType)(0), // 0: proto.control_plane.experimental.v1.FABRIDConnectionType + (*FABRIDDetachableMaps)(nil), // 1: proto.control_plane.experimental.v1.FABRIDDetachableMaps + (*FABRIDPolicyIdentifier)(nil), // 2: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + (*FABRIDIndexMapEntry)(nil), // 3: proto.control_plane.experimental.v1.FABRIDIndexMapEntry + (*FABRIDIngressEgressPair)(nil), // 4: proto.control_plane.experimental.v1.FABRIDIngressEgressPair + (*FABRIDConnectionPoint)(nil), // 5: proto.control_plane.experimental.v1.FABRIDConnectionPoint + nil, // 6: proto.control_plane.experimental.v1.FABRIDDetachableMaps.IndexIdentifierMapEntry +} +var file_proto_control_plane_experimental_v1_fabrid_extensions_proto_depIdxs = []int32{ + 3, // 0: proto.control_plane.experimental.v1.FABRIDDetachableMaps.supported_indices_map:type_name -> proto.control_plane.experimental.v1.FABRIDIndexMapEntry + 6, // 1: proto.control_plane.experimental.v1.FABRIDDetachableMaps.index_identifier_map:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps.IndexIdentifierMapEntry + 4, // 2: proto.control_plane.experimental.v1.FABRIDIndexMapEntry.ie_pair:type_name -> proto.control_plane.experimental.v1.FABRIDIngressEgressPair + 5, // 3: proto.control_plane.experimental.v1.FABRIDIngressEgressPair.ingress:type_name -> proto.control_plane.experimental.v1.FABRIDConnectionPoint + 5, // 4: proto.control_plane.experimental.v1.FABRIDIngressEgressPair.egress:type_name -> proto.control_plane.experimental.v1.FABRIDConnectionPoint + 0, // 5: proto.control_plane.experimental.v1.FABRIDConnectionPoint.type:type_name -> proto.control_plane.experimental.v1.FABRIDConnectionType + 2, // 6: proto.control_plane.experimental.v1.FABRIDDetachableMaps.IndexIdentifierMapEntry.value:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() } +func file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() { + if File_proto_control_plane_experimental_v1_fabrid_extensions_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDDetachableMaps); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDPolicyIdentifier); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDIndexMapEntry); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDIngressEgressPair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDConnectionPoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDesc, + NumEnums: 1, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_control_plane_experimental_v1_fabrid_extensions_proto_goTypes, + DependencyIndexes: file_proto_control_plane_experimental_v1_fabrid_extensions_proto_depIdxs, + EnumInfos: file_proto_control_plane_experimental_v1_fabrid_extensions_proto_enumTypes, + MessageInfos: file_proto_control_plane_experimental_v1_fabrid_extensions_proto_msgTypes, + }.Build() + File_proto_control_plane_experimental_v1_fabrid_extensions_proto = out.File + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_rawDesc = nil + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_goTypes = nil + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_depIdxs = nil +} diff --git a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go index da4342be28..667bbc38ad 100755 --- a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go +++ b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go @@ -75,6 +75,53 @@ func (x *EPICDetachedExtension) GetAuthPeerEntries() [][]byte { return nil } +type FABRIDDetachedExtension struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Maps *FABRIDDetachableMaps `protobuf:"bytes,1,opt,name=maps,proto3" json:"maps,omitempty"` +} + +func (x *FABRIDDetachedExtension) Reset() { + *x = FABRIDDetachedExtension{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDDetachedExtension) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDDetachedExtension) ProtoMessage() {} + +func (x *FABRIDDetachedExtension) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDDetachedExtension.ProtoReflect.Descriptor instead. +func (*FABRIDDetachedExtension) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDescGZIP(), []int{1} +} + +func (x *FABRIDDetachedExtension) GetMaps() *FABRIDDetachableMaps { + if x != nil { + return x.Maps + } + return nil +} + var File_proto_control_plane_experimental_v1_seg_detached_extensions_proto protoreflect.FileDescriptor var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDesc = []byte{ @@ -84,18 +131,29 @@ var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDe 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x22, 0x69, 0x0a, 0x15, 0x45, 0x50, 0x49, 0x43, - 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x48, - 0x6f, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x5f, - 0x70, 0x65, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, - 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, - 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, + 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x69, 0x0a, 0x15, 0x45, 0x50, 0x49, 0x43, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, + 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x48, 0x6f, 0x70, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x65, 0x65, + 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x0f, 0x61, 0x75, 0x74, 0x68, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x22, 0x68, 0x0a, 0x17, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x04, 0x6d, + 0x61, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, + 0x4d, 0x61, 0x70, 0x73, 0x52, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -110,16 +168,19 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawD return file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDescData } -var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_goTypes = []interface{}{ - (*EPICDetachedExtension)(nil), // 0: proto.control_plane.experimental.v1.EPICDetachedExtension + (*EPICDetachedExtension)(nil), // 0: proto.control_plane.experimental.v1.EPICDetachedExtension + (*FABRIDDetachedExtension)(nil), // 1: proto.control_plane.experimental.v1.FABRIDDetachedExtension + (*FABRIDDetachableMaps)(nil), // 2: proto.control_plane.experimental.v1.FABRIDDetachableMaps } var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 2, // 0: proto.control_plane.experimental.v1.FABRIDDetachedExtension.maps:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init() } @@ -127,6 +188,7 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init if File_proto_control_plane_experimental_v1_seg_detached_extensions_proto != nil { return } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() if !protoimpl.UnsafeEnabled { file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EPICDetachedExtension); i { @@ -140,6 +202,18 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init return nil } } + file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDDetachedExtension); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -147,7 +221,7 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/proto/control_plane/seg_extensions.pb.go b/pkg/proto/control_plane/seg_extensions.pb.go index 8e6b6e165d..0c8b1e4831 100644 --- a/pkg/proto/control_plane/seg_extensions.pb.go +++ b/pkg/proto/control_plane/seg_extensions.pb.go @@ -511,7 +511,8 @@ type DigestExtension struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epic *DigestExtension_Digest `protobuf:"bytes,1000,opt,name=epic,proto3" json:"epic,omitempty"` + Epic *DigestExtension_Digest `protobuf:"bytes,1000,opt,name=epic,proto3" json:"epic,omitempty"` + Fabrid *DigestExtension_Digest `protobuf:"bytes,1001,opt,name=fabrid,proto3" json:"fabrid,omitempty"` } func (x *DigestExtension) Reset() { @@ -553,12 +554,20 @@ func (x *DigestExtension) GetEpic() *DigestExtension_Digest { return nil } +func (x *DigestExtension) GetFabrid() *DigestExtension_Digest { + if x != nil { + return x.Fabrid + } + return nil +} + type PathSegmentUnsignedExtensions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epic *experimental.EPICDetachedExtension `protobuf:"bytes,1000,opt,name=epic,proto3" json:"epic,omitempty"` + Epic *experimental.EPICDetachedExtension `protobuf:"bytes,1000,opt,name=epic,proto3" json:"epic,omitempty"` + Fabrid *experimental.FABRIDDetachedExtension `protobuf:"bytes,1001,opt,name=fabrid,proto3" json:"fabrid,omitempty"` } func (x *PathSegmentUnsignedExtensions) Reset() { @@ -600,6 +609,13 @@ func (x *PathSegmentUnsignedExtensions) GetEpic() *experimental.EPICDetachedExte return nil } +func (x *PathSegmentUnsignedExtensions) GetFabrid() *experimental.FABRIDDetachedExtension { + if x != nil { + return x.Fabrid + } + return nil +} + type DigestExtension_Digest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -785,32 +801,43 @@ var file_proto_control_plane_v1_seg_extensions_proto_rawDesc = []byte{ 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x78, 0x0a, 0x0f, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x04, 0x65, 0x70, 0x69, - 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x1a, 0x20, - 0x0a, 0x06, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x22, 0x70, 0x0a, 0x1d, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x55, - 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x4f, 0x0a, 0x04, 0x65, 0x70, 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, - 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x50, 0x49, 0x43, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x65, 0x70, - 0x69, 0x63, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, - 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, - 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, - 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, - 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, - 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, - 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0f, 0x44, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x04, 0x65, 0x70, + 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, + 0x47, 0x0a, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, + 0x52, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x1a, 0x20, 0x0a, 0x06, 0x44, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0xc7, 0x01, 0x0a, 0x1d, 0x50, + 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4f, 0x0a, 0x04, + 0x65, 0x70, 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x50, 0x49, 0x43, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, 0x55, 0x0a, + 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, + 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x66, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, + 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, + 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, + 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, + 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, + 0x10, 0x03, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, + 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -848,7 +875,8 @@ var file_proto_control_plane_v1_seg_extensions_proto_goTypes = []interface{}{ nil, // 17: proto.control_plane.v1.CarbonIntensityInfo.IntraEntry nil, // 18: proto.control_plane.v1.CarbonIntensityInfo.InterEntry (*DigestExtension_Digest)(nil), // 19: proto.control_plane.v1.DigestExtension.Digest - (*experimental.EPICDetachedExtension)(nil), // 20: proto.control_plane.experimental.v1.EPICDetachedExtension + (*experimental.EPICDetachedExtension)(nil), // 20: proto.control_plane.experimental.v1.EPICDetachedExtension + (*experimental.FABRIDDetachedExtension)(nil), // 21: proto.control_plane.experimental.v1.FABRIDDetachedExtension } var file_proto_control_plane_v1_seg_extensions_proto_depIdxs = []int32{ 3, // 0: proto.control_plane.v1.PathSegmentExtensions.static_info:type_name -> proto.control_plane.v1.StaticInfoExtension @@ -867,14 +895,16 @@ var file_proto_control_plane_v1_seg_extensions_proto_depIdxs = []int32{ 17, // 13: proto.control_plane.v1.CarbonIntensityInfo.intra:type_name -> proto.control_plane.v1.CarbonIntensityInfo.IntraEntry 18, // 14: proto.control_plane.v1.CarbonIntensityInfo.inter:type_name -> proto.control_plane.v1.CarbonIntensityInfo.InterEntry 19, // 15: proto.control_plane.v1.DigestExtension.epic:type_name -> proto.control_plane.v1.DigestExtension.Digest - 20, // 16: proto.control_plane.v1.PathSegmentUnsignedExtensions.epic:type_name -> proto.control_plane.experimental.v1.EPICDetachedExtension - 7, // 17: proto.control_plane.v1.StaticInfoExtension.GeoEntry.value:type_name -> proto.control_plane.v1.GeoCoordinates - 0, // 18: proto.control_plane.v1.StaticInfoExtension.LinkTypeEntry.value:type_name -> proto.control_plane.v1.LinkType - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 19, // 16: proto.control_plane.v1.DigestExtension.fabrid:type_name -> proto.control_plane.v1.DigestExtension.Digest + 20, // 17: proto.control_plane.v1.PathSegmentUnsignedExtensions.epic:type_name -> proto.control_plane.experimental.v1.EPICDetachedExtension + 21, // 18: proto.control_plane.v1.PathSegmentUnsignedExtensions.fabrid:type_name -> proto.control_plane.experimental.v1.FABRIDDetachedExtension + 7, // 19: proto.control_plane.v1.StaticInfoExtension.GeoEntry.value:type_name -> proto.control_plane.v1.GeoCoordinates + 0, // 20: proto.control_plane.v1.StaticInfoExtension.LinkTypeEntry.value:type_name -> proto.control_plane.v1.LinkType + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_proto_control_plane_v1_seg_extensions_proto_init() } diff --git a/pkg/segment/BUILD.bazel b/pkg/segment/BUILD.bazel index c4185122dd..89d1ab38ce 100644 --- a/pkg/segment/BUILD.bazel +++ b/pkg/segment/BUILD.bazel @@ -20,10 +20,12 @@ go_library( "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", "//pkg/proto/control_plane:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", "//pkg/proto/crypto:go_default_library", "//pkg/scrypto/signed:go_default_library", "//pkg/segment/extensions/digest:go_default_library", "//pkg/segment/extensions/epic:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/segment/extensions/staticinfo:go_default_library", "//pkg/slayers/path:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", @@ -49,6 +51,7 @@ go_test( "//pkg/scrypto/signed:go_default_library", "//pkg/segment/extensions/digest:go_default_library", "//pkg/segment/extensions/epic:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/slayers/path:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/pkg/segment/extensions/digest/BUILD.bazel b/pkg/segment/extensions/digest/BUILD.bazel index a174a73076..8ad5c39fdd 100644 --- a/pkg/segment/extensions/digest/BUILD.bazel +++ b/pkg/segment/extensions/digest/BUILD.bazel @@ -17,6 +17,7 @@ go_test( deps = [ ":go_default_library", "//pkg/segment/extensions/epic:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", ], ) diff --git a/pkg/segment/extensions/digest/digest.go b/pkg/segment/extensions/digest/digest.go index 1a41352029..700733b2ca 100644 --- a/pkg/segment/extensions/digest/digest.go +++ b/pkg/segment/extensions/digest/digest.go @@ -30,25 +30,36 @@ type Digest struct { const DigestLength = 16 type Extension struct { - // Epic dentoes the digest of the EpicDetachedExtension + // Epic denotes the digest of the EpicDetachedExtension Epic Digest + // Fabrid denotes the hash of both the supported indices map, as well as the + // index to identifier map. + Fabrid Digest } func ExtensionFromPB(d *cppb.DigestExtension) *Extension { if d == nil { return nil } + var epic Digest + var fabrid Digest if d.Epic == nil { - return &Extension{ - Epic: Digest{}, - } + epic = Digest{} + } else { + e := make([]byte, DigestLength) + copy(e, d.Epic.Digest) + epic = Digest{Digest: e} + } + if d.Fabrid == nil { + fabrid = Digest{} + } else { + e := make([]byte, DigestLength) + copy(e, d.Fabrid.Digest) + fabrid = Digest{Digest: e} } - e := make([]byte, DigestLength) - copy(e, d.Epic.Digest) return &Extension{ - Epic: Digest{ - Digest: e, - }, + Epic: epic, + Fabrid: fabrid, } } @@ -58,10 +69,16 @@ func ExtensionToPB(d *Extension) *cppb.DigestExtension { } e := make([]byte, DigestLength) copy(e, d.Epic.Digest) + + f := make([]byte, DigestLength) + copy(f, d.Fabrid.Digest) return &cppb.DigestExtension{ Epic: &cppb.DigestExtension_Digest{ Digest: e, }, + Fabrid: &cppb.DigestExtension_Digest{ + Digest: f, + }, } } diff --git a/pkg/segment/extensions/digest/digest_test.go b/pkg/segment/extensions/digest/digest_test.go index 2ad1d385b9..2510a97c5a 100644 --- a/pkg/segment/extensions/digest/digest_test.go +++ b/pkg/segment/extensions/digest/digest_test.go @@ -21,6 +21,7 @@ import ( "github.com/scionproto/scion/pkg/segment/extensions/digest" "github.com/scionproto/scion/pkg/segment/extensions/epic" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" ) func TestDecodeEncode(t *testing.T) { @@ -34,6 +35,20 @@ func TestDecodeEncode(t *testing.T) { AuthHopEntry: hop, AuthPeerEntries: peers, } + fd := &fabrid.Detached{ + SupportedIndicesMap: fabrid.SupportedIndicesMap{ + fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.2.100", + Prefix: 22, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 44, + }}: []uint8{1}}, + IndexIdentiferMap: fabrid.IndexIdentifierMap{}, + } var d digest.Digest input, err := ed.DigestInput() @@ -42,8 +57,14 @@ func TestDecodeEncode(t *testing.T) { err = d.Validate(input) assert.NoError(t, err) + var fabridDigest digest.Digest + fabridDigest.Set(fd.Hash()) + err = fabridDigest.Validate(fd.Hash()) + assert.NoError(t, err) + dig := &digest.Extension{ - Epic: d, + Epic: d, + Fabrid: fabridDigest, } dig2 := digest.ExtensionFromPB(digest.ExtensionToPB(dig)) assert.Equal(t, dig, dig2) diff --git a/pkg/segment/extensions/fabrid/BUILD.bazel b/pkg/segment/extensions/fabrid/BUILD.bazel new file mode 100644 index 0000000000..8397738817 --- /dev/null +++ b/pkg/segment/extensions/fabrid/BUILD.bazel @@ -0,0 +1,22 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["fabrid.go"], + importpath = "github.com/scionproto/scion/pkg/segment/extensions/fabrid", + visibility = ["//visibility:public"], + deps = [ + "//pkg/proto/control_plane/experimental:go_default_library", + "//pkg/segment/extensions/digest:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["fabrid_test.go"], + embed = [":go_default_library"], + deps = [ + "//pkg/proto/control_plane/experimental:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + ], +) diff --git a/pkg/segment/extensions/fabrid/fabrid.go b/pkg/segment/extensions/fabrid/fabrid.go new file mode 100644 index 0000000000..464420e8b3 --- /dev/null +++ b/pkg/segment/extensions/fabrid/fabrid.go @@ -0,0 +1,349 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "crypto/sha256" + "encoding/binary" + "fmt" + "net" + "sort" + + fabridpb "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + "github.com/scionproto/scion/pkg/segment/extensions/digest" +) + +type SupportedIndicesMap map[ConnectionPair][]uint8 + +type IndexIdentifierMap map[uint8]*PolicyIdentifier + +type Detached struct { + SupportedIndicesMap SupportedIndicesMap + IndexIdentiferMap IndexIdentifierMap +} + +func (ind *SupportedIndicesMap) SortedKeys() []ConnectionPair { + orderedKeysSupIndex := make([]ConnectionPair, 0, len(*ind)) + for k := range *ind { + orderedKeysSupIndex = append(orderedKeysSupIndex, k) + } + sort.Slice(orderedKeysSupIndex, func(i int, j int) bool { + if orderedKeysSupIndex[i].Ingress != orderedKeysSupIndex[j].Ingress { + return orderedKeysSupIndex[i].Ingress.Less(orderedKeysSupIndex[j].Ingress) + } + return orderedKeysSupIndex[i].Egress.Less(orderedKeysSupIndex[j].Egress) + }) + return orderedKeysSupIndex +} + +func (id *IndexIdentifierMap) SortedKeys() []uint8 { + orderedKeys := make([]uint8, 0, len(*id)) + for k := range *id { + orderedKeys = append(orderedKeys, k) + } + sort.Slice(orderedKeys, func(i int, j int) bool { + return orderedKeys[i] < orderedKeys[j] + }) + return orderedKeys +} + +type ConnectionPointType string + +const ( + IPv4Range ConnectionPointType = "ipv4" + IPv6Range ConnectionPointType = "ipv6" + Interface ConnectionPointType = "interface" + Wildcard ConnectionPointType = "wildcard" +) + +type ConnectionPoint struct { + Type ConnectionPointType + IP string // Stored as a string to allow it to be key of a map. + Prefix uint32 + InterfaceId uint16 +} + +// To ensure that the connection point strings are identical, i.e. without padding, +// parse using the net library +func IPConnectionPointFromString(IP string, Prefix uint32, + Type ConnectionPointType) ConnectionPoint { + var m net.IPMask + if Type == IPv4Range { + m = net.CIDRMask(int(Prefix), 8*net.IPv4len) + } else if Type == IPv6Range { + m = net.CIDRMask(int(Prefix), 8*net.IPv6len) + } + return ConnectionPoint{Type: Type, IP: net.ParseIP(IP).Mask(m).String(), Prefix: Prefix} +} + +func (c *ConnectionPoint) Less(d ConnectionPoint) bool { + if c.Type != d.Type { + return c.Type < d.Type + } + if c.IP != d.IP { + return c.IP < d.IP + } + if c.Prefix != d.Prefix { + return c.Prefix < d.Prefix + } + return c.InterfaceId < d.InterfaceId +} + +func (c *ConnectionPoint) IPNetwork() *net.IPNet { + if c.Type == IPv4Range { + m := net.CIDRMask(int(c.Prefix), 8*net.IPv4len) + return &net.IPNet{IP: net.ParseIP(c.IP).Mask(m), Mask: m} + } else if c.Type == IPv6Range { + m := net.CIDRMask(int(c.Prefix), 8*net.IPv6len) + return &net.IPNet{IP: net.ParseIP(c.IP).Mask(m), Mask: m} + } + return &net.IPNet{} +} +func (c *ConnectionPoint) MatchesIF(intf uint16) bool { + return (c.Type == Interface && c.InterfaceId == intf) || c.Type == Wildcard +} + +type ConnectionPair struct { + Ingress ConnectionPoint + Egress ConnectionPoint +} + +func (c *ConnectionPair) Matches(ingress, egress uint16, allowIpPolicies bool) bool { + match := c.Ingress.MatchesIF(ingress) && c.Egress.MatchesIF(egress) + if allowIpPolicies { + match = match || (c.Ingress.MatchesIF(ingress) && egress == 0 && + (c.Egress.Type == IPv4Range || c.Egress.Type == IPv6Range)) + } + return match +} + +type PolicyIdentifier struct { + IsLocal bool + Identifier uint32 +} + +func PolicyIdentifierToPB(identifier *PolicyIdentifier) *fabridpb.FABRIDPolicyIdentifier { + return &fabridpb.FABRIDPolicyIdentifier{ + PolicyIsLocal: identifier.IsLocal, + PolicyIdentifier: identifier.Identifier, + } +} + +func PolicyIdentifierFromPB(identifier *fabridpb.FABRIDPolicyIdentifier) *PolicyIdentifier { + return &PolicyIdentifier{ + IsLocal: identifier.PolicyIsLocal, + Identifier: identifier.PolicyIdentifier, + } +} + +func ConnectionPointToPB(point ConnectionPoint) *fabridpb.FABRIDConnectionPoint { + switch point.Type { + case IPv4Range: + return &fabridpb.FABRIDConnectionPoint{ + Type: fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV4_RANGE, + IpAddress: point.IPNetwork().IP, + IpPrefix: point.Prefix, + } + case IPv6Range: + return &fabridpb.FABRIDConnectionPoint{ + Type: fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV6_RANGE, + IpAddress: point.IPNetwork().IP, + IpPrefix: point.Prefix, + } + case Interface: + return &fabridpb.FABRIDConnectionPoint{ + Type: fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE, + Interface: uint64(point.InterfaceId), + } + case Wildcard: + return &fabridpb.FABRIDConnectionPoint{ + Type: fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_WILDCARD, + } + default: + return &fabridpb.FABRIDConnectionPoint{} + } +} + +func ConnectionPointFromPB(point *fabridpb.FABRIDConnectionPoint) ConnectionPoint { + switch point.Type { + case fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV4_RANGE: + return ConnectionPoint{ + Type: IPv4Range, + IP: net.IP(point.IpAddress).String(), + Prefix: point.IpPrefix, + } + case fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV6_RANGE: + return ConnectionPoint{ + Type: IPv6Range, + IP: net.IP(point.IpAddress).String(), + Prefix: point.IpPrefix, + } + case fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE: + return ConnectionPoint{ + Type: Interface, + InterfaceId: uint16(point.Interface), + } + case fabridpb.FABRIDConnectionType_FABRID_CONNECTION_TYPE_WILDCARD: + return ConnectionPoint{Type: Wildcard} + default: + return ConnectionPoint{} + } +} + +func SupportedIndicesMapToPB(indicesMap SupportedIndicesMap) []*fabridpb.FABRIDIndexMapEntry { + supIndices := make([]*fabridpb.FABRIDIndexMapEntry, 0) + for ie, indices := range indicesMap { + indicesu32 := make([]uint32, len(indices)) + for i, index := range indices { + indicesu32[i] = uint32(index) + } + supIndices = append(supIndices, &fabridpb.FABRIDIndexMapEntry{ + IePair: &fabridpb.FABRIDIngressEgressPair{ + Ingress: ConnectionPointToPB(ie.Ingress), + Egress: ConnectionPointToPB(ie.Egress), + }, + SupportedPolicyIndices: indicesu32, + }) + + } + return supIndices +} + +func SupportedIndicesMapFromPB(indicesMap []*fabridpb.FABRIDIndexMapEntry) SupportedIndicesMap { + supIndices := make(SupportedIndicesMap, 0) + for _, entry := range indicesMap { + indicesu8 := make([]uint8, len(entry.SupportedPolicyIndices)) + for i, index := range entry.SupportedPolicyIndices { + indicesu8[i] = uint8(index) + } + supIndices[ConnectionPair{ + Ingress: ConnectionPointFromPB(entry.IePair.Ingress), + Egress: ConnectionPointFromPB(entry.IePair.Egress), + }] = indicesu8 + + } + return supIndices +} + +func IndexIdentifierMapToPB(identifierMap IndexIdentifierMap) map[uint32]*fabridpb. + FABRIDPolicyIdentifier { + identMap := make(map[uint32]*fabridpb.FABRIDPolicyIdentifier, len(identifierMap)) + for index, identifier := range identifierMap { + identMap[uint32(index)] = PolicyIdentifierToPB(identifier) + } + return identMap +} + +func IndexIdentifierMapFromPB(identifierMap map[uint32]*fabridpb. + FABRIDPolicyIdentifier) IndexIdentifierMap { + identMap := make(IndexIdentifierMap, len(identifierMap)) + for index, identifier := range identifierMap { + identMap[uint8(index)] = PolicyIdentifierFromPB(identifier) + } + return identMap +} + +func DetachedToPB(detached *Detached) *fabridpb.FABRIDDetachedExtension { + if detached == nil { + return &fabridpb.FABRIDDetachedExtension{} + } + return &fabridpb.FABRIDDetachedExtension{ + Maps: &fabridpb.FABRIDDetachableMaps{ + SupportedIndicesMap: SupportedIndicesMapToPB(detached.SupportedIndicesMap), + IndexIdentifierMap: IndexIdentifierMapToPB(detached.IndexIdentiferMap), + }, + } +} + +func DetachedFromPB(detached *fabridpb.FABRIDDetachedExtension) *Detached { + if detached == nil || detached.Maps == nil { + return nil + } + return &Detached{ + SupportedIndicesMap: SupportedIndicesMapFromPB(detached.Maps.SupportedIndicesMap), + IndexIdentiferMap: IndexIdentifierMapFromPB(detached.Maps.IndexIdentifierMap), + } +} + +func (d *Detached) String() string { + base := " indexIdentifierMap: [" + for _, k := range d.IndexIdentiferMap.SortedKeys() { + base += fmt.Sprintf("{ index: %d, is_local: %t, identifier: %d }", k, + d.IndexIdentiferMap[k].IsLocal, d.IndexIdentiferMap[k].Identifier) + } + base += "], supportedIndicesMap: [" + + for _, k := range d.SupportedIndicesMap.SortedKeys() { + base += fmt.Sprintf("{ ingress: { type: %s ", k.Ingress.Type) + if k.Ingress.Type == Interface { + base += fmt.Sprintf("interfaceId: %d }", k.Ingress.InterfaceId) + } else if k.Ingress.Type == IPv4Range || k.Ingress.Type == IPv6Range { + base += fmt.Sprintf("ip: %s, prefix: %d }", k.Ingress.IP, k.Ingress.Prefix) + } else if k.Ingress.Type == Wildcard { + base += "wildcard }" + } + + base += fmt.Sprintf("} egress : { type: %s ", k.Egress.Type) + if k.Egress.Type == Interface { + base += fmt.Sprintf("interfaceId: %d } ", k.Egress.InterfaceId) + } else if k.Egress.Type == IPv4Range || k.Egress.Type == IPv6Range { + base += fmt.Sprintf("ip: %s, prefix: %d } ", k.Egress.IP, k.Egress.Prefix) + } else if k.Ingress.Type == Wildcard { + base += "wildcard }" + } + base += " supports: [" + supported := d.SupportedIndicesMap[k] + sort.Slice(supported, func(i int, j int) bool { + return supported[i] < supported[j] + }) + for _, z := range supported { + base += fmt.Sprintf("%d, ", z) + } + base += "] } " + } + return base +} + +func (d *Detached) Hash() []byte { + h := sha256.New() + for _, k := range d.IndexIdentiferMap.SortedKeys() { + _ = binary.Write(h, binary.BigEndian, k) + _ = binary.Write(h, binary.BigEndian, d.IndexIdentiferMap[k].IsLocal) + _ = binary.Write(h, binary.BigEndian, d.IndexIdentiferMap[k].Identifier) + } + for _, k := range d.SupportedIndicesMap.SortedKeys() { + _ = binary.Write(h, binary.BigEndian, k.Ingress.Type) + if k.Ingress.Type == Interface { + _ = binary.Write(h, binary.BigEndian, k.Ingress.InterfaceId) + } else if k.Ingress.Type == IPv4Range || k.Ingress.Type == IPv6Range { + _ = binary.Write(h, binary.BigEndian, k.Ingress.Prefix) + _ = binary.Write(h, binary.BigEndian, k.Ingress.IP) + } + + _ = binary.Write(h, binary.BigEndian, k.Egress.Type) + if k.Egress.Type == Interface { + _ = binary.Write(h, binary.BigEndian, k.Egress.InterfaceId) + } else if k.Egress.Type == IPv4Range || k.Egress.Type == IPv6Range { + _ = binary.Write(h, binary.BigEndian, k.Egress.Prefix) + _ = binary.Write(h, binary.BigEndian, k.Egress.IP) + } + supported := d.SupportedIndicesMap[k] + sort.Slice(supported, func(i int, j int) bool { + return supported[i] < supported[j] + }) + _ = binary.Write(h, binary.BigEndian, supported) + } + return h.Sum(nil)[0:digest.DigestLength] +} diff --git a/pkg/segment/extensions/fabrid/fabrid_test.go b/pkg/segment/extensions/fabrid/fabrid_test.go new file mode 100644 index 0000000000..a490b741e8 --- /dev/null +++ b/pkg/segment/extensions/fabrid/fabrid_test.go @@ -0,0 +1,598 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabrid + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" +) + +func TestSupportedIndicesSortedKeys(t *testing.T) { + connectionPairs := []ConnectionPair{ + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 25, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 25, + }, + }, + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 31, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 28, + }, + }, + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 11, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 25, + }, + }, + { + Ingress: ConnectionPoint{ + Type: IPv4Range, + Prefix: 24, + IP: "192.168.2.100", + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 2, + }, + }, + { + Ingress: ConnectionPoint{ + Type: IPv4Range, + Prefix: 24, + IP: "192.168.2.101", + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 2, + }, + }, + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 2, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + Prefix: 24, + IP: "192.168.2.101", + }, + }, + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 2, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + Prefix: 24, + IP: "192.168.2.101", + }, + }, + { + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 3, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + Prefix: 24, + IP: "192.168.2.101", + }, + }, + } + tests := map[string]struct { + Input SupportedIndicesMap + Expected []ConnectionPair + }{ + "base": { + Input: SupportedIndicesMap{ + connectionPairs[0]: []uint8{0}, + connectionPairs[1]: []uint8{1}, + connectionPairs[2]: []uint8{2}, + connectionPairs[3]: []uint8{3}, + connectionPairs[4]: []uint8{4}, + connectionPairs[5]: []uint8{5}, + connectionPairs[6]: []uint8{5}, // 6 is a duplicate of 5. + connectionPairs[7]: []uint8{7}, + }, + }, + "reversed": { + Input: SupportedIndicesMap{ + connectionPairs[7]: []uint8{7}, + connectionPairs[6]: []uint8{5}, // 6 is a duplicate of 5. + connectionPairs[5]: []uint8{5}, + connectionPairs[4]: []uint8{4}, + connectionPairs[3]: []uint8{3}, + connectionPairs[2]: []uint8{2}, + connectionPairs[1]: []uint8{1}, + connectionPairs[0]: []uint8{0}, + }, + }, + "random": { + Input: SupportedIndicesMap{ + connectionPairs[4]: []uint8{4}, + connectionPairs[2]: []uint8{2}, + connectionPairs[6]: []uint8{5}, // 6 is a duplicate of 5. + connectionPairs[1]: []uint8{1}, + connectionPairs[3]: []uint8{3}, + connectionPairs[7]: []uint8{7}, + connectionPairs[0]: []uint8{0}, + connectionPairs[5]: []uint8{5}, + }, + }, + "random-duplicates": { + Input: SupportedIndicesMap{ + connectionPairs[2]: []uint8{2}, + connectionPairs[4]: []uint8{4}, + connectionPairs[2]: []uint8{2}, + connectionPairs[3]: []uint8{3}, + connectionPairs[6]: []uint8{5}, // 6 is a duplicate of 5. + connectionPairs[1]: []uint8{1}, + connectionPairs[3]: []uint8{3}, + connectionPairs[7]: []uint8{7}, + connectionPairs[3]: []uint8{3}, + connectionPairs[0]: []uint8{0}, + connectionPairs[5]: []uint8{5}, + }, + }, + "random-duplicates-copy": { + Input: SupportedIndicesMap{ + connectionPairs[7]: []uint8{7}, + connectionPairs[4]: []uint8{4}, + connectionPairs[2]: []uint8{2}, + connectionPairs[3]: []uint8{3}, + connectionPairs[6]: []uint8{5}, // 6 is a duplicate of 5. + connectionPairs[0]: []uint8{0}, + connectionPairs[2]: []uint8{2}, + connectionPairs[1]: []uint8{1}, + connectionPairs[5]: []uint8{5}, + connectionPairs[3]: []uint8{3}, + connectionPairs[5]: []uint8{5}, + connectionPairs[3]: []uint8{3}, + }, + }, + } + input := tests["base"].Input + baseSorted := input.SortedKeys() + baseOrder := make([]uint8, 0, len(tests["base"].Input)) + for _, connectionPair := range baseSorted { + fmt.Println(tests["base"].Input[connectionPair][0]) + baseOrder = append(baseOrder, tests["base"].Input[connectionPair][0]) + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + order := make([]uint8, 0, len(tc.Input)) + for _, connectionPair := range tc.Input.SortedKeys() { + order = append(order, tc.Input[connectionPair][0]) + } + assert.Equal(t, baseOrder, order) + }) + } +} + +func TestConnectionPointFromString(t *testing.T) { + type TestCase struct { + IP string + Prefix uint32 + Type ConnectionPointType + } + tests := map[string]struct { + Eq1 TestCase + Eq2 TestCase + }{ + "ipv4": {TestCase{ + IP: "192.168.2.101", + Prefix: 24, + Type: IPv4Range, + }, TestCase{ + IP: "192.168.2.100", + Prefix: 24, + Type: IPv4Range, + }}, + "ipv4-2": {TestCase{ + IP: "192.168.2.101", + Prefix: 24, + Type: IPv4Range, + }, TestCase{ + IP: "192.168.2.100", + Prefix: 24, + Type: IPv4Range, + }}, + "ipv4-3": {TestCase{ + IP: "192.168.3.155", + Prefix: 16, + Type: IPv4Range, + }, TestCase{ + IP: "192.168.2.100", + Prefix: 16, + Type: IPv4Range, + }}, + "ipv4-4": {TestCase{ + IP: "192.168.3.101", + Prefix: 2, + Type: IPv4Range, + }, TestCase{ + IP: "192.168.3.102", + Prefix: 2, + Type: IPv4Range, + }}, + "ipv6-1": {TestCase{ + IP: "2001:0db8:85a3::8a2e:0370:7334", + Prefix: 1, + Type: IPv6Range, + }, TestCase{ + IP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + Prefix: 1, + Type: IPv6Range, + }}, + "ipv6-2": {TestCase{ + IP: "2001:0db8:85a3::8a2e:0370:7338", + Prefix: 24, + Type: IPv6Range, + }, TestCase{ + IP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + Prefix: 24, + Type: IPv6Range, + }}, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, IPConnectionPointFromString(tc.Eq1.IP, tc.Eq1.Prefix, tc.Eq1.Type).IP, + IPConnectionPointFromString(tc.Eq2.IP, tc.Eq2.Prefix, tc.Eq2.Type).IP) + }) + } +} + +func TestDetachedToFromPB(t *testing.T) { + tests := map[string]struct { + Expected *Detached + Input *experimental.FABRIDDetachedExtension + }{ + "nil": {}, + "index-identifiers only": { + Expected: &Detached{ + SupportedIndicesMap: SupportedIndicesMap{}, + IndexIdentiferMap: IndexIdentifierMap{ + 2: &PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + }, + Input: &experimental.FABRIDDetachedExtension{Maps: &experimental. + FABRIDDetachableMaps{ + IndexIdentifierMap: map[uint32]*experimental.FABRIDPolicyIdentifier{ + 2: { + PolicyIsLocal: false, + PolicyIdentifier: 22, + }, + 8: { + PolicyIsLocal: true, + PolicyIdentifier: 1, + }, + 15: { + PolicyIsLocal: false, + PolicyIdentifier: 50, + }, + }, + }}, + }, + "index-identifiers and supported indices": { + Expected: &Detached{ + SupportedIndicesMap: SupportedIndicesMap{ + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 6, + }, + }: []uint8{2, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 9, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.55.0", + Prefix: 24, + }, + }: []uint8{2, 15}, + }, + IndexIdentiferMap: IndexIdentifierMap{ + 2: &PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + }, + Input: &experimental.FABRIDDetachedExtension{Maps: &experimental. + FABRIDDetachableMaps{ + SupportedIndicesMap: []*experimental.FABRIDIndexMapEntry{ + { + IePair: &experimental.FABRIDIngressEgressPair{ + Ingress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE, + Interface: 9, + }, + Egress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV4_RANGE, + IpAddress: []byte{192, 168, 55, 0}, + IpPrefix: 24, + }, + }, + SupportedPolicyIndices: []uint32{2, 15}, + }, { + IePair: &experimental.FABRIDIngressEgressPair{ + Ingress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE, + Interface: 5, + }, + Egress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE, + Interface: 6, + }, + }, + SupportedPolicyIndices: []uint32{2, 15}, + }, { + IePair: &experimental.FABRIDIngressEgressPair{ + Ingress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_IPV4_RANGE, + IpAddress: []byte{192, 168, 2, 0}, + IpPrefix: 24, + }, + Egress: &experimental.FABRIDConnectionPoint{ + Type: experimental. + FABRIDConnectionType_FABRID_CONNECTION_TYPE_INTERFACE, + Interface: 5, + }, + }, + SupportedPolicyIndices: []uint32{2, 8, 15}, + }, + }, + IndexIdentifierMap: map[uint32]*experimental.FABRIDPolicyIdentifier{ + 2: { + PolicyIsLocal: false, + PolicyIdentifier: 22, + }, + 8: { + PolicyIsLocal: true, + PolicyIdentifier: 1, + }, + 15: { + PolicyIsLocal: false, + PolicyIdentifier: 50, + }, + }, + }}, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tc.Expected, DetachedFromPB(tc.Input)) + assert.Equal(t, tc.Expected, DetachedFromPB(DetachedToPB(tc.Expected))) + }) + } + +} +func TestHash(t *testing.T) { + eq1 := &Detached{ + SupportedIndicesMap: SupportedIndicesMap{ + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 6, + }, + }: []uint8{2, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 9, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.55.0", + Prefix: 24, + }, + }: []uint8{2, 15}, + }, + IndexIdentiferMap: IndexIdentifierMap{ + 2: &PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + } + eq2 := &Detached{ + SupportedIndicesMap: SupportedIndicesMap{ + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 9, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.55.0", + Prefix: 24, + }, + }: []uint8{15, 2}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 6, + }, + }: []uint8{15, 2}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + }: []uint8{15, 8, 2}, + }, + IndexIdentiferMap: IndexIdentifierMap{ + 15: &PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + 8: &PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 2: &PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + }, + } + eq3 := &Detached{ + SupportedIndicesMap: SupportedIndicesMap{ + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 9, + }, + Egress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.55.0", + Prefix: 24, + }, + }: []uint8{2, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 6, + }, + }: []uint8{2, 15}, + ConnectionPair{ + Ingress: ConnectionPoint{ + Type: IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: ConnectionPoint{ + Type: Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 1}, // Difference to eq2. + }, + IndexIdentiferMap: IndexIdentifierMap{ + 15: &PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + 8: &PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 2: &PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + }, + } + assert.Equal(t, eq1.Hash(), eq2.Hash()) + assert.NotEqual(t, eq1.Hash(), eq3.Hash()) +} diff --git a/pkg/segment/extensions_test.go b/pkg/segment/extensions_test.go index 48b10a4651..d1f3d15549 100644 --- a/pkg/segment/extensions_test.go +++ b/pkg/segment/extensions_test.go @@ -24,10 +24,14 @@ import ( func TestDecodeEncodeEpicDigest(t *testing.T) { h := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} + h2 := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} dig := &digest.Extension{ Epic: digest.Digest{ Digest: h, }, + Fabrid: digest.Digest{ + Digest: h2, + }, } ext := Extensions{ Digests: dig, diff --git a/pkg/segment/unsigned.go b/pkg/segment/unsigned.go index 79c67c7860..137284904a 100644 --- a/pkg/segment/unsigned.go +++ b/pkg/segment/unsigned.go @@ -15,15 +15,22 @@ package segment import ( + "bytes" + "encoding/hex" + "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" "github.com/scionproto/scion/pkg/segment/extensions/epic" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" ) type UnsignedExtensions struct { // EpicDetached contains the detachable epic authenticators. It is nil // if it was detached (or never added). EpicDetached *epic.Detached + // FabridDetached contains the detachable fabrid maps. It is nil if it was detached + FabridDetached *fabrid.Detached } func UnsignedExtensionsFromPB(ue *cppb.PathSegmentUnsignedExtensions) UnsignedExtensions { @@ -31,16 +38,30 @@ func UnsignedExtensionsFromPB(ue *cppb.PathSegmentUnsignedExtensions) UnsignedEx return UnsignedExtensions{} } return UnsignedExtensions{ - EpicDetached: epic.DetachedFromPB(ue.Epic), + EpicDetached: epic.DetachedFromPB(ue.Epic), + FabridDetached: fabrid.DetachedFromPB(ue.Fabrid), } } func UnsignedExtensionsToPB(ue UnsignedExtensions) *cppb.PathSegmentUnsignedExtensions { + var e *experimental.EPICDetachedExtension + var f *experimental.FABRIDDetachedExtension + if ue.EpicDetached == nil { - return nil + e = nil + } else { + e = epic.DetachedToPB(ue.EpicDetached) } + + if ue.FabridDetached == nil { + f = nil + } else { + f = fabrid.DetachedToPB(ue.FabridDetached) + } + return &cppb.PathSegmentUnsignedExtensions{ - Epic: epic.DetachedToPB(ue.EpicDetached), + Epic: e, + Fabrid: f, } } @@ -71,5 +92,27 @@ func checkUnsignedExtensions(ue *UnsignedExtensions, e *Extensions) error { return err } } + + if ue.FabridDetached != nil { + hasSupportedIndices := len(ue.FabridDetached.SupportedIndicesMap) > 0 + hasIndexIdentifiers := len(ue.FabridDetached.IndexIdentiferMap) > 0 + fabridDigest := e.Digests != nil && len(e.Digests.Fabrid.Digest) != 0 + if hasSupportedIndices && !hasIndexIdentifiers { + // An AS may announce index->identifiers that are not used in the supported indices map. + //However, announcing supported policy indices without specifying the identifiers is + //invalid. + return serrors.New("fabrid maps are malformed") + } + + if fabridDigest { + if digest := ue.FabridDetached.Hash(); !bytes.Equal(e.Digests.Fabrid.Digest, digest) { + return serrors.New("fabrid digest validation failed", + "calculated", hex.EncodeToString(e.Digests.Fabrid.Digest), + "stored", hex.EncodeToString(digest)) + } + } else { + return serrors.New("fabrid maps present, but hash is not") + } + } return nil } diff --git a/pkg/segment/unsigned_test.go b/pkg/segment/unsigned_test.go index 9d67a63466..c53c9ed670 100644 --- a/pkg/segment/unsigned_test.go +++ b/pkg/segment/unsigned_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/scionproto/scion/pkg/segment/extensions/epic" + "github.com/scionproto/scion/pkg/segment/extensions/fabrid" ) func TestDecodeEncode(t *testing.T) { @@ -33,9 +34,24 @@ func TestDecodeEncode(t *testing.T) { AuthHopEntry: hop, AuthPeerEntries: peers, } + fd := &fabrid.Detached{ + SupportedIndicesMap: fabrid.SupportedIndicesMap{ + fabrid.ConnectionPair{ + Ingress: fabrid.ConnectionPoint{ + Type: fabrid.IPv4Range, + IP: "192.168.0.0", + Prefix: 22, + }, + Egress: fabrid.ConnectionPoint{ + Type: fabrid.Interface, + InterfaceId: 44, + }}: []uint8{1}}, + IndexIdentiferMap: fabrid.IndexIdentifierMap{}, + } ue := UnsignedExtensions{ - EpicDetached: ed, + EpicDetached: ed, + FabridDetached: fd, } ue2 := UnsignedExtensionsFromPB( UnsignedExtensionsToPB(ue)) diff --git a/private/mgmtapi/segments/api/testdata/segments-blob-by-id.txt b/private/mgmtapi/segments/api/testdata/segments-blob-by-id.txt index 06f02b0fb4..e11f16775b 100644 --- a/private/mgmtapi/segments/api/testdata/segments-blob-by-id.txt +++ b/private/mgmtapi/segments/api/testdata/segments-blob-by-id.txt @@ -1,6 +1,6 @@ -----BEGIN PATH SEGMENT----- -CgkI8eCagAYQuQoSLwotCiAKBggDEgJpZBIWCJCCgICA4H8aDAoKEAEiBhERERER -ERIJc2lnbmF0dXJlEjEKLwoiCgYIAxICaWQSGAiRgoCAgOB/Gg4KDAgBEAIiBhIS -EhISEhIJc2lnbmF0dXJlEi8KLQogCgYIAxICaWQSFgiTgoCAgOB/GgwKCggCIgYT -ExMTExMSCXNpZ25hdHVyZQ== +CgkI8eCagAYQuQoSMQotCiAKBggDEgJpZBIWCJCCgICA4H8aDAoKEAEiBhERERER +ERIJc2lnbmF0dXJlEgASMwovCiIKBggDEgJpZBIYCJGCgICA4H8aDgoMCAEQAiIG +EhISEhISEglzaWduYXR1cmUSABIxCi0KIAoGCAMSAmlkEhYIk4KAgIDgfxoMCgoI +AiIGExMTExMTEglzaWduYXR1cmUSAA== -----END PATH SEGMENT----- diff --git a/proto/control_plane/experimental/v1/BUILD.bazel b/proto/control_plane/experimental/v1/BUILD.bazel index d5ef433680..0ce5267386 100644 --- a/proto/control_plane/experimental/v1/BUILD.bazel +++ b/proto/control_plane/experimental/v1/BUILD.bazel @@ -2,7 +2,11 @@ load("@rules_proto//proto:defs.bzl", "proto_library") proto_library( name = "experimental", - srcs = ["seg_detached_extensions.proto"], + srcs = [ + "fabrid.proto", + "fabrid_extensions.proto", + "seg_detached_extensions.proto", + ], visibility = ["//visibility:public"], deps = [ "//proto/crypto/v1:crypto", diff --git a/proto/control_plane/experimental/v1/fabrid.proto b/proto/control_plane/experimental/v1/fabrid.proto new file mode 100644 index 0000000000..daa98978ad --- /dev/null +++ b/proto/control_plane/experimental/v1/fabrid.proto @@ -0,0 +1,121 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option go_package = "github.com/scionproto/scion/pkg/proto/control_plane/experimental"; + +package proto.control_plane.experimental.v1; + +import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; + +service FABRIDInterService{ + // Gets the I-map for a local AS, mapping interfaces to supported policy indices + rpc SupportedIndicesMap(SupportedIndicesMapRequest) returns (SupportedIndicesMapResponse) {} + // Gets the D-Map for a local AS, mapping policy indices to policy identifiers + rpc IndexIdentifierMap(IndexIdentifierMapRequest) returns (IndexIdentifierMapResponse) {} +// todo(jvanbommel): Q signatures on the maps ? (hash in pcb?) + // Gets a string description for a local policy + rpc LocalPolicyDescription(LocalPolicyDescriptionRequest) returns + (LocalPolicyDescriptionResponse) {} +} + +service FABRIDIntraService { + // Used by a host inside the AS to request a policy description for another AS. The control + // service will request the policy description from the remote AS if it is unknown to the + // control service. + rpc RemotePolicyDescription(RemotePolicyDescriptionRequest) returns + (RemotePolicyDescriptionResponse) {} + + // Used by border routers in the AS to request the mapping of supported policy indices to local MPLS labels + rpc MPLSMap(MPLSMapRequest) returns (MPLSMapResponse) {} +} + +message MPLSIPArray { + // An entry of the MPLS Map, represented as an array to maintain the order. + repeated MPLSIP entry = 1; +} + +message MPLSIP { + // The MPLS label to apply to a packet that is sent to a specific policy index that has a + // specific (AS-local) destination IP + uint32 mpls_label = 1; + // Specifies the IP which the packet has to match in addition to matching the specific policy + // index, before applying the MPLS Label + bytes ip = 2; + // In order to support more than one IP per MPLSIP mapping, a prefix is used to denote a range + // of IP addresses + uint32 prefix = 3; +} + +message MPLSMapRequest { + // The MPLS map is only updated if the hash of the map already saved at the router is mismatched + // with the current active MPLS map. This field is optional, if empty, the active map is + // always sent in response. + bytes hash = 1; +} + +message MPLSMapResponse { + // If true the endpoint should update its MPLS label map, if false it is already up to date + bool update = 1; + // The hash of the current active MPLS map on the control service + bytes hash = 2; + // The mapping for policy indices (uint8) to MPLS labels (uint32) that is used for + // connections where the egress is an interface. + map mpls_interface_policies_map = 3; + // The mapping for policies to a specific MPLS label in cases where a packet is forwarded + // intra-AS to a specified IP range: + map mpls_ip_map = 4; +} + +message SupportedIndicesMapRequest { } + +message SupportedIndicesMapResponse { + // Maps a pair of ingress and egress points (i.e. interfaces, or ip ranges) + // to a given local 8-bit policy index. The policy index is used in the + // dataplane and can be mapped to the corresponding policy identifier using the D-map. + repeated FABRIDIndexMapEntry supported_indices_map = 1; +} + +message IndexIdentifierMapRequest { } + +message IndexIdentifierMapResponse { + // An AS-local policy index is mapped to a local or global policy identifier + // using the index_identifier_map (D-map). + map index_identifier_map = 1; +} +message RemotePolicyDescriptionRequest { + // The identifier for the policy + uint32 policy_identifier = 1; + // Remote ISD-AS of the non-global policy identifier + uint64 isd_as = 2; +} + +message RemotePolicyDescriptionResponse { + // A description of the local policy. + string description = 1; +} + +message LocalPolicyDescriptionRequest { + // The identifier for the policy + uint32 policy_identifier = 1; +} + +message LocalPolicyDescriptionResponse { + // A description of the local policy. + string description = 1; +} + + + diff --git a/proto/control_plane/experimental/v1/fabrid_extensions.proto b/proto/control_plane/experimental/v1/fabrid_extensions.proto new file mode 100644 index 0000000000..fe5602d9bb --- /dev/null +++ b/proto/control_plane/experimental/v1/fabrid_extensions.proto @@ -0,0 +1,78 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option go_package = "github.com/scionproto/scion/pkg/proto/control_plane/experimental"; + +package proto.control_plane.experimental.v1; + +message FABRIDDetachableMaps { + // Maps a pair of ingress and egress points (i.e. interfaces, or ip ranges) + // to a given local 16-bit policy index. The policy index is used in the + // dataplane + repeated FABRIDIndexMapEntry supported_indices_map = 1; + // The policy index is mapped to a policy identifier using the + // index_identifier_map (D-map) + map index_identifier_map = 2; +} + +message FABRIDPolicyIdentifier { + // Flag to specify local policies + bool policy_is_local = 1; + // The identifier for the policy + uint32 policy_identifier = 2; +} + +message FABRIDIndexMapEntry { + // The ingress and egress connection point pair that supports a set of + // policies + FABRIDIngressEgressPair ie_pair = 1; + // The indices of the policies that are supported by the ingress and + // egress pair. + repeated uint32 supported_policy_indices = 2; +} + +enum FABRIDConnectionType { + // Unspecified connection type + FABRID_CONNECTION_TYPE_UNSPECIFIED = 0; + // IPv4 Range + FABRID_CONNECTION_TYPE_IPV4_RANGE = 1; + // IPv6 Range + FABRID_CONNECTION_TYPE_IPV6_RANGE = 2; + // AS egress or ingress interface + FABRID_CONNECTION_TYPE_INTERFACE = 3; + // Wildcard, policy from any interface + FABRID_CONNECTION_TYPE_WILDCARD = 4; +} +message FABRIDIngressEgressPair { + // Specifies the IP range or interface traffic is coming from, in order to satisfy + // a given policy. + FABRIDConnectionPoint ingress = 1; + // Specifies the destination of traffic which satisfies the policy. + FABRIDConnectionPoint egress = 2; +} + +message FABRIDConnectionPoint { + // The type of the ingress/egress point, which can either be an + // interface, or an IP Range. + FABRIDConnectionType type = 1; + // When the type is IPv4 or IPv6 range, specify the IP and subnet mask for the range here. + bytes ip_address = 2; + // IP prefix length, as in CIDR notation. + uint32 ip_prefix = 3; + // The interface for the interface type. + uint64 interface = 4; + +} diff --git a/proto/control_plane/experimental/v1/seg_detached_extensions.proto b/proto/control_plane/experimental/v1/seg_detached_extensions.proto index 0d26c5fb16..bba43d9e92 100644 --- a/proto/control_plane/experimental/v1/seg_detached_extensions.proto +++ b/proto/control_plane/experimental/v1/seg_detached_extensions.proto @@ -18,9 +18,18 @@ option go_package = "github.com/scionproto/scion/pkg/proto/control_plane/experim package proto.control_plane.experimental.v1; +import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; + + message EPICDetachedExtension { // Remaining bytes of the full MAC in the hop entry. bytes auth_hop_entry = 1; // Remaining bytes of the full MAC in the peer entries. repeated bytes auth_peer_entries = 2; } + + +message FABRIDDetachedExtension { + // The I and D-map of FABRID + proto.control_plane.experimental.v1.FABRIDDetachableMaps maps = 1; +} diff --git a/proto/control_plane/v1/seg_extensions.proto b/proto/control_plane/v1/seg_extensions.proto index fb50e4f0c1..a4984089da 100644 --- a/proto/control_plane/v1/seg_extensions.proto +++ b/proto/control_plane/v1/seg_extensions.proto @@ -111,7 +111,9 @@ message BandwidthInfo { // all paths (cross-over, shortcut, peering) based on this ASEntry. // All values are in grams of CO2 emitted per terabyte of traffic. message CarbonIntensityInfo { + // The intra-AS carbon intensity info map intra = 1; + // The inter-AS carbon intensity info map inter = 2; } @@ -156,9 +158,20 @@ message DigestExtension { // total number of authenticators used in the hash. // Digest epic = 1000; + // The digest of the detached FABRID extension. The hash input is defined as follows: + // + // input = I-map || D-Map + // + // Here, 'I-map' is the mapping from connection points (e.g. interfaces or ip ranges) + // to the supported policy indices. + // Conversely, 'D-map' maps policy indices to local or global policy identifiers. + Digest fabrid = 1001; } + message PathSegmentUnsignedExtensions { // Optional EPIC extension. proto.control_plane.experimental.v1.EPICDetachedExtension epic = 1000; + // Optional FABRID extension + proto.control_plane.experimental.v1.FABRIDDetachedExtension fabrid = 1001; } diff --git a/tools/topogen.py b/tools/topogen.py index 8bd1a349b2..937fad04aa 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -51,6 +51,8 @@ def add_arguments(parser): parser.add_argument('--sig', action='store_true', help='Generate a SIG per AS (only available with -d, the SIG image needs\ to be built manually e.g. when running acceptance tests)') + parser.add_argument('--fabrid', action='store_true', + help='Enables FABRID and DRKey on all CSes, BRs and SDs') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ e.g. foo,bar enables foo and bar feature.') return parser diff --git a/tools/topology/go.py b/tools/topology/go.py index 72a1902097..72d53639e4 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -129,6 +129,12 @@ def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): 'api': self._api_entry(infra_elem, CS_PROM_PORT+700), 'features': translate_features(self.args.features), } + if self.args.fabrid: + fabrid_path = os.path.join(config_dir, 'fabrid-policies') + raw_entry['fabrid'] = { + 'enabled': True, + 'path': fabrid_path, + } if ca: raw_entry['ca'] = {'mode': 'in-process'} return raw_entry From dd3236293f63ebcbde94406d7d57a1a5a458f570 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 12:27:10 +0200 Subject: [PATCH 02/26] Daemon FABRID support - SD adds FABRID policies to paths --- daemon/internal/servers/BUILD.bazel | 2 + daemon/internal/servers/grpc.go | 27 +- pkg/daemon/BUILD.bazel | 1 + pkg/daemon/grpc.go | 20 + pkg/proto/daemon/BUILD.bazel | 1 + pkg/proto/daemon/daemon.pb.go | 1010 ++++++++++++++++----------- pkg/snet/BUILD.bazel | 1 + pkg/snet/path.go | 16 +- proto/daemon/v1/BUILD.bazel | 1 + proto/daemon/v1/daemon.proto | 17 + 10 files changed, 676 insertions(+), 420 deletions(-) diff --git a/daemon/internal/servers/BUILD.bazel b/daemon/internal/servers/BUILD.bazel index 9bf6640324..a5d3a6627e 100644 --- a/daemon/internal/servers/BUILD.bazel +++ b/daemon/internal/servers/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "//daemon/fetcher:go_default_library", "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", + "//pkg/experimental/fabrid:go_default_library", "//pkg/log:go_default_library", "//pkg/metrics:go_default_library", "//pkg/private/common:go_default_library", @@ -21,6 +22,7 @@ go_library( "//pkg/private/prom:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", "//pkg/proto/daemon:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/path:go_default_library", diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index 8f1d929b5f..e69f0f495a 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -30,6 +30,7 @@ import ( "github.com/scionproto/scion/daemon/fetcher" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/ctrl/path_mgmt" @@ -37,6 +38,7 @@ import ( "github.com/scionproto/scion/pkg/private/prom" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" pb_daemon "github.com/scionproto/scion/pkg/proto/daemon" sdpb "github.com/scionproto/scion/pkg/proto/daemon" "github.com/scionproto/scion/pkg/snet" @@ -165,7 +167,10 @@ func pathToPB(path snet.Path) *sdpb.Path { if nextHop := path.UnderlayNextHop(); nextHop != nil { nextHopStr = nextHop.String() } - + fabridPolicies := make([]*sdpb.FabridPolicies, len(meta.FabridPolicies)) + for i, v := range meta.FabridPolicies { + fabridPolicies[i] = fabridPoliciesToPB(v) + } epicAuths := &sdpb.EpicAuths{ AuthPhvf: append([]byte(nil), meta.EpicAuths.AuthPHVF...), AuthLhvf: append([]byte(nil), meta.EpicAuths.AuthLHVF...), @@ -187,10 +192,30 @@ func pathToPB(path snet.Path) *sdpb.Path { InternalHops: meta.InternalHops, Notes: meta.Notes, EpicAuths: epicAuths, + FabridEnabled: meta.FabridEnabled, + FabridPolicies: fabridPolicies, } +} +func fabridPolicyToPB(fp *fabrid.Policy) *sdpb.FabridPolicy { + return &sdpb.FabridPolicy{ + PolicyIdentifier: &experimental.FABRIDPolicyIdentifier{ + PolicyIsLocal: fp.IsLocal, + PolicyIdentifier: fp.Identifier, + }, + PolicyIndex: uint32(fp.Index), + } } +func fabridPoliciesToPB(fpList []*fabrid.Policy) *sdpb.FabridPolicies { + pbPolicies := make([]*sdpb.FabridPolicy, len(fpList)) + for i, fp := range fpList { + pbPolicies[i] = fabridPolicyToPB(fp) + } + return &sdpb.FabridPolicies{ + Policies: pbPolicies, + } +} func linkTypeToPB(lt snet.LinkType) sdpb.LinkType { switch lt { case snet.LinkTypeDirect: diff --git a/pkg/daemon/BUILD.bazel b/pkg/daemon/BUILD.bazel index 8a8ca23be8..cb0fe57cab 100644 --- a/pkg/daemon/BUILD.bazel +++ b/pkg/daemon/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/daemon/internal/metrics:go_default_library", "//pkg/drkey:go_default_library", + "//pkg/experimental/fabrid:go_default_library", "//pkg/grpc:go_default_library", "//pkg/metrics:go_default_library", "//pkg/private/common:go_default_library", diff --git a/pkg/daemon/grpc.go b/pkg/daemon/grpc.go index ec4e16fdb0..7ac09f3d9a 100644 --- a/pkg/daemon/grpc.go +++ b/pkg/daemon/grpc.go @@ -26,6 +26,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" libgrpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/ctrl/path_mgmt" @@ -281,6 +282,11 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { linkType[i] = linkTypeFromPB(v) } + policyIdentifiers := make([][]*fabrid.Policy, len(p.FabridPolicies)) + for i, v := range p.FabridPolicies { + policyIdentifiers[i] = fabridPoliciesFromPB(v) + } + res := path.Path{ Src: interfaces[0].IA, Dst: dst, @@ -299,6 +305,8 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { LinkType: linkType, InternalHops: p.InternalHops, Notes: p.Notes, + FabridEnabled: p.FabridEnabled, + FabridPolicies: policyIdentifiers, }, } @@ -312,6 +320,18 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { return res, nil } +func fabridPoliciesFromPB(fpList *sdpb.FabridPolicies) []*fabrid.Policy { + pbPolicies := make([]*fabrid.Policy, len(fpList.Policies)) + for i, fp := range fpList.Policies { + pbPolicies[i] = &fabrid.Policy{ + IsLocal: fp.PolicyIdentifier.PolicyIsLocal, + Identifier: fp.PolicyIdentifier.PolicyIdentifier, + Index: fabrid.PolicyID(fp.PolicyIndex), + } + } + return pbPolicies +} + func linkTypeFromPB(lt sdpb.LinkType) snet.LinkType { switch lt { case sdpb.LinkType_LINK_TYPE_DIRECT: diff --git a/pkg/proto/daemon/BUILD.bazel b/pkg/proto/daemon/BUILD.bazel index 97a549ec9c..d4ee98c55e 100644 --- a/pkg/proto/daemon/BUILD.bazel +++ b/pkg/proto/daemon/BUILD.bazel @@ -7,6 +7,7 @@ go_proto_library( proto = "//proto/daemon/v1:daemon", visibility = ["//visibility:public"], deps = [ + "//pkg/proto/control_plane/experimental:go_default_library", "//pkg/proto/drkey:go_default_library", ], ) diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index 71f10bf2b5..0fa64eb59d 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -8,6 +8,7 @@ package daemon import ( context "context" + experimental "github.com/scionproto/scion/pkg/proto/control_plane/experimental" drkey "github.com/scionproto/scion/pkg/proto/drkey" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -216,6 +217,8 @@ type Path struct { Notes []string `protobuf:"bytes,11,rep,name=notes,proto3" json:"notes,omitempty"` EpicAuths *EpicAuths `protobuf:"bytes,12,opt,name=epic_auths,json=epicAuths,proto3" json:"epic_auths,omitempty"` CarbonIntensity []int64 `protobuf:"varint,13,rep,packed,name=carbon_intensity,json=carbonIntensity,proto3" json:"carbon_intensity,omitempty"` + FabridEnabled []bool `protobuf:"varint,14,rep,packed,name=fabrid_enabled,json=fabridEnabled,proto3" json:"fabrid_enabled,omitempty"` + FabridPolicies []*FabridPolicies `protobuf:"bytes,15,rep,name=fabrid_policies,json=fabridPolicies,proto3" json:"fabrid_policies,omitempty"` } func (x *Path) Reset() { @@ -341,6 +344,122 @@ func (x *Path) GetCarbonIntensity() []int64 { return nil } +func (x *Path) GetFabridEnabled() []bool { + if x != nil { + return x.FabridEnabled + } + return nil +} + +func (x *Path) GetFabridPolicies() []*FabridPolicies { + if x != nil { + return x.FabridPolicies + } + return nil +} + +type FabridPolicies struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policies []*FabridPolicy `protobuf:"bytes,1,rep,name=policies,proto3" json:"policies,omitempty"` +} + +func (x *FabridPolicies) Reset() { + *x = FabridPolicies{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridPolicies) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridPolicies) ProtoMessage() {} + +func (x *FabridPolicies) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridPolicies.ProtoReflect.Descriptor instead. +func (*FabridPolicies) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} +} + +func (x *FabridPolicies) GetPolicies() []*FabridPolicy { + if x != nil { + return x.Policies + } + return nil +} + +type FabridPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PolicyIdentifier *experimental.FABRIDPolicyIdentifier `protobuf:"bytes,1,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` + PolicyIndex uint32 `protobuf:"varint,2,opt,name=policy_index,json=policyIndex,proto3" json:"policy_index,omitempty"` +} + +func (x *FabridPolicy) Reset() { + *x = FabridPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridPolicy) ProtoMessage() {} + +func (x *FabridPolicy) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridPolicy.ProtoReflect.Descriptor instead. +func (*FabridPolicy) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{4} +} + +func (x *FabridPolicy) GetPolicyIdentifier() *experimental.FABRIDPolicyIdentifier { + if x != nil { + return x.PolicyIdentifier + } + return nil +} + +func (x *FabridPolicy) GetPolicyIndex() uint32 { + if x != nil { + return x.PolicyIndex + } + return 0 +} + type EpicAuths struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -353,7 +472,7 @@ type EpicAuths struct { func (x *EpicAuths) Reset() { *x = EpicAuths{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -366,7 +485,7 @@ func (x *EpicAuths) String() string { func (*EpicAuths) ProtoMessage() {} func (x *EpicAuths) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -379,7 +498,7 @@ func (x *EpicAuths) ProtoReflect() protoreflect.Message { // Deprecated: Use EpicAuths.ProtoReflect.Descriptor instead. func (*EpicAuths) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} } func (x *EpicAuths) GetAuthPhvf() []byte { @@ -408,7 +527,7 @@ type PathInterface struct { func (x *PathInterface) Reset() { *x = PathInterface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -421,7 +540,7 @@ func (x *PathInterface) String() string { func (*PathInterface) ProtoMessage() {} func (x *PathInterface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -434,7 +553,7 @@ func (x *PathInterface) ProtoReflect() protoreflect.Message { // Deprecated: Use PathInterface.ProtoReflect.Descriptor instead. func (*PathInterface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{4} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} } func (x *PathInterface) GetIsdAs() uint64 { @@ -464,7 +583,7 @@ type GeoCoordinates struct { func (x *GeoCoordinates) Reset() { *x = GeoCoordinates{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -477,7 +596,7 @@ func (x *GeoCoordinates) String() string { func (*GeoCoordinates) ProtoMessage() {} func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -490,7 +609,7 @@ func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoCoordinates.ProtoReflect.Descriptor instead. func (*GeoCoordinates) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} } func (x *GeoCoordinates) GetLatitude() float32 { @@ -525,7 +644,7 @@ type ASRequest struct { func (x *ASRequest) Reset() { *x = ASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -538,7 +657,7 @@ func (x *ASRequest) String() string { func (*ASRequest) ProtoMessage() {} func (x *ASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -551,7 +670,7 @@ func (x *ASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ASRequest.ProtoReflect.Descriptor instead. func (*ASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} } func (x *ASRequest) GetIsdAs() uint64 { @@ -574,7 +693,7 @@ type ASResponse struct { func (x *ASResponse) Reset() { *x = ASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -587,7 +706,7 @@ func (x *ASResponse) String() string { func (*ASResponse) ProtoMessage() {} func (x *ASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -600,7 +719,7 @@ func (x *ASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ASResponse.ProtoReflect.Descriptor instead. func (*ASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} } func (x *ASResponse) GetIsdAs() uint64 { @@ -633,7 +752,7 @@ type InterfacesRequest struct { func (x *InterfacesRequest) Reset() { *x = InterfacesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -646,7 +765,7 @@ func (x *InterfacesRequest) String() string { func (*InterfacesRequest) ProtoMessage() {} func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -659,7 +778,7 @@ func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesRequest.ProtoReflect.Descriptor instead. func (*InterfacesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} } type InterfacesResponse struct { @@ -673,7 +792,7 @@ type InterfacesResponse struct { func (x *InterfacesResponse) Reset() { *x = InterfacesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -686,7 +805,7 @@ func (x *InterfacesResponse) String() string { func (*InterfacesResponse) ProtoMessage() {} func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -699,7 +818,7 @@ func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesResponse.ProtoReflect.Descriptor instead. func (*InterfacesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} } func (x *InterfacesResponse) GetInterfaces() map[uint64]*Interface { @@ -720,7 +839,7 @@ type Interface struct { func (x *Interface) Reset() { *x = Interface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -733,7 +852,7 @@ func (x *Interface) String() string { func (*Interface) ProtoMessage() {} func (x *Interface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -746,7 +865,7 @@ func (x *Interface) ProtoReflect() protoreflect.Message { // Deprecated: Use Interface.ProtoReflect.Descriptor instead. func (*Interface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} } func (x *Interface) GetAddress() *Underlay { @@ -765,7 +884,7 @@ type ServicesRequest struct { func (x *ServicesRequest) Reset() { *x = ServicesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -778,7 +897,7 @@ func (x *ServicesRequest) String() string { func (*ServicesRequest) ProtoMessage() {} func (x *ServicesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -791,7 +910,7 @@ func (x *ServicesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesRequest.ProtoReflect.Descriptor instead. func (*ServicesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} } type ServicesResponse struct { @@ -805,7 +924,7 @@ type ServicesResponse struct { func (x *ServicesResponse) Reset() { *x = ServicesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -818,7 +937,7 @@ func (x *ServicesResponse) String() string { func (*ServicesResponse) ProtoMessage() {} func (x *ServicesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -831,7 +950,7 @@ func (x *ServicesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesResponse.ProtoReflect.Descriptor instead. func (*ServicesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} } func (x *ServicesResponse) GetServices() map[string]*ListService { @@ -852,7 +971,7 @@ type ListService struct { func (x *ListService) Reset() { *x = ListService{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -865,7 +984,7 @@ func (x *ListService) String() string { func (*ListService) ProtoMessage() {} func (x *ListService) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -878,7 +997,7 @@ func (x *ListService) ProtoReflect() protoreflect.Message { // Deprecated: Use ListService.ProtoReflect.Descriptor instead. func (*ListService) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} } func (x *ListService) GetServices() []*Service { @@ -899,7 +1018,7 @@ type Service struct { func (x *Service) Reset() { *x = Service{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -912,7 +1031,7 @@ func (x *Service) String() string { func (*Service) ProtoMessage() {} func (x *Service) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -925,7 +1044,7 @@ func (x *Service) ProtoReflect() protoreflect.Message { // Deprecated: Use Service.ProtoReflect.Descriptor instead. func (*Service) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} } func (x *Service) GetUri() string { @@ -946,7 +1065,7 @@ type Underlay struct { func (x *Underlay) Reset() { *x = Underlay{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -959,7 +1078,7 @@ func (x *Underlay) String() string { func (*Underlay) ProtoMessage() {} func (x *Underlay) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -972,7 +1091,7 @@ func (x *Underlay) ProtoReflect() protoreflect.Message { // Deprecated: Use Underlay.ProtoReflect.Descriptor instead. func (*Underlay) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} } func (x *Underlay) GetAddress() string { @@ -994,7 +1113,7 @@ type NotifyInterfaceDownRequest struct { func (x *NotifyInterfaceDownRequest) Reset() { *x = NotifyInterfaceDownRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1007,7 +1126,7 @@ func (x *NotifyInterfaceDownRequest) String() string { func (*NotifyInterfaceDownRequest) ProtoMessage() {} func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1020,7 +1139,7 @@ func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownRequest.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} } func (x *NotifyInterfaceDownRequest) GetIsdAs() uint64 { @@ -1046,7 +1165,7 @@ type NotifyInterfaceDownResponse struct { func (x *NotifyInterfaceDownResponse) Reset() { *x = NotifyInterfaceDownResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1059,7 +1178,7 @@ func (x *NotifyInterfaceDownResponse) String() string { func (*NotifyInterfaceDownResponse) ProtoMessage() {} func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1072,7 +1191,7 @@ func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownResponse.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} } type PortRangeResponse struct { @@ -1087,7 +1206,7 @@ type PortRangeResponse struct { func (x *PortRangeResponse) Reset() { *x = PortRangeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1100,7 +1219,7 @@ func (x *PortRangeResponse) String() string { func (*PortRangeResponse) ProtoMessage() {} func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1113,7 +1232,7 @@ func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PortRangeResponse.ProtoReflect.Descriptor instead. func (*PortRangeResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} } func (x *PortRangeResponse) GetDispatchedPortStart() uint32 { @@ -1145,7 +1264,7 @@ type DRKeyHostASRequest struct { func (x *DRKeyHostASRequest) Reset() { *x = DRKeyHostASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1158,7 +1277,7 @@ func (x *DRKeyHostASRequest) String() string { func (*DRKeyHostASRequest) ProtoMessage() {} func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1171,7 +1290,7 @@ func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} } func (x *DRKeyHostASRequest) GetValTime() *timestamppb.Timestamp { @@ -1222,7 +1341,7 @@ type DRKeyHostASResponse struct { func (x *DRKeyHostASResponse) Reset() { *x = DRKeyHostASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1235,7 +1354,7 @@ func (x *DRKeyHostASResponse) String() string { func (*DRKeyHostASResponse) ProtoMessage() {} func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1248,7 +1367,7 @@ func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} } func (x *DRKeyHostASResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1287,7 +1406,7 @@ type DRKeyASHostRequest struct { func (x *DRKeyASHostRequest) Reset() { *x = DRKeyASHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1300,7 +1419,7 @@ func (x *DRKeyASHostRequest) String() string { func (*DRKeyASHostRequest) ProtoMessage() {} func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1313,7 +1432,7 @@ func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyASHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} } func (x *DRKeyASHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1364,7 +1483,7 @@ type DRKeyASHostResponse struct { func (x *DRKeyASHostResponse) Reset() { *x = DRKeyASHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1377,7 +1496,7 @@ func (x *DRKeyASHostResponse) String() string { func (*DRKeyASHostResponse) ProtoMessage() {} func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1390,7 +1509,7 @@ func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyASHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} } func (x *DRKeyASHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1430,7 +1549,7 @@ type DRKeyHostHostRequest struct { func (x *DRKeyHostHostRequest) Reset() { *x = DRKeyHostHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1443,7 +1562,7 @@ func (x *DRKeyHostHostRequest) String() string { func (*DRKeyHostHostRequest) ProtoMessage() {} func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1456,7 +1575,7 @@ func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{25} } func (x *DRKeyHostHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1514,7 +1633,7 @@ type DRKeyHostHostResponse struct { func (x *DRKeyHostHostResponse) Reset() { *x = DRKeyHostHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1527,7 +1646,7 @@ func (x *DRKeyHostHostResponse) String() string { func (*DRKeyHostHostResponse) ProtoMessage() {} func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1540,7 +1659,7 @@ func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{26} } func (x *DRKeyHostHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1577,263 +1696,288 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x72, - 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x50, 0x61, - 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x2c, - 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x73, - 0x64, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x22, 0x3c, - 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2b, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xbf, 0x04, 0x0a, - 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, - 0x6d, 0x74, 0x75, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x33, 0x0a, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, 0x61, 0x74, - 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x12, 0x31, 0x0a, 0x03, 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, - 0x52, 0x03, 0x67, 0x65, 0x6f, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, - 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, 0x69, 0x63, - 0x5f, 0x61, 0x75, 0x74, 0x68, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, 0x41, 0x75, - 0x74, 0x68, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x63, - 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x22, 0x45, - 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, - 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, - 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, - 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, - 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, - 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, - 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, - 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, - 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, - 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, - 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, - 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, + 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, + 0x65, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x22, 0x3c, 0x0a, 0x0d, 0x50, + 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, + 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x05, 0x0a, 0x04, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x03, 0x72, 0x61, 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, - 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, - 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, - 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, - 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, - 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, - 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, - 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, - 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, - 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, + 0x61, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x3e, + 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x10, + 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, + 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x07, + 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, + 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, + 0x31, 0x0a, 0x03, 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x03, 0x67, + 0x65, 0x6f, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x09, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, + 0x0d, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, + 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, 0x69, 0x63, 0x5f, 0x61, 0x75, + 0x74, 0x68, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x69, 0x63, + 0x41, 0x75, 0x74, 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, + 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, + 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x66, + 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, + 0x03, 0x28, 0x08, 0x52, 0x0d, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x48, 0x0a, 0x0f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x0e, 0x66, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x0e, + 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x39, + 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, + 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x0c, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x68, 0x0a, 0x11, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, + 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, + 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, + 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, + 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, + 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, + 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, + 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, + 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, + 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, + 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, + 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, + 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, + 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, + 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, + 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, + 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, + 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, + 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, + 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, + 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, + 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, + 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, + 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, + 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, + 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, + 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, + 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, + 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, + 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, + 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, - 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, + 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, + 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, + 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, + 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, + 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, + 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, - 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, - 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, - 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, - 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, - 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, - 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, - 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, - 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, - 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, - 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, - 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, - 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, - 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0x9f, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, - 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, - 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, - 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, - 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, + 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, + 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, + 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, + 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, + 0x03, 0x32, 0x9f, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, + 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, + 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, + 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, + 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, + 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, + 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, + 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, + 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, + 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, + 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1849,91 +1993,97 @@ func file_proto_daemon_v1_daemon_proto_rawDescGZIP() []byte { } var file_proto_daemon_v1_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 29) var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ - (LinkType)(0), // 0: proto.daemon.v1.LinkType - (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest - (*PathsResponse)(nil), // 2: proto.daemon.v1.PathsResponse - (*Path)(nil), // 3: proto.daemon.v1.Path - (*EpicAuths)(nil), // 4: proto.daemon.v1.EpicAuths - (*PathInterface)(nil), // 5: proto.daemon.v1.PathInterface - (*GeoCoordinates)(nil), // 6: proto.daemon.v1.GeoCoordinates - (*ASRequest)(nil), // 7: proto.daemon.v1.ASRequest - (*ASResponse)(nil), // 8: proto.daemon.v1.ASResponse - (*InterfacesRequest)(nil), // 9: proto.daemon.v1.InterfacesRequest - (*InterfacesResponse)(nil), // 10: proto.daemon.v1.InterfacesResponse - (*Interface)(nil), // 11: proto.daemon.v1.Interface - (*ServicesRequest)(nil), // 12: proto.daemon.v1.ServicesRequest - (*ServicesResponse)(nil), // 13: proto.daemon.v1.ServicesResponse - (*ListService)(nil), // 14: proto.daemon.v1.ListService - (*Service)(nil), // 15: proto.daemon.v1.Service - (*Underlay)(nil), // 16: proto.daemon.v1.Underlay - (*NotifyInterfaceDownRequest)(nil), // 17: proto.daemon.v1.NotifyInterfaceDownRequest - (*NotifyInterfaceDownResponse)(nil), // 18: proto.daemon.v1.NotifyInterfaceDownResponse - (*PortRangeResponse)(nil), // 19: proto.daemon.v1.PortRangeResponse - (*DRKeyHostASRequest)(nil), // 20: proto.daemon.v1.DRKeyHostASRequest - (*DRKeyHostASResponse)(nil), // 21: proto.daemon.v1.DRKeyHostASResponse - (*DRKeyASHostRequest)(nil), // 22: proto.daemon.v1.DRKeyASHostRequest - (*DRKeyASHostResponse)(nil), // 23: proto.daemon.v1.DRKeyASHostResponse - (*DRKeyHostHostRequest)(nil), // 24: proto.daemon.v1.DRKeyHostHostRequest - (*DRKeyHostHostResponse)(nil), // 25: proto.daemon.v1.DRKeyHostHostResponse - nil, // 26: proto.daemon.v1.InterfacesResponse.InterfacesEntry - nil, // 27: proto.daemon.v1.ServicesResponse.ServicesEntry - (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 29: google.protobuf.Duration - (drkey.Protocol)(0), // 30: proto.drkey.v1.Protocol - (*emptypb.Empty)(nil), // 31: google.protobuf.Empty + (LinkType)(0), // 0: proto.daemon.v1.LinkType + (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest + (*PathsResponse)(nil), // 2: proto.daemon.v1.PathsResponse + (*Path)(nil), // 3: proto.daemon.v1.Path + (*FabridPolicies)(nil), // 4: proto.daemon.v1.FabridPolicies + (*FabridPolicy)(nil), // 5: proto.daemon.v1.FabridPolicy + (*EpicAuths)(nil), // 6: proto.daemon.v1.EpicAuths + (*PathInterface)(nil), // 7: proto.daemon.v1.PathInterface + (*GeoCoordinates)(nil), // 8: proto.daemon.v1.GeoCoordinates + (*ASRequest)(nil), // 9: proto.daemon.v1.ASRequest + (*ASResponse)(nil), // 10: proto.daemon.v1.ASResponse + (*InterfacesRequest)(nil), // 11: proto.daemon.v1.InterfacesRequest + (*InterfacesResponse)(nil), // 12: proto.daemon.v1.InterfacesResponse + (*Interface)(nil), // 13: proto.daemon.v1.Interface + (*ServicesRequest)(nil), // 14: proto.daemon.v1.ServicesRequest + (*ServicesResponse)(nil), // 15: proto.daemon.v1.ServicesResponse + (*ListService)(nil), // 16: proto.daemon.v1.ListService + (*Service)(nil), // 17: proto.daemon.v1.Service + (*Underlay)(nil), // 18: proto.daemon.v1.Underlay + (*NotifyInterfaceDownRequest)(nil), // 19: proto.daemon.v1.NotifyInterfaceDownRequest + (*NotifyInterfaceDownResponse)(nil), // 20: proto.daemon.v1.NotifyInterfaceDownResponse + (*PortRangeResponse)(nil), // 21: proto.daemon.v1.PortRangeResponse + (*DRKeyHostASRequest)(nil), // 22: proto.daemon.v1.DRKeyHostASRequest + (*DRKeyHostASResponse)(nil), // 23: proto.daemon.v1.DRKeyHostASResponse + (*DRKeyASHostRequest)(nil), // 24: proto.daemon.v1.DRKeyASHostRequest + (*DRKeyASHostResponse)(nil), // 25: proto.daemon.v1.DRKeyASHostResponse + (*DRKeyHostHostRequest)(nil), // 26: proto.daemon.v1.DRKeyHostHostRequest + (*DRKeyHostHostResponse)(nil), // 27: proto.daemon.v1.DRKeyHostHostResponse + nil, // 28: proto.daemon.v1.InterfacesResponse.InterfacesEntry + nil, // 29: proto.daemon.v1.ServicesResponse.ServicesEntry + (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 31: google.protobuf.Duration + (*experimental.FABRIDPolicyIdentifier)(nil), // 32: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + (drkey.Protocol)(0), // 33: proto.drkey.v1.Protocol + (*emptypb.Empty)(nil), // 34: google.protobuf.Empty } var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 3, // 0: proto.daemon.v1.PathsResponse.paths:type_name -> proto.daemon.v1.Path - 11, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface - 5, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface - 28, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp - 29, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration - 6, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates + 13, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface + 7, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface + 30, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp + 31, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration + 8, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates 0, // 6: proto.daemon.v1.Path.link_type:type_name -> proto.daemon.v1.LinkType - 4, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths - 26, // 8: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry - 16, // 9: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay - 27, // 10: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry - 15, // 11: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service - 28, // 12: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp - 30, // 13: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 28, // 14: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 28, // 15: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp - 28, // 16: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp - 30, // 17: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 28, // 18: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 28, // 19: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 28, // 20: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp - 30, // 21: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 28, // 22: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 28, // 23: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 11, // 24: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface - 14, // 25: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService - 1, // 26: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest - 7, // 27: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest - 9, // 28: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest - 12, // 29: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest - 17, // 30: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest - 31, // 31: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty - 22, // 32: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest - 20, // 33: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest - 24, // 34: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest - 2, // 35: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse - 8, // 36: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse - 10, // 37: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse - 13, // 38: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse - 18, // 39: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse - 19, // 40: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse - 23, // 41: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse - 21, // 42: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse - 25, // 43: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse - 35, // [35:44] is the sub-list for method output_type - 26, // [26:35] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 6, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths + 4, // 8: proto.daemon.v1.Path.fabrid_policies:type_name -> proto.daemon.v1.FabridPolicies + 5, // 9: proto.daemon.v1.FabridPolicies.policies:type_name -> proto.daemon.v1.FabridPolicy + 32, // 10: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 28, // 11: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry + 18, // 12: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay + 29, // 13: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry + 17, // 14: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service + 30, // 15: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp + 33, // 16: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 30, // 17: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 30, // 18: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp + 30, // 19: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp + 33, // 20: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 30, // 21: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 30, // 22: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 30, // 23: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp + 33, // 24: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 30, // 25: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 30, // 26: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 27: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface + 16, // 28: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService + 1, // 29: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest + 9, // 30: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest + 11, // 31: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest + 14, // 32: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest + 19, // 33: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest + 34, // 34: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty + 24, // 35: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest + 22, // 36: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest + 26, // 37: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest + 2, // 38: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse + 10, // 39: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse + 12, // 40: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse + 15, // 41: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse + 20, // 42: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse + 21, // 43: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse + 25, // 44: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse + 23, // 45: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse + 27, // 46: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse + 38, // [38:47] is the sub-list for method output_type + 29, // [29:38] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_proto_daemon_v1_daemon_proto_init() } @@ -1979,7 +2129,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EpicAuths); i { + switch v := v.(*FabridPolicies); i { case 0: return &v.state case 1: @@ -1991,7 +2141,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PathInterface); i { + switch v := v.(*FabridPolicy); i { case 0: return &v.state case 1: @@ -2003,7 +2153,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GeoCoordinates); i { + switch v := v.(*EpicAuths); i { case 0: return &v.state case 1: @@ -2015,7 +2165,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ASRequest); i { + switch v := v.(*PathInterface); i { case 0: return &v.state case 1: @@ -2027,7 +2177,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ASResponse); i { + switch v := v.(*GeoCoordinates); i { case 0: return &v.state case 1: @@ -2039,7 +2189,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfacesRequest); i { + switch v := v.(*ASRequest); i { case 0: return &v.state case 1: @@ -2051,7 +2201,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfacesResponse); i { + switch v := v.(*ASResponse); i { case 0: return &v.state case 1: @@ -2063,7 +2213,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Interface); i { + switch v := v.(*InterfacesRequest); i { case 0: return &v.state case 1: @@ -2075,7 +2225,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicesRequest); i { + switch v := v.(*InterfacesResponse); i { case 0: return &v.state case 1: @@ -2087,7 +2237,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicesResponse); i { + switch v := v.(*Interface); i { case 0: return &v.state case 1: @@ -2099,7 +2249,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListService); i { + switch v := v.(*ServicesRequest); i { case 0: return &v.state case 1: @@ -2111,7 +2261,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Service); i { + switch v := v.(*ServicesResponse); i { case 0: return &v.state case 1: @@ -2123,7 +2273,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Underlay); i { + switch v := v.(*ListService); i { case 0: return &v.state case 1: @@ -2135,7 +2285,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyInterfaceDownRequest); i { + switch v := v.(*Service); i { case 0: return &v.state case 1: @@ -2147,7 +2297,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyInterfaceDownResponse); i { + switch v := v.(*Underlay); i { case 0: return &v.state case 1: @@ -2159,7 +2309,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PortRangeResponse); i { + switch v := v.(*NotifyInterfaceDownRequest); i { case 0: return &v.state case 1: @@ -2171,7 +2321,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostASRequest); i { + switch v := v.(*NotifyInterfaceDownResponse); i { case 0: return &v.state case 1: @@ -2183,7 +2333,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostASResponse); i { + switch v := v.(*PortRangeResponse); i { case 0: return &v.state case 1: @@ -2195,7 +2345,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyASHostRequest); i { + switch v := v.(*DRKeyHostASRequest); i { case 0: return &v.state case 1: @@ -2207,7 +2357,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyASHostResponse); i { + switch v := v.(*DRKeyHostASResponse); i { case 0: return &v.state case 1: @@ -2219,7 +2369,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostHostRequest); i { + switch v := v.(*DRKeyASHostRequest); i { case 0: return &v.state case 1: @@ -2231,6 +2381,30 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DRKeyASHostResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DRKeyHostHostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostHostResponse); i { case 0: return &v.state @@ -2249,7 +2423,7 @@ func file_proto_daemon_v1_daemon_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_daemon_v1_daemon_proto_rawDesc, NumEnums: 1, - NumMessages: 27, + NumMessages: 29, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/snet/BUILD.bazel b/pkg/snet/BUILD.bazel index 568cc98d7c..c8ea9c18a9 100644 --- a/pkg/snet/BUILD.bazel +++ b/pkg/snet/BUILD.bazel @@ -21,6 +21,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", "//pkg/log:go_default_library", "//pkg/metrics/v2:go_default_library", "//pkg/private/common:go_default_library", diff --git a/pkg/snet/path.go b/pkg/snet/path.go index 4fcf7b5837..4274080907 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -22,6 +22,7 @@ import ( "time" "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/slayers" ) @@ -151,13 +152,23 @@ type PathMetadata struct { // EpicAuths contains the EPIC authenticators. EpicAuths EpicAuths + + // FabridEnabled contains a boolean for each AS, indicating whether it supports FABRID. + FabridEnabled []bool + + // FabridPolicies Contains the policy identifiers of interfaces on the path + FabridPolicies [][]*fabrid.Policy } func (pm *PathMetadata) Copy() *PathMetadata { if pm == nil { return nil } - + fabridPoliciesCopy := make([][]*fabrid.Policy, len(pm.FabridPolicies)) + for i := range pm.FabridPolicies { + fabridPoliciesCopy[i] = make([]*fabrid.Policy, len(pm.FabridPolicies[i])) + copy(fabridPoliciesCopy[i], pm.FabridPolicies[i]) + } return &PathMetadata{ Interfaces: append(pm.Interfaces[:0:0], pm.Interfaces...), MTU: pm.MTU, @@ -169,6 +180,9 @@ func (pm *PathMetadata) Copy() *PathMetadata { LinkType: append(pm.LinkType[:0:0], pm.LinkType...), InternalHops: append(pm.InternalHops[:0:0], pm.InternalHops...), Notes: append(pm.Notes[:0:0], pm.Notes...), + FabridEnabled: append(pm.FabridEnabled[:0:0], pm.FabridEnabled...), + FabridPolicies: fabridPoliciesCopy, + EpicAuths: EpicAuths{ AuthPHVF: append([]byte(nil), pm.EpicAuths.AuthPHVF...), AuthLHVF: append([]byte(nil), pm.EpicAuths.AuthLHVF...), diff --git a/proto/daemon/v1/BUILD.bazel b/proto/daemon/v1/BUILD.bazel index 8e53589e34..a0dc5e5afa 100644 --- a/proto/daemon/v1/BUILD.bazel +++ b/proto/daemon/v1/BUILD.bazel @@ -7,6 +7,7 @@ proto_library( ], visibility = ["//visibility:public"], deps = [ + "//proto/control_plane/experimental/v1:experimental", "//proto/drkey/v1:drkey", "@com_google_protobuf//:duration_proto", "@com_google_protobuf//:empty_proto", diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index 0697195fc1..cfeb54f4d9 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -22,6 +22,7 @@ import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/empty.proto"; import "proto/drkey/v1/drkey.proto"; +import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; service DaemonService { // Return a set of paths to the requested destination. @@ -114,6 +115,22 @@ message Path { // Entry i describes the carbon intensity between interface i and i+1. // Consequently, there are N-1 entries for N interfaces. repeated int64 carbon_intensity = 13; + // FabridEnabled describes which hops support Fabrid. + repeated bool fabrid_enabled = 14; + // FabridPolicies contains the fabrid policy identifiers that are supported for an interface + // Entry i describes the policies between interfaces i and i+1. + repeated FabridPolicies fabrid_policies = 15; +} + +message FabridPolicies { + // A list of policies for a specific interface + repeated FabridPolicy policies = 1; +} +message FabridPolicy { + // The identifier for the policy, either local or global: + proto.control_plane.experimental.v1.FABRIDPolicyIdentifier policy_identifier = 1; + // The local index, this may differ between similar policy identifiers, as it is specific to a hop. + uint32 policy_index = 2; } message EpicAuths { From ee8a3e28664369b58ce60bcb75c6720b03dd6ce0 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 12:30:10 +0200 Subject: [PATCH 03/26] DRKeys for FABRID - SD uses correct local address for fetching DRKeys - FabridKeys function fetches required ASHost keys and the HostHost key --- daemon/cmd/daemon/main.go | 16 +- daemon/drkey/client_engine.go | 49 ++ daemon/drkey/grpc/BUILD.bazel | 1 + daemon/drkey/grpc/fetcher.go | 35 ++ daemon/internal/servers/grpc.go | 43 ++ pkg/daemon/daemon.go | 2 + pkg/daemon/grpc.go | 51 ++ pkg/daemon/helper/BUILD.bazel | 16 + pkg/daemon/helper/protobuf.go | 163 +++++ pkg/drkey/drkey.go | 22 + pkg/proto/daemon/daemon.pb.go | 1028 ++++++++++++++++++++----------- pkg/proto/drkey/drkey.pb.go | 17 +- proto/daemon/v1/daemon.proto | 29 + proto/drkey/v1/drkey.proto | 2 + tools/topology/go.py | 6 +- 15 files changed, 1110 insertions(+), 370 deletions(-) create mode 100644 pkg/daemon/helper/BUILD.bazel create mode 100644 pkg/daemon/helper/protobuf.go diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index 5b3f7c3e05..e3254e0ce2 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -202,10 +202,20 @@ func realMain(ctx context.Context) error { }, } defer level2DB.Close() - - drkeyFetcher := &sd_grpc.Fetcher{ - Dialer: dialer, + csAddr, err := net.ResolveTCPAddr("tcp", topo.ControlServiceAddresses()[0].String()) + if err != nil { + return serrors.WrapStr("resolve control service address", err) + } + localAddrIPString, _, err := net.SplitHostPort(globalCfg.SD.Address) + if err != nil { + return serrors.WrapStr("resolve local address", err) + } + localAddrIP := net.ParseIP(localAddrIPString) + localAddr := &net.TCPAddr{ + IP: localAddrIP, + Port: 0, } + drkeyFetcher := sd_grpc.SetupFetcher(csAddr, localAddr) drkeyClientEngine = &sd_drkey.ClientEngine{ IA: topo.IA(), DB: level2DB, diff --git a/daemon/drkey/client_engine.go b/daemon/drkey/client_engine.go index 658e997dbd..987dda9957 100644 --- a/daemon/drkey/client_engine.go +++ b/daemon/drkey/client_engine.go @@ -38,6 +38,55 @@ type ClientEngine struct { Fetcher Fetcher } +// For all ASHost Keys and for the HostHost Key, it checks whether the keys are in the database. +// If this is the case, those keys are returned. If not, the keys are requested from CS. +func (e *ClientEngine) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, +) (drkey.FabridKeysResponse, error) { + now := time.Now() + var hostHostKey drkey.FabridKey = drkey.FabridKey{} + if meta.DstHost != nil && len(meta.PathASes) > 0 { + key, err := e.GetHostHostKey(ctx, drkey.HostHostMeta{ + ProtoId: drkey.FABRID, + Validity: now, + SrcIA: meta.DstAS, + SrcHost: *meta.DstHost, + DstIA: meta.SrcAS, + DstHost: meta.SrcHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID host-host key", err) + } + hostHostKey = drkey.FabridKey{ + Epoch: key.Epoch, + AS: meta.DstAS, + Key: key.Key, + } + } + asHostKeys := make([]drkey.FabridKey, 0, len(meta.PathASes)) + for _, as := range meta.PathASes { + key, err := e.GetASHostKey(ctx, drkey.ASHostMeta{ + ProtoId: drkey.FABRID, + Validity: now, + SrcIA: as, + DstIA: meta.SrcAS, + DstHost: meta.SrcHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID AS-host key", err) + } + asHostKeys = append(asHostKeys, drkey.FabridKey{ + Epoch: key.Epoch, + AS: as, + Key: key.Key, + }) + } + + return drkey.FabridKeysResponse{ + ASHostKeys: asHostKeys, + PathKey: hostHostKey, + }, nil +} + // GetASHostKey returns the ASHost key from the local DB or if not found, by asking our local CS. func (e *ClientEngine) GetASHostKey( ctx context.Context, diff --git a/daemon/drkey/grpc/BUILD.bazel b/daemon/drkey/grpc/BUILD.bazel index c1fdb982c8..b82537d328 100644 --- a/daemon/drkey/grpc/BUILD.bazel +++ b/daemon/drkey/grpc/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "//pkg/proto/drkey:go_default_library", "//pkg/scrypto/cppki:go_default_library", "//pkg/snet:go_default_library", + "@org_golang_google_grpc//:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) diff --git a/daemon/drkey/grpc/fetcher.go b/daemon/drkey/grpc/fetcher.go index a6e51ffe75..b66250a8b2 100644 --- a/daemon/drkey/grpc/fetcher.go +++ b/daemon/drkey/grpc/fetcher.go @@ -16,6 +16,9 @@ package grpc import ( "context" + "net" + + "google.golang.org/grpc" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" @@ -30,6 +33,38 @@ type Fetcher struct { Dialer sc_grpc.Dialer } +func SetupFetcher(csAddr *net.TCPAddr, localAddr *net.TCPAddr) *Fetcher { + return &Fetcher{ + Dialer: &CustomDialer{ + CsAddr: csAddr, + LocalAddr: localAddr, + }, + } +} + +type CustomDialer struct { + CsAddr *net.TCPAddr + LocalAddr *net.TCPAddr +} + +// This custom dialer is used for communication with the local control service. Therefore +// the destination address is already configured during the setup and any passed +// address will be ignored. +func (d *CustomDialer) Dial(ctx context.Context, _ net.Addr) (*grpc.ClientConn, error) { + // this custom dialer modifies its local address. Otherwise in the local setup + // grpc might use 127.0.0.1 as local address and therefore the control service + // would reject the drkey request + dialer := func(ctx context.Context, addr string) (net.Conn, error) { + return net.DialTCP("tcp", d.LocalAddr, d.CsAddr) + } + return grpc.DialContext(ctx, d.CsAddr.String(), + grpc.WithInsecure(), + grpc.WithContextDialer(dialer), + sc_grpc.UnaryClientInterceptor(), + sc_grpc.StreamClientInterceptor(), + ) +} + func (f *Fetcher) ASHostKey( ctx context.Context, meta drkey.ASHostMeta, diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index e69f0f495a..0e182058fc 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -392,6 +392,49 @@ func (s *DaemonServer) PortRange( }, nil } +func (s *DaemonServer) FabridKeys(ctx context.Context, req *pb_daemon.FabridKeysRequest, +) (*pb_daemon.FabridKeysResponse, error) { + if s.DRKeyClient == nil { + return nil, serrors.New("DRKey is not available") + } + pathASes := make([]addr.IA, 0, len(req.PathAses)) + for _, as := range req.PathAses { + pathASes = append(pathASes, addr.IA(as)) + } + resp, err := s.DRKeyClient.FabridKeys(ctx, drkey.FabridKeysMeta{ + SrcAS: s.DRKeyClient.IA, + SrcHost: req.SrcHost, + DstHost: req.DstHost, + PathASes: pathASes, + DstAS: addr.IA(req.DstAs), + }) + if err != nil { + return nil, serrors.WrapStr("getting fabrid keys from client store", err) + } + fabridKeys := make([]*pb_daemon.FabridKeyResponse, 0, len(resp.ASHostKeys)) + for i := range resp.ASHostKeys { + key := resp.ASHostKeys[i] + fabridKeys = append(fabridKeys, &sdpb.FabridKeyResponse{ + EpochBegin: ×tamppb.Timestamp{Seconds: key.Epoch.NotBefore.Unix()}, + EpochEnd: ×tamppb.Timestamp{Seconds: key.Epoch.NotAfter.Unix()}, + Key: key.Key[:], + }) + } + + var hostHostKey *sdpb.FabridKeyResponse = nil + if req.DstHost != nil { + hostHostKey = &sdpb.FabridKeyResponse{ + EpochBegin: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotBefore.Unix()}, + EpochEnd: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotAfter.Unix()}, + Key: resp.PathKey.Key[:], + } + } + return &pb_daemon.FabridKeysResponse{ + AsHostKeys: fabridKeys, + HostHostKey: hostHostKey, + }, nil +} + func (s *DaemonServer) DRKeyASHost( ctx context.Context, req *pb_daemon.DRKeyASHostRequest, diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index a9ba3397ee..edd6994cd9 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -88,6 +88,8 @@ type Connector interface { DRKeyGetHostASKey(ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) // DRKeyGetHostHostKey requests a Host-Host Key from the daemon. DRKeyGetHostHostKey(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) + // FabridKeys requests FABRID DRKeys for all provided ASes and the path validation key + FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta) (drkey.FabridKeysResponse, error) // Close shuts down the connection to the daemon. Close() error } diff --git a/pkg/daemon/grpc.go b/pkg/daemon/grpc.go index 7ac09f3d9a..929d99c664 100644 --- a/pkg/daemon/grpc.go +++ b/pkg/daemon/grpc.go @@ -225,6 +225,57 @@ func (c grpcConn) DRKeyGetHostHostKey(ctx context.Context, return key, nil } +// Returns all the ASHost DRKeys for the ASes inside the meta.PathAS +func (c grpcConn) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, +) (drkey.FabridKeysResponse, error) { + + client := sdpb.NewDaemonServiceClient((c.conn)) + pathASes := make([]uint64, 0, len(meta.PathASes)) + for i := 0; i < len(meta.PathASes); i++ { + pathASes = append(pathASes, uint64(meta.PathASes[i])) + } + resp, err := client.FabridKeys(ctx, &sdpb.FabridKeysRequest{ + SrcHost: meta.SrcHost, + PathAses: pathASes, + DstAs: uint64(meta.DstAS), + DstHost: meta.DstHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, err + } + asHostKeys := make([]drkey.FabridKey, 0, len(resp.AsHostKeys)) + for i, key := range resp.AsHostKeys { + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: key.EpochBegin.AsTime(), + NotAfter: key.EpochEnd.AsTime(), + }, + } + asHostKeys = append(asHostKeys, drkey.FabridKey{ + Epoch: epoch, + AS: meta.PathASes[i], + Key: drkey.Key(key.Key), + }) + } + var hostHostKey drkey.FabridKey = drkey.FabridKey{} + if resp.HostHostKey != nil { + hostHostKey = drkey.FabridKey{ + Epoch: drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: resp.HostHostKey.EpochBegin.AsTime(), + NotAfter: resp.HostHostKey.EpochEnd.AsTime(), + }, + }, + AS: meta.DstAS, + Key: drkey.Key(resp.HostHostKey.Key), + } + } + return drkey.FabridKeysResponse{ + ASHostKeys: asHostKeys, + PathKey: hostHostKey, + }, nil +} + func (c grpcConn) Close() error { return c.conn.Close() } diff --git a/pkg/daemon/helper/BUILD.bazel b/pkg/daemon/helper/BUILD.bazel new file mode 100644 index 0000000000..5d42ff3c5c --- /dev/null +++ b/pkg/daemon/helper/BUILD.bazel @@ -0,0 +1,16 @@ +load("//tools/lint:go.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["protobuf.go"], + importpath = "github.com/scionproto/scion/pkg/daemon/helper", + visibility = ["//visibility:public"], + deps = [ + "//pkg/drkey:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/proto/control_plane:go_default_library", + "//pkg/proto/drkey:go_default_library", + "//pkg/scrypto/cppki:go_default_library", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", + ], +) diff --git a/pkg/daemon/helper/protobuf.go b/pkg/daemon/helper/protobuf.go new file mode 100644 index 0000000000..76e8066c02 --- /dev/null +++ b/pkg/daemon/helper/protobuf.go @@ -0,0 +1,163 @@ +// Copyright 2022 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package protobuf + +import ( + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/private/serrors" + cppb "github.com/scionproto/scion/pkg/proto/control_plane" + drkeypb "github.com/scionproto/scion/pkg/proto/drkey" + "github.com/scionproto/scion/pkg/scrypto/cppki" +) + +func AsHostMetaToProtoRequest(meta drkey.ASHostMeta) *cppb.DRKeyASHostRequest { + return &cppb.DRKeyASHostRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: drkeypb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + DstHost: meta.DstHost, + } +} + +func GetASHostKeyFromReply( + rep *cppb.DRKeyASHostResponse, + meta drkey.ASHostMeta, +) (drkey.ASHostKey, error) { + + err := rep.EpochBegin.CheckValid() + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("invalid EpochBegin from response", err) + } + err = rep.EpochEnd.CheckValid() + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("invalid EpochEnd from response", err) + } + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + + returningKey := drkey.ASHostKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + DstHost: meta.DstHost, + } + + if len(rep.Key) != 16 { + return drkey.ASHostKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} + +func HostASMetaToProtoRequest(meta drkey.HostASMeta) *cppb.DRKeyHostASRequest { + return &cppb.DRKeyHostASRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: drkeypb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + SrcHost: meta.SrcHost, + } +} + +func GetHostASKeyFromReply( + rep *cppb.DRKeyHostASResponse, + meta drkey.HostASMeta, +) (drkey.HostASKey, error) { + + err := rep.EpochBegin.CheckValid() + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("invalid EpochBegin from response", err) + } + err = rep.EpochEnd.CheckValid() + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("invalid EpochEnd from response", err) + } + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + + returningKey := drkey.HostASKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + SrcHost: meta.SrcHost, + } + if len(rep.Key) != 16 { + return drkey.HostASKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} + +func HostHostMetaToProtoRequest(meta drkey.HostHostMeta) *cppb.DRKeyHostHostRequest { + return &cppb.DRKeyHostHostRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: drkeypb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + DstHost: meta.DstHost, + SrcHost: meta.SrcHost, + } +} + +func GetHostHostKeyFromReply( + rep *cppb.DRKeyHostHostResponse, + meta drkey.HostHostMeta, +) (drkey.HostHostKey, error) { + + err := rep.EpochBegin.CheckValid() + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("invalid EpochBegin from response", err) + } + err = rep.EpochEnd.CheckValid() + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("invalid EpochEnd from response", err) + } + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + + returningKey := drkey.HostHostKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + SrcHost: meta.SrcHost, + DstHost: meta.DstHost, + } + if len(rep.Key) != 16 { + return drkey.HostHostKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} diff --git a/pkg/drkey/drkey.go b/pkg/drkey/drkey.go index 23811a88fe..635cebaa39 100644 --- a/pkg/drkey/drkey.go +++ b/pkg/drkey/drkey.go @@ -33,6 +33,7 @@ import ( const ( Generic = Protocol(pb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED) SCMP = Protocol(pb.Protocol_PROTOCOL_SCMP) + FABRID = Protocol(pb.Protocol_PROTOCOL_FABRID) ) // Epoch represents a validity period. @@ -198,3 +199,24 @@ type HostHostKey struct { DstHost string Key Key } + +type FabridKeysMeta struct { + SrcAS addr.IA + SrcHost string + // ASes on the path. Don't have to be in order + PathASes []addr.IA + // Field is optional. If DstHost is nil, no path-key will be fetched + DstHost *string + DstAS addr.IA +} + +type FabridKey struct { + Epoch Epoch + AS addr.IA + Key Key +} + +type FabridKeysResponse struct { + ASHostKeys []FabridKey + PathKey FabridKey +} diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index 0fa64eb59d..cf32075acb 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -460,6 +460,195 @@ func (x *FabridPolicy) GetPolicyIndex() uint32 { return 0 } +type FabridKeysRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrcHost string `protobuf:"bytes,1,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` + DstAs uint64 `protobuf:"varint,2,opt,name=dst_as,json=dstAs,proto3" json:"dst_as,omitempty"` + PathAses []uint64 `protobuf:"varint,3,rep,packed,name=path_ases,json=pathAses,proto3" json:"path_ases,omitempty"` + DstHost *string `protobuf:"bytes,4,opt,name=dst_host,json=dstHost,proto3,oneof" json:"dst_host,omitempty"` +} + +func (x *FabridKeysRequest) Reset() { + *x = FabridKeysRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeysRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeysRequest) ProtoMessage() {} + +func (x *FabridKeysRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeysRequest.ProtoReflect.Descriptor instead. +func (*FabridKeysRequest) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} +} + +func (x *FabridKeysRequest) GetSrcHost() string { + if x != nil { + return x.SrcHost + } + return "" +} + +func (x *FabridKeysRequest) GetDstAs() uint64 { + if x != nil { + return x.DstAs + } + return 0 +} + +func (x *FabridKeysRequest) GetPathAses() []uint64 { + if x != nil { + return x.PathAses + } + return nil +} + +func (x *FabridKeysRequest) GetDstHost() string { + if x != nil && x.DstHost != nil { + return *x.DstHost + } + return "" +} + +type FabridKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *FabridKeyResponse) Reset() { + *x = FabridKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeyResponse) ProtoMessage() {} + +func (x *FabridKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeyResponse.ProtoReflect.Descriptor instead. +func (*FabridKeyResponse) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} +} + +func (x *FabridKeyResponse) GetEpochBegin() *timestamppb.Timestamp { + if x != nil { + return x.EpochBegin + } + return nil +} + +func (x *FabridKeyResponse) GetEpochEnd() *timestamppb.Timestamp { + if x != nil { + return x.EpochEnd + } + return nil +} + +func (x *FabridKeyResponse) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +type FabridKeysResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AsHostKeys []*FabridKeyResponse `protobuf:"bytes,1,rep,name=as_host_keys,json=asHostKeys,proto3" json:"as_host_keys,omitempty"` + HostHostKey *FabridKeyResponse `protobuf:"bytes,2,opt,name=host_host_key,json=hostHostKey,proto3,oneof" json:"host_host_key,omitempty"` +} + +func (x *FabridKeysResponse) Reset() { + *x = FabridKeysResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeysResponse) ProtoMessage() {} + +func (x *FabridKeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeysResponse.ProtoReflect.Descriptor instead. +func (*FabridKeysResponse) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} +} + +func (x *FabridKeysResponse) GetAsHostKeys() []*FabridKeyResponse { + if x != nil { + return x.AsHostKeys + } + return nil +} + +func (x *FabridKeysResponse) GetHostHostKey() *FabridKeyResponse { + if x != nil { + return x.HostHostKey + } + return nil +} + type EpicAuths struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -472,7 +661,7 @@ type EpicAuths struct { func (x *EpicAuths) Reset() { *x = EpicAuths{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -485,7 +674,7 @@ func (x *EpicAuths) String() string { func (*EpicAuths) ProtoMessage() {} func (x *EpicAuths) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -498,7 +687,7 @@ func (x *EpicAuths) ProtoReflect() protoreflect.Message { // Deprecated: Use EpicAuths.ProtoReflect.Descriptor instead. func (*EpicAuths) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} } func (x *EpicAuths) GetAuthPhvf() []byte { @@ -527,7 +716,7 @@ type PathInterface struct { func (x *PathInterface) Reset() { *x = PathInterface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -540,7 +729,7 @@ func (x *PathInterface) String() string { func (*PathInterface) ProtoMessage() {} func (x *PathInterface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -553,7 +742,7 @@ func (x *PathInterface) ProtoReflect() protoreflect.Message { // Deprecated: Use PathInterface.ProtoReflect.Descriptor instead. func (*PathInterface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} } func (x *PathInterface) GetIsdAs() uint64 { @@ -583,7 +772,7 @@ type GeoCoordinates struct { func (x *GeoCoordinates) Reset() { *x = GeoCoordinates{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -596,7 +785,7 @@ func (x *GeoCoordinates) String() string { func (*GeoCoordinates) ProtoMessage() {} func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -609,7 +798,7 @@ func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoCoordinates.ProtoReflect.Descriptor instead. func (*GeoCoordinates) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} } func (x *GeoCoordinates) GetLatitude() float32 { @@ -644,7 +833,7 @@ type ASRequest struct { func (x *ASRequest) Reset() { *x = ASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -657,7 +846,7 @@ func (x *ASRequest) String() string { func (*ASRequest) ProtoMessage() {} func (x *ASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -670,7 +859,7 @@ func (x *ASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ASRequest.ProtoReflect.Descriptor instead. func (*ASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} } func (x *ASRequest) GetIsdAs() uint64 { @@ -693,7 +882,7 @@ type ASResponse struct { func (x *ASResponse) Reset() { *x = ASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -706,7 +895,7 @@ func (x *ASResponse) String() string { func (*ASResponse) ProtoMessage() {} func (x *ASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -719,7 +908,7 @@ func (x *ASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ASResponse.ProtoReflect.Descriptor instead. func (*ASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} } func (x *ASResponse) GetIsdAs() uint64 { @@ -752,7 +941,7 @@ type InterfacesRequest struct { func (x *InterfacesRequest) Reset() { *x = InterfacesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -765,7 +954,7 @@ func (x *InterfacesRequest) String() string { func (*InterfacesRequest) ProtoMessage() {} func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -778,7 +967,7 @@ func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesRequest.ProtoReflect.Descriptor instead. func (*InterfacesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} } type InterfacesResponse struct { @@ -792,7 +981,7 @@ type InterfacesResponse struct { func (x *InterfacesResponse) Reset() { *x = InterfacesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -805,7 +994,7 @@ func (x *InterfacesResponse) String() string { func (*InterfacesResponse) ProtoMessage() {} func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -818,7 +1007,7 @@ func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesResponse.ProtoReflect.Descriptor instead. func (*InterfacesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} } func (x *InterfacesResponse) GetInterfaces() map[uint64]*Interface { @@ -839,7 +1028,7 @@ type Interface struct { func (x *Interface) Reset() { *x = Interface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -852,7 +1041,7 @@ func (x *Interface) String() string { func (*Interface) ProtoMessage() {} func (x *Interface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -865,7 +1054,7 @@ func (x *Interface) ProtoReflect() protoreflect.Message { // Deprecated: Use Interface.ProtoReflect.Descriptor instead. func (*Interface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} } func (x *Interface) GetAddress() *Underlay { @@ -884,7 +1073,7 @@ type ServicesRequest struct { func (x *ServicesRequest) Reset() { *x = ServicesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -897,7 +1086,7 @@ func (x *ServicesRequest) String() string { func (*ServicesRequest) ProtoMessage() {} func (x *ServicesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -910,7 +1099,7 @@ func (x *ServicesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesRequest.ProtoReflect.Descriptor instead. func (*ServicesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} } type ServicesResponse struct { @@ -924,7 +1113,7 @@ type ServicesResponse struct { func (x *ServicesResponse) Reset() { *x = ServicesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -937,7 +1126,7 @@ func (x *ServicesResponse) String() string { func (*ServicesResponse) ProtoMessage() {} func (x *ServicesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -950,7 +1139,7 @@ func (x *ServicesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesResponse.ProtoReflect.Descriptor instead. func (*ServicesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} } func (x *ServicesResponse) GetServices() map[string]*ListService { @@ -971,7 +1160,7 @@ type ListService struct { func (x *ListService) Reset() { *x = ListService{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -984,7 +1173,7 @@ func (x *ListService) String() string { func (*ListService) ProtoMessage() {} func (x *ListService) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -997,7 +1186,7 @@ func (x *ListService) ProtoReflect() protoreflect.Message { // Deprecated: Use ListService.ProtoReflect.Descriptor instead. func (*ListService) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} } func (x *ListService) GetServices() []*Service { @@ -1018,7 +1207,7 @@ type Service struct { func (x *Service) Reset() { *x = Service{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1031,7 +1220,7 @@ func (x *Service) String() string { func (*Service) ProtoMessage() {} func (x *Service) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1044,7 +1233,7 @@ func (x *Service) ProtoReflect() protoreflect.Message { // Deprecated: Use Service.ProtoReflect.Descriptor instead. func (*Service) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} } func (x *Service) GetUri() string { @@ -1065,7 +1254,7 @@ type Underlay struct { func (x *Underlay) Reset() { *x = Underlay{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1078,7 +1267,7 @@ func (x *Underlay) String() string { func (*Underlay) ProtoMessage() {} func (x *Underlay) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1091,7 +1280,7 @@ func (x *Underlay) ProtoReflect() protoreflect.Message { // Deprecated: Use Underlay.ProtoReflect.Descriptor instead. func (*Underlay) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} } func (x *Underlay) GetAddress() string { @@ -1113,7 +1302,7 @@ type NotifyInterfaceDownRequest struct { func (x *NotifyInterfaceDownRequest) Reset() { *x = NotifyInterfaceDownRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1126,7 +1315,7 @@ func (x *NotifyInterfaceDownRequest) String() string { func (*NotifyInterfaceDownRequest) ProtoMessage() {} func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1139,7 +1328,7 @@ func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownRequest.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} } func (x *NotifyInterfaceDownRequest) GetIsdAs() uint64 { @@ -1165,7 +1354,7 @@ type NotifyInterfaceDownResponse struct { func (x *NotifyInterfaceDownResponse) Reset() { *x = NotifyInterfaceDownResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1178,7 +1367,7 @@ func (x *NotifyInterfaceDownResponse) String() string { func (*NotifyInterfaceDownResponse) ProtoMessage() {} func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1191,7 +1380,7 @@ func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownResponse.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} } type PortRangeResponse struct { @@ -1206,7 +1395,7 @@ type PortRangeResponse struct { func (x *PortRangeResponse) Reset() { *x = PortRangeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1219,7 +1408,7 @@ func (x *PortRangeResponse) String() string { func (*PortRangeResponse) ProtoMessage() {} func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1232,7 +1421,7 @@ func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PortRangeResponse.ProtoReflect.Descriptor instead. func (*PortRangeResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} } func (x *PortRangeResponse) GetDispatchedPortStart() uint32 { @@ -1264,7 +1453,7 @@ type DRKeyHostASRequest struct { func (x *DRKeyHostASRequest) Reset() { *x = DRKeyHostASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1277,7 +1466,7 @@ func (x *DRKeyHostASRequest) String() string { func (*DRKeyHostASRequest) ProtoMessage() {} func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1290,7 +1479,7 @@ func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} } func (x *DRKeyHostASRequest) GetValTime() *timestamppb.Timestamp { @@ -1341,7 +1530,7 @@ type DRKeyHostASResponse struct { func (x *DRKeyHostASResponse) Reset() { *x = DRKeyHostASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1354,7 +1543,7 @@ func (x *DRKeyHostASResponse) String() string { func (*DRKeyHostASResponse) ProtoMessage() {} func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1367,7 +1556,7 @@ func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{25} } func (x *DRKeyHostASResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1406,7 +1595,7 @@ type DRKeyASHostRequest struct { func (x *DRKeyASHostRequest) Reset() { *x = DRKeyASHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1419,7 +1608,7 @@ func (x *DRKeyASHostRequest) String() string { func (*DRKeyASHostRequest) ProtoMessage() {} func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1432,7 +1621,7 @@ func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyASHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{26} } func (x *DRKeyASHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1483,7 +1672,7 @@ type DRKeyASHostResponse struct { func (x *DRKeyASHostResponse) Reset() { *x = DRKeyASHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1496,7 +1685,7 @@ func (x *DRKeyASHostResponse) String() string { func (*DRKeyASHostResponse) ProtoMessage() {} func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1509,7 +1698,7 @@ func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyASHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{27} } func (x *DRKeyASHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1549,7 +1738,7 @@ type DRKeyHostHostRequest struct { func (x *DRKeyHostHostRequest) Reset() { *x = DRKeyHostHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1562,7 +1751,7 @@ func (x *DRKeyHostHostRequest) String() string { func (*DRKeyHostHostRequest) ProtoMessage() {} func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1575,7 +1764,7 @@ func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{25} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{28} } func (x *DRKeyHostHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1633,7 +1822,7 @@ type DRKeyHostHostResponse struct { func (x *DRKeyHostHostResponse) Reset() { *x = DRKeyHostHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1646,7 +1835,7 @@ func (x *DRKeyHostHostResponse) String() string { func (*DRKeyHostHostResponse) ProtoMessage() {} func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1659,7 +1848,7 @@ func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{26} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{29} } func (x *DRKeyHostHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1771,105 +1960,159 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, - 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, - 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, - 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, - 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, - 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, - 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, - 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, - 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, - 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, - 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, - 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, - 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, - 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, - 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, - 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, - 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, - 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, - 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, - 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, - 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, - 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, - 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, - 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, - 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, - 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, + 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, 0x11, 0x46, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, + 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x41, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x41, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x08, + 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, + 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x9b, 0x01, 0x0a, 0x11, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xb9, 0x01, 0x0a, 0x12, 0x46, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, + 0x0a, 0x0c, 0x61, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x61, 0x73, 0x48, 0x6f, 0x73, 0x74, + 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, + 0x00, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x88, 0x01, + 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x6b, 0x65, 0x79, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, + 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, 0x66, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, 0x66, 0x12, 0x1b, 0x0a, + 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, 0x0a, 0x0d, 0x50, 0x61, + 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, + 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, + 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, 0x41, 0x53, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x22, 0x49, 0x0a, 0x0a, + 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, + 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, + 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x07, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, 0x72, + 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x43, 0x0a, + 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, + 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, + 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x65, 0x6e, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, + 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, + 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, + 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, + 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, + 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, + 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, + 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, + 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, + 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, + 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, + 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, + 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xec, + 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, @@ -1880,104 +2123,86 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, - 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, - 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, - 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, - 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, - 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, - 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, - 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, - 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, - 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, - 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, - 0x03, 0x32, 0x9f, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, - 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, - 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, - 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, + 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, + 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9f, 0x01, + 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, + 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x2a, + 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, + 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, + 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, + 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0xf8, 0x06, + 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, 0x41, 0x53, 0x12, + 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, - 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, - 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, - 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, - 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, - 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, - 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, + 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x09, 0x50, 0x6f, + 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, + 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, - 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, + 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, + 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, + 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x25, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x57, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x22, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1993,7 +2218,7 @@ func file_proto_daemon_v1_daemon_proto_rawDescGZIP() []byte { } var file_proto_daemon_v1_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 32) var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ (LinkType)(0), // 0: proto.daemon.v1.LinkType (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest @@ -2001,89 +2226,98 @@ var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ (*Path)(nil), // 3: proto.daemon.v1.Path (*FabridPolicies)(nil), // 4: proto.daemon.v1.FabridPolicies (*FabridPolicy)(nil), // 5: proto.daemon.v1.FabridPolicy - (*EpicAuths)(nil), // 6: proto.daemon.v1.EpicAuths - (*PathInterface)(nil), // 7: proto.daemon.v1.PathInterface - (*GeoCoordinates)(nil), // 8: proto.daemon.v1.GeoCoordinates - (*ASRequest)(nil), // 9: proto.daemon.v1.ASRequest - (*ASResponse)(nil), // 10: proto.daemon.v1.ASResponse - (*InterfacesRequest)(nil), // 11: proto.daemon.v1.InterfacesRequest - (*InterfacesResponse)(nil), // 12: proto.daemon.v1.InterfacesResponse - (*Interface)(nil), // 13: proto.daemon.v1.Interface - (*ServicesRequest)(nil), // 14: proto.daemon.v1.ServicesRequest - (*ServicesResponse)(nil), // 15: proto.daemon.v1.ServicesResponse - (*ListService)(nil), // 16: proto.daemon.v1.ListService - (*Service)(nil), // 17: proto.daemon.v1.Service - (*Underlay)(nil), // 18: proto.daemon.v1.Underlay - (*NotifyInterfaceDownRequest)(nil), // 19: proto.daemon.v1.NotifyInterfaceDownRequest - (*NotifyInterfaceDownResponse)(nil), // 20: proto.daemon.v1.NotifyInterfaceDownResponse - (*PortRangeResponse)(nil), // 21: proto.daemon.v1.PortRangeResponse - (*DRKeyHostASRequest)(nil), // 22: proto.daemon.v1.DRKeyHostASRequest - (*DRKeyHostASResponse)(nil), // 23: proto.daemon.v1.DRKeyHostASResponse - (*DRKeyASHostRequest)(nil), // 24: proto.daemon.v1.DRKeyASHostRequest - (*DRKeyASHostResponse)(nil), // 25: proto.daemon.v1.DRKeyASHostResponse - (*DRKeyHostHostRequest)(nil), // 26: proto.daemon.v1.DRKeyHostHostRequest - (*DRKeyHostHostResponse)(nil), // 27: proto.daemon.v1.DRKeyHostHostResponse - nil, // 28: proto.daemon.v1.InterfacesResponse.InterfacesEntry - nil, // 29: proto.daemon.v1.ServicesResponse.ServicesEntry - (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 31: google.protobuf.Duration - (*experimental.FABRIDPolicyIdentifier)(nil), // 32: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier - (drkey.Protocol)(0), // 33: proto.drkey.v1.Protocol - (*emptypb.Empty)(nil), // 34: google.protobuf.Empty + (*FabridKeysRequest)(nil), // 6: proto.daemon.v1.FabridKeysRequest + (*FabridKeyResponse)(nil), // 7: proto.daemon.v1.FabridKeyResponse + (*FabridKeysResponse)(nil), // 8: proto.daemon.v1.FabridKeysResponse + (*EpicAuths)(nil), // 9: proto.daemon.v1.EpicAuths + (*PathInterface)(nil), // 10: proto.daemon.v1.PathInterface + (*GeoCoordinates)(nil), // 11: proto.daemon.v1.GeoCoordinates + (*ASRequest)(nil), // 12: proto.daemon.v1.ASRequest + (*ASResponse)(nil), // 13: proto.daemon.v1.ASResponse + (*InterfacesRequest)(nil), // 14: proto.daemon.v1.InterfacesRequest + (*InterfacesResponse)(nil), // 15: proto.daemon.v1.InterfacesResponse + (*Interface)(nil), // 16: proto.daemon.v1.Interface + (*ServicesRequest)(nil), // 17: proto.daemon.v1.ServicesRequest + (*ServicesResponse)(nil), // 18: proto.daemon.v1.ServicesResponse + (*ListService)(nil), // 19: proto.daemon.v1.ListService + (*Service)(nil), // 20: proto.daemon.v1.Service + (*Underlay)(nil), // 21: proto.daemon.v1.Underlay + (*NotifyInterfaceDownRequest)(nil), // 22: proto.daemon.v1.NotifyInterfaceDownRequest + (*NotifyInterfaceDownResponse)(nil), // 23: proto.daemon.v1.NotifyInterfaceDownResponse + (*PortRangeResponse)(nil), // 24: proto.daemon.v1.PortRangeResponse + (*DRKeyHostASRequest)(nil), // 25: proto.daemon.v1.DRKeyHostASRequest + (*DRKeyHostASResponse)(nil), // 26: proto.daemon.v1.DRKeyHostASResponse + (*DRKeyASHostRequest)(nil), // 27: proto.daemon.v1.DRKeyASHostRequest + (*DRKeyASHostResponse)(nil), // 28: proto.daemon.v1.DRKeyASHostResponse + (*DRKeyHostHostRequest)(nil), // 29: proto.daemon.v1.DRKeyHostHostRequest + (*DRKeyHostHostResponse)(nil), // 30: proto.daemon.v1.DRKeyHostHostResponse + nil, // 31: proto.daemon.v1.InterfacesResponse.InterfacesEntry + nil, // 32: proto.daemon.v1.ServicesResponse.ServicesEntry + (*timestamppb.Timestamp)(nil), // 33: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 34: google.protobuf.Duration + (*experimental.FABRIDPolicyIdentifier)(nil), // 35: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + (drkey.Protocol)(0), // 36: proto.drkey.v1.Protocol + (*emptypb.Empty)(nil), // 37: google.protobuf.Empty } var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 3, // 0: proto.daemon.v1.PathsResponse.paths:type_name -> proto.daemon.v1.Path - 13, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface - 7, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface - 30, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp - 31, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration - 8, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates + 16, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface + 10, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface + 33, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp + 34, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration + 11, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates 0, // 6: proto.daemon.v1.Path.link_type:type_name -> proto.daemon.v1.LinkType - 6, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths + 9, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths 4, // 8: proto.daemon.v1.Path.fabrid_policies:type_name -> proto.daemon.v1.FabridPolicies 5, // 9: proto.daemon.v1.FabridPolicies.policies:type_name -> proto.daemon.v1.FabridPolicy - 32, // 10: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier - 28, // 11: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry - 18, // 12: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay - 29, // 13: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry - 17, // 14: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service - 30, // 15: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp - 33, // 16: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 30, // 17: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 30, // 18: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp - 30, // 19: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp - 33, // 20: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 30, // 21: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 30, // 22: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 30, // 23: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp - 33, // 24: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 30, // 25: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 30, // 26: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 13, // 27: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface - 16, // 28: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService - 1, // 29: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest - 9, // 30: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest - 11, // 31: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest - 14, // 32: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest - 19, // 33: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest - 34, // 34: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty - 24, // 35: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest - 22, // 36: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest - 26, // 37: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest - 2, // 38: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse - 10, // 39: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse - 12, // 40: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse - 15, // 41: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse - 20, // 42: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse - 21, // 43: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse - 25, // 44: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse - 23, // 45: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse - 27, // 46: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse - 38, // [38:47] is the sub-list for method output_type - 29, // [29:38] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 35, // 10: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 33, // 11: proto.daemon.v1.FabridKeyResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 33, // 12: proto.daemon.v1.FabridKeyResponse.epoch_end:type_name -> google.protobuf.Timestamp + 7, // 13: proto.daemon.v1.FabridKeysResponse.as_host_keys:type_name -> proto.daemon.v1.FabridKeyResponse + 7, // 14: proto.daemon.v1.FabridKeysResponse.host_host_key:type_name -> proto.daemon.v1.FabridKeyResponse + 31, // 15: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry + 21, // 16: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay + 32, // 17: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry + 20, // 18: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service + 33, // 19: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp + 36, // 20: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 33, // 21: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 33, // 22: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp + 33, // 23: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp + 36, // 24: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 33, // 25: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 33, // 26: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 33, // 27: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp + 36, // 28: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 33, // 29: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 33, // 30: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 16, // 31: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface + 19, // 32: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService + 1, // 33: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest + 12, // 34: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest + 14, // 35: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest + 17, // 36: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest + 22, // 37: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest + 37, // 38: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty + 27, // 39: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest + 25, // 40: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest + 29, // 41: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest + 6, // 42: proto.daemon.v1.DaemonService.FabridKeys:input_type -> proto.daemon.v1.FabridKeysRequest + 2, // 43: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse + 13, // 44: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse + 15, // 45: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse + 18, // 46: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse + 23, // 47: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse + 24, // 48: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse + 28, // 49: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse + 26, // 50: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse + 30, // 51: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse + 8, // 52: proto.daemon.v1.DaemonService.FabridKeys:output_type -> proto.daemon.v1.FabridKeysResponse + 43, // [43:53] is the sub-list for method output_type + 33, // [33:43] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 33, // [33:33] is the sub-list for extension extendee + 0, // [0:33] is the sub-list for field type_name } func init() { file_proto_daemon_v1_daemon_proto_init() } @@ -2153,7 +2387,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EpicAuths); i { + switch v := v.(*FabridKeysRequest); i { case 0: return &v.state case 1: @@ -2165,7 +2399,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PathInterface); i { + switch v := v.(*FabridKeyResponse); i { case 0: return &v.state case 1: @@ -2177,7 +2411,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GeoCoordinates); i { + switch v := v.(*FabridKeysResponse); i { case 0: return &v.state case 1: @@ -2189,7 +2423,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ASRequest); i { + switch v := v.(*EpicAuths); i { case 0: return &v.state case 1: @@ -2201,7 +2435,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ASResponse); i { + switch v := v.(*PathInterface); i { case 0: return &v.state case 1: @@ -2213,7 +2447,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfacesRequest); i { + switch v := v.(*GeoCoordinates); i { case 0: return &v.state case 1: @@ -2225,7 +2459,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfacesResponse); i { + switch v := v.(*ASRequest); i { case 0: return &v.state case 1: @@ -2237,7 +2471,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Interface); i { + switch v := v.(*ASResponse); i { case 0: return &v.state case 1: @@ -2249,7 +2483,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicesRequest); i { + switch v := v.(*InterfacesRequest); i { case 0: return &v.state case 1: @@ -2261,7 +2495,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServicesResponse); i { + switch v := v.(*InterfacesResponse); i { case 0: return &v.state case 1: @@ -2273,7 +2507,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListService); i { + switch v := v.(*Interface); i { case 0: return &v.state case 1: @@ -2285,7 +2519,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Service); i { + switch v := v.(*ServicesRequest); i { case 0: return &v.state case 1: @@ -2297,7 +2531,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Underlay); i { + switch v := v.(*ServicesResponse); i { case 0: return &v.state case 1: @@ -2309,7 +2543,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyInterfaceDownRequest); i { + switch v := v.(*ListService); i { case 0: return &v.state case 1: @@ -2321,7 +2555,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotifyInterfaceDownResponse); i { + switch v := v.(*Service); i { case 0: return &v.state case 1: @@ -2333,7 +2567,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PortRangeResponse); i { + switch v := v.(*Underlay); i { case 0: return &v.state case 1: @@ -2345,7 +2579,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostASRequest); i { + switch v := v.(*NotifyInterfaceDownRequest); i { case 0: return &v.state case 1: @@ -2357,7 +2591,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostASResponse); i { + switch v := v.(*NotifyInterfaceDownResponse); i { case 0: return &v.state case 1: @@ -2369,7 +2603,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyASHostRequest); i { + switch v := v.(*PortRangeResponse); i { case 0: return &v.state case 1: @@ -2381,7 +2615,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyASHostResponse); i { + switch v := v.(*DRKeyHostASRequest); i { case 0: return &v.state case 1: @@ -2393,7 +2627,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyHostHostRequest); i { + switch v := v.(*DRKeyHostASResponse); i { case 0: return &v.state case 1: @@ -2405,6 +2639,42 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DRKeyASHostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DRKeyASHostResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DRKeyHostHostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostHostResponse); i { case 0: return &v.state @@ -2417,13 +2687,15 @@ func file_proto_daemon_v1_daemon_proto_init() { } } } + file_proto_daemon_v1_daemon_proto_msgTypes[5].OneofWrappers = []interface{}{} + file_proto_daemon_v1_daemon_proto_msgTypes[7].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_daemon_v1_daemon_proto_rawDesc, NumEnums: 1, - NumMessages: 29, + NumMessages: 32, NumExtensions: 0, NumServices: 1, }, @@ -2459,6 +2731,7 @@ type DaemonServiceClient interface { DRKeyASHost(ctx context.Context, in *DRKeyASHostRequest, opts ...grpc.CallOption) (*DRKeyASHostResponse, error) DRKeyHostAS(ctx context.Context, in *DRKeyHostASRequest, opts ...grpc.CallOption) (*DRKeyHostASResponse, error) DRKeyHostHost(ctx context.Context, in *DRKeyHostHostRequest, opts ...grpc.CallOption) (*DRKeyHostHostResponse, error) + FabridKeys(ctx context.Context, in *FabridKeysRequest, opts ...grpc.CallOption) (*FabridKeysResponse, error) } type daemonServiceClient struct { @@ -2550,6 +2823,15 @@ func (c *daemonServiceClient) DRKeyHostHost(ctx context.Context, in *DRKeyHostHo return out, nil } +func (c *daemonServiceClient) FabridKeys(ctx context.Context, in *FabridKeysRequest, opts ...grpc.CallOption) (*FabridKeysResponse, error) { + out := new(FabridKeysResponse) + err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/FabridKeys", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // DaemonServiceServer is the server API for DaemonService service. type DaemonServiceServer interface { Paths(context.Context, *PathsRequest) (*PathsResponse, error) @@ -2561,6 +2843,7 @@ type DaemonServiceServer interface { DRKeyASHost(context.Context, *DRKeyASHostRequest) (*DRKeyASHostResponse, error) DRKeyHostAS(context.Context, *DRKeyHostASRequest) (*DRKeyHostASResponse, error) DRKeyHostHost(context.Context, *DRKeyHostHostRequest) (*DRKeyHostHostResponse, error) + FabridKeys(context.Context, *FabridKeysRequest) (*FabridKeysResponse, error) } // UnimplementedDaemonServiceServer can be embedded to have forward compatible implementations. @@ -2594,6 +2877,9 @@ func (*UnimplementedDaemonServiceServer) DRKeyHostAS(context.Context, *DRKeyHost func (*UnimplementedDaemonServiceServer) DRKeyHostHost(context.Context, *DRKeyHostHostRequest) (*DRKeyHostHostResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DRKeyHostHost not implemented") } +func (*UnimplementedDaemonServiceServer) FabridKeys(context.Context, *FabridKeysRequest) (*FabridKeysResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FabridKeys not implemented") +} func RegisterDaemonServiceServer(s *grpc.Server, srv DaemonServiceServer) { s.RegisterService(&_DaemonService_serviceDesc, srv) @@ -2761,6 +3047,24 @@ func _DaemonService_DRKeyHostHost_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _DaemonService_FabridKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FabridKeysRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).FabridKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.daemon.v1.DaemonService/FabridKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).FabridKeys(ctx, req.(*FabridKeysRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _DaemonService_serviceDesc = grpc.ServiceDesc{ ServiceName: "proto.daemon.v1.DaemonService", HandlerType: (*DaemonServiceServer)(nil), @@ -2801,6 +3105,10 @@ var _DaemonService_serviceDesc = grpc.ServiceDesc{ MethodName: "DRKeyHostHost", Handler: _DaemonService_DRKeyHostHost_Handler, }, + { + MethodName: "FabridKeys", + Handler: _DaemonService_FabridKeys_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/daemon/v1/daemon.proto", diff --git a/pkg/proto/drkey/drkey.pb.go b/pkg/proto/drkey/drkey.pb.go index 3b31cb7307..52d98f0d50 100644 --- a/pkg/proto/drkey/drkey.pb.go +++ b/pkg/proto/drkey/drkey.pb.go @@ -25,6 +25,7 @@ type Protocol int32 const ( Protocol_PROTOCOL_GENERIC_UNSPECIFIED Protocol = 0 Protocol_PROTOCOL_SCMP Protocol = 1 + Protocol_PROTOCOL_FABRID Protocol = 2 ) // Enum value maps for Protocol. @@ -32,10 +33,12 @@ var ( Protocol_name = map[int32]string{ 0: "PROTOCOL_GENERIC_UNSPECIFIED", 1: "PROTOCOL_SCMP", + 2: "PROTOCOL_FABRID", } Protocol_value = map[string]int32{ "PROTOCOL_GENERIC_UNSPECIFIED": 0, "PROTOCOL_SCMP": 1, + "PROTOCOL_FABRID": 2, } ) @@ -71,15 +74,17 @@ var File_proto_drkey_v1_drkey_proto protoreflect.FileDescriptor var file_proto_drkey_v1_drkey_proto_rawDesc = []byte{ 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2a, 0x4b, 0x0a, 0x08, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2a, 0x60, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x20, 0x0a, 0x1c, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x49, 0x43, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x53, 0x43, 0x4d, 0x50, 0x10, 0x01, 0x22, 0x0a, 0x08, - 0x80, 0x80, 0x04, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x53, 0x43, 0x4d, 0x50, 0x10, 0x01, 0x12, 0x13, 0x0a, + 0x0f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, + 0x10, 0x02, 0x22, 0x0a, 0x08, 0x80, 0x80, 0x04, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x2d, + 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, + 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index cfeb54f4d9..df3f276147 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -45,6 +45,8 @@ service DaemonService { rpc DRKeyHostAS (DRKeyHostASRequest) returns (DRKeyHostASResponse) {} // DRKeyHostHost returns a key that matches the request. rpc DRKeyHostHost (DRKeyHostHostRequest) returns (DRKeyHostHostResponse) {} + // FabridKeys returns the DRKeys for FABRID + rpc FabridKeys (FabridKeysRequest) returns (FabridKeysResponse) {} } message PathsRequest { @@ -133,6 +135,33 @@ message FabridPolicy { uint32 policy_index = 2; } +message FabridKeysRequest { + // The source host + string src_host = 1; + // The destination AS + uint64 dst_as = 2; + // A list of ASes for which the AS-Host Key should be fetched + repeated uint64 path_ases = 3; + // The destination host. Only required if the path key should be fetched too + optional string dst_host = 4; +} + +message FabridKeyResponse { + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Level2 key. + bytes key = 3; +} + +message FabridKeysResponse { + // The FABRID AS-Host DRKeys + repeated FabridKeyResponse as_host_keys = 1; + // The FABRID path key + optional FabridKeyResponse host_host_key = 2; +} + message EpicAuths { // AuthPHVF is the authenticator use to calculate the PHVF. bytes auth_phvf = 1; diff --git a/proto/drkey/v1/drkey.proto b/proto/drkey/v1/drkey.proto index 560fe309cd..910c8e5e83 100644 --- a/proto/drkey/v1/drkey.proto +++ b/proto/drkey/v1/drkey.proto @@ -23,6 +23,8 @@ enum Protocol{ PROTOCOL_GENERIC_UNSPECIFIED = 0; // SCMP protocol PROTOCOL_SCMP = 1; + // FABRID protocol + PROTOCOL_FABRID = 2; reserved 65536 to max; // only 16-bit values allowed } diff --git a/tools/topology/go.py b/tools/topology/go.py index 72d53639e4..266c7bd0ca 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -171,8 +171,12 @@ def _build_sciond_conf(self, topo_id, ia, base): 'features': translate_features(self.args.features), 'api': { 'addr': socket_address_str(ip, SD_API_PORT+700), - } + }, } + if self.args.fabrid: + raw_entry['drkey_level2_db'] = { + 'connection': os.path.join(self.db_dir, '%s.drkey_level2.db' % name), + } return raw_entry def generate_disp(self): From c466392fc815ba8b68210e2015e0134d3748ac4d Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Fri, 26 Jul 2024 09:01:02 +0200 Subject: [PATCH 04/26] FABRID detachable extensions --- control/cmd/control/main.go | 2 +- control/fabrid/BUILD.bazel | 1 + control/fabrid/fabrid_manager.go | 7 + control/fabrid/grpc/fabrid_service.go | 43 +- control/fabrid/grpc/fabrid_service_test.go | 135 +++- control/fabrid/grpc/fetcher.go | 89 ++- control/fabrid/grpc/fetcher_test.go | 75 +- control/fabrid/grpc/mock_grpc/BUILD.bazel | 2 +- control/fabrid/grpc/mock_grpc/mock.go | 46 +- daemon/cmd/daemon/main.go | 1 + daemon/daemon.go | 2 + daemon/internal/servers/BUILD.bazel | 3 + daemon/internal/servers/grpc.go | 128 +++- pkg/daemon/apitypes.go | 5 +- pkg/daemon/grpc.go | 31 +- .../control_plane/experimental/fabrid.pb.go | 489 +++++++++++-- pkg/proto/daemon/daemon.pb.go | 672 +++++++++--------- pkg/snet/path.go | 39 +- private/path/combinator/BUILD.bazel | 3 + private/path/combinator/fabrid_accumulator.go | 80 +++ .../experimental/v1/fabrid.proto | 26 +- proto/daemon/v1/daemon.proto | 26 +- 22 files changed, 1425 insertions(+), 480 deletions(-) create mode 100644 private/path/combinator/fabrid_accumulator.go diff --git a/control/cmd/control/main.go b/control/cmd/control/main.go index 489cac6fa0..d44ff4ae1d 100644 --- a/control/cmd/control/main.go +++ b/control/cmd/control/main.go @@ -349,7 +349,7 @@ func realMain(ctx context.Context) error { }) // Handle fabrid map and policy requests if globalCfg.Fabrid.Enabled { - polFetcher := fabridgrpc.BasicPolicyFetcher{ + polFetcher := fabridgrpc.BasicFabridControlPlaneFetcher{ Dialer: &libgrpc.QUICDialer{ Rewriter: nc.AddressRewriter(), Dialer: quicStack.Dialer, diff --git a/control/fabrid/BUILD.bazel b/control/fabrid/BUILD.bazel index 9a6597c720..021937a772 100644 --- a/control/fabrid/BUILD.bazel +++ b/control/fabrid/BUILD.bazel @@ -10,6 +10,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//control/config:go_default_library", + "//pkg/addr:go_default_library", "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/segment/extensions/fabrid:go_default_library", diff --git a/control/fabrid/fabrid_manager.go b/control/fabrid/fabrid_manager.go index 3ad5b47235..89d52ed503 100644 --- a/control/fabrid/fabrid_manager.go +++ b/control/fabrid/fabrid_manager.go @@ -22,6 +22,7 @@ import ( "gopkg.in/yaml.v2" "github.com/scionproto/scion/control/config" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" @@ -38,6 +39,10 @@ type RemotePolicyDescription struct { Description string Expires time.Time } +type RemoteMap struct { + Digest []byte + fabrid_ext.Detached +} type FabridManager struct { autoIncrIndex int @@ -47,6 +52,7 @@ type FabridManager struct { IdentifierDescriptionMap map[uint32]string MPLSMap *MplsMaps RemotePolicyCache map[RemotePolicyIdentifier]RemotePolicyDescription + RemoteMapsCache map[addr.IA]RemoteMap RemoteCacheValidity time.Duration } @@ -57,6 +63,7 @@ func NewFabridManager(asInterfaceIDs []uint16, remoteCacheValidity time.Duration IdentifierDescriptionMap: map[uint32]string{}, MPLSMap: NewMplsMaps(), RemotePolicyCache: map[RemotePolicyIdentifier]RemotePolicyDescription{}, + RemoteMapsCache: map[addr.IA]RemoteMap{}, RemoteCacheValidity: remoteCacheValidity, autoIncrIndex: 1, asInterfaceIDs: asInterfaceIDs, diff --git a/control/fabrid/grpc/fabrid_service.go b/control/fabrid/grpc/fabrid_service.go index 695a3ac474..802c08a24a 100644 --- a/control/fabrid/grpc/fabrid_service.go +++ b/control/fabrid/grpc/fabrid_service.go @@ -27,7 +27,7 @@ import ( type Server struct { FabridManager *fabrid.FabridManager - Fetcher PolicyFetcher + Fetcher FabridControlPlaneFetcher } func (s Server) mplsIPMapToPB() map[uint32]*experimental.MPLSIPArray { @@ -88,6 +88,35 @@ func (s Server) RemotePolicyDescription(ctx context.Context, return &experimental.RemotePolicyDescriptionResponse{Description: policy.Description}, nil } +func (s Server) RemoteMaps(ctx context.Context, request *experimental.RemoteMapsRequest) ( + *experimental.RemoteMapsResponse, error) { + + if val, ok := s.FabridManager.RemoteMapsCache[addr.IA(request.IsdAs)]; ok && bytes.Equal(val. + Digest, request.Digest) { + return &experimental.RemoteMapsResponse{ + Maps: &experimental.FABRIDDetachableMaps{ + SupportedIndicesMap: fabridext.SupportedIndicesMapToPB(val.SupportedIndicesMap), + IndexIdentifierMap: fabridext.IndexIdentifierMapToPB(val.IndexIdentiferMap), + }, + }, nil + } + + maps, err := s.Fetcher.GetRemoteMaps(ctx, addr.IA(request.IsdAs)) + if err != nil { + return &experimental.RemoteMapsResponse{}, err + } + detached := fabridext.Detached{ + SupportedIndicesMap: fabridext.SupportedIndicesMapFromPB(maps.Maps.SupportedIndicesMap), + IndexIdentiferMap: fabridext.IndexIdentifierMapFromPB(maps.Maps.IndexIdentifierMap), + } + s.FabridManager.RemoteMapsCache[addr.IA(request.IsdAs)] = fabrid.RemoteMap{ + Detached: detached, + Digest: detached.Hash(), + } + + return &experimental.RemoteMapsResponse{Maps: maps.Maps}, nil +} + func (s Server) SupportedIndicesMap(_ context.Context, _ *experimental.SupportedIndicesMapRequest) (*experimental.SupportedIndicesMapResponse, error) { return &experimental.SupportedIndicesMapResponse{ @@ -103,6 +132,18 @@ func (s Server) IndexIdentifierMap(_ context.Context, _ *experimental.IndexIdent }, nil } +func (s Server) DetachedMaps(_ context.Context, _ *experimental.DetachedMapsRequest) ( + *experimental.DetachedMapsResponse, error) { + return &experimental.DetachedMapsResponse{ + Maps: &experimental.FABRIDDetachableMaps{ + SupportedIndicesMap: fabridext.SupportedIndicesMapToPB(s.FabridManager. + SupportedIndicesMap), + IndexIdentifierMap: fabridext.IndexIdentifierMapToPB(s.FabridManager. + IndexIdentifierMap), + }, + }, nil +} + func (s Server) LocalPolicyDescription(_ context.Context, request *experimental.LocalPolicyDescriptionRequest) ( *experimental.LocalPolicyDescriptionResponse, error) { diff --git a/control/fabrid/grpc/fabrid_service_test.go b/control/fabrid/grpc/fabrid_service_test.go index 383ffa7f9d..0baa1a9a07 100644 --- a/control/fabrid/grpc/fabrid_service_test.go +++ b/control/fabrid/grpc/fabrid_service_test.go @@ -95,7 +95,7 @@ func TestRemotePolicyDescription(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { - fetcher := mock_grpc.NewMockPolicyFetcher(ctrl) + fetcher := mock_grpc.NewMockFabridControlPlaneFetcher(ctrl) fetcher.EXPECT().GetRemotePolicy(gomock.Any(), ia, tc.PolicyIdentifier).Times(tc.ExpectedFetcherCalls).DoAndReturn( func(ctx context.Context, @@ -132,6 +132,139 @@ func TestRemotePolicyDescription(t *testing.T) { }) } } +func TestRemoteMaps_ExistingCacheEntry(t *testing.T) { + ia := xtest.MustParseIA("1-ff00:00:100") + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + fetcher := mock_grpc.NewMockFabridControlPlaneFetcher(ctrl) + manager := &fabrid.FabridManager{ + RemoteMapsCache: make(map[addr.IA]fabrid.RemoteMap), + } + server := Server{Fetcher: fetcher, FabridManager: manager} + expectedMaps := fabrid_ext.Detached{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMap{ + fabrid_ext.ConnectionPair{ + Ingress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}}, + IndexIdentiferMap: fabrid_ext.IndexIdentifierMap{ + 2: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &fabrid_ext.PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + } + manager.RemoteMapsCache[ia] = fabrid.RemoteMap{ + Digest: []byte{0x01, 0x02, 0x03, 0x04}, + Detached: expectedMaps, + } + + fetcher.EXPECT().GetRemoteMaps(gomock.Any(), ia).Times(0) + + request := &experimental.RemoteMapsRequest{IsdAs: uint64(ia), Digest: []byte{0x01, 0x02, + 0x03, 0x04}} + response, err := server.RemoteMaps(ctx, request) + + assert.Nil(t, err) + assert.Equal(t, expectedMaps.SupportedIndicesMap, fabrid_ext.SupportedIndicesMapFromPB( + response.Maps.SupportedIndicesMap)) + assert.Equal(t, expectedMaps.IndexIdentiferMap, fabrid_ext.IndexIdentifierMapFromPB( + response.Maps.IndexIdentifierMap)) +} + +func TestRemoteMaps_NonExistingCacheEntry(t *testing.T) { + ia := xtest.MustParseIA("1-ff00:00:100") + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + fetcher := mock_grpc.NewMockFabridControlPlaneFetcher(ctrl) + manager := &fabrid.FabridManager{ + RemoteMapsCache: make(map[addr.IA]fabrid.RemoteMap), + } + server := Server{Fetcher: fetcher, FabridManager: manager} + expectedMaps := fabrid_ext.Detached{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMap{ + fabrid_ext.ConnectionPair{ + Ingress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}}, + IndexIdentiferMap: fabrid_ext.IndexIdentifierMap{ + 2: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &fabrid_ext.PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + } + + fetcher.EXPECT().GetRemoteMaps(gomock.Any(), ia).Times(1).DoAndReturn(func( + ctx context.Context, + remoteIA addr.IA, + ) (*experimental.DetachedMapsResponse, error) { + return &experimental.DetachedMapsResponse{ + + Maps: &experimental.FABRIDDetachableMaps{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMapToPB(expectedMaps. + SupportedIndicesMap), + IndexIdentifierMap: fabrid_ext.IndexIdentifierMapToPB(expectedMaps. + IndexIdentiferMap), + }, + }, nil + }) + + request := &experimental.RemoteMapsRequest{IsdAs: uint64(ia), Digest: expectedMaps.Hash()} + response, err := server.RemoteMaps(ctx, request) + + assert.Nil(t, err) + assert.Equal(t, expectedMaps.SupportedIndicesMap, fabrid_ext.SupportedIndicesMapFromPB( + response.Maps.SupportedIndicesMap)) + assert.Equal(t, expectedMaps.IndexIdentiferMap, fabrid_ext.IndexIdentifierMapFromPB( + response.Maps.IndexIdentifierMap)) + + //Check if the request is cached. + assert.Equal(t, manager.RemoteMapsCache[ia].Digest, expectedMaps.Hash()) + assert.Equal(t, manager.RemoteMapsCache[ia].SupportedIndicesMap, + expectedMaps.SupportedIndicesMap) + assert.Equal(t, manager.RemoteMapsCache[ia].IndexIdentiferMap, expectedMaps.IndexIdentiferMap) + // The request should now be cached, fetch again to test. + response, err = server.RemoteMaps(ctx, request) + + assert.Nil(t, err) + assert.Equal(t, expectedMaps.SupportedIndicesMap, fabrid_ext.SupportedIndicesMapFromPB( + response.Maps.SupportedIndicesMap)) + assert.Equal(t, expectedMaps.IndexIdentiferMap, fabrid_ext.IndexIdentifierMapFromPB( + response.Maps.IndexIdentifierMap)) +} func TestSupportedIndicesMap(t *testing.T) { supportedIndices := fabrid_ext.SupportedIndicesMap{ diff --git a/control/fabrid/grpc/fetcher.go b/control/fabrid/grpc/fetcher.go index 6b1c4fbb3c..800c983ff6 100644 --- a/control/fabrid/grpc/fetcher.go +++ b/control/fabrid/grpc/fetcher.go @@ -34,12 +34,13 @@ const ( var errNotReachable = serrors.New("remote not reachable") var errNotFound = serrors.New("FABRID local policy is not found") -type PolicyFetcher interface { +type FabridControlPlaneFetcher interface { GetRemotePolicy(ctx context.Context, remoteIA addr.IA, remotePolicyIdentifier uint32) (*experimental.RemotePolicyDescriptionResponse, error) + GetRemoteMaps(ctx context.Context, remoteIA addr.IA) (*experimental.DetachedMapsResponse, error) } -type BasicPolicyFetcher struct { +type BasicFabridControlPlaneFetcher struct { Dialer libgrpc.Dialer Router snet.Router MaxRetries int @@ -47,7 +48,43 @@ type BasicPolicyFetcher struct { errorPaths map[snet.PathFingerprint]struct{} } -func (f *BasicPolicyFetcher) GetRemotePolicy( +func (f *BasicFabridControlPlaneFetcher) GetRemoteMaps( + ctx context.Context, + remoteIA addr.IA, +) (*experimental.DetachedMapsResponse, error) { + var errList serrors.List + f.errorPaths = make(map[snet.PathFingerprint]struct{}) + for i := 0; i < f.MaxRetries; i++ { + rep, err := f.attemptFetchRemote(ctx, remoteIA, func(ctx context.Context, + client experimental.FABRIDInterServiceClient) (interface{}, error) { + return client.DetachedMaps(ctx, &experimental.DetachedMapsRequest{}) + }) + if errors.Is(err, errNotReachable) || (err != nil && strings.Contains(err.Error(), + errNotFound.Error())) { + return &experimental.DetachedMapsResponse{}, serrors.New( + "remote maps fetch fetch failed", "try", i+1, "peer", remoteIA, + "err", err) + } else if err != nil { + errList = append(errList, + serrors.WrapStr("fetching policy", err, "try", i+1, "peer", remoteIA), + ) + continue + } + maps, ok := rep.(*experimental.DetachedMapsResponse) + if !ok { + return &experimental.DetachedMapsResponse{}, serrors.New( + "remote policy fetch fetch failed, invalid response", "try", i+1, + "peer", remoteIA) + } + return maps, nil + } + return &experimental.DetachedMapsResponse{}, serrors.WrapStr( + "reached max retry attempts fetching remote policy", + errList, + ) +} + +func (f *BasicFabridControlPlaneFetcher) GetRemotePolicy( ctx context.Context, remoteIA addr.IA, remotePolicyIdentifier uint32, @@ -55,22 +92,31 @@ func (f *BasicPolicyFetcher) GetRemotePolicy( var errList serrors.List f.errorPaths = make(map[snet.PathFingerprint]struct{}) for i := 0; i < f.MaxRetries; i++ { - rep, err := f.attemptFetchRemotePolicy(ctx, remoteIA, remotePolicyIdentifier) + rep, err := f.attemptFetchRemote(ctx, remoteIA, func(ctx context.Context, + client experimental.FABRIDInterServiceClient) (interface{}, error) { + return client.LocalPolicyDescription(ctx, + &experimental.LocalPolicyDescriptionRequest{ + PolicyIdentifier: remotePolicyIdentifier}) + }) if errors.Is(err, errNotReachable) || (err != nil && strings.Contains(err.Error(), errNotFound.Error())) { return &experimental.RemotePolicyDescriptionResponse{}, serrors.New( - "remote policy fetch fetch failed", - "try", i+1, - "peer", remoteIA, - "err", err, + "remote policy fetch fetch failed", "try", i+1, "peer", remoteIA, + "err", err) + } else if err != nil { + errList = append(errList, + serrors.WrapStr("fetching policy", err, "try", i+1, "peer", remoteIA), ) + continue } - if err == nil { - return rep, nil + policyDescr, ok := rep.(*experimental.LocalPolicyDescriptionResponse) + if !ok { + return &experimental.RemotePolicyDescriptionResponse{}, serrors.New( + "remote policy fetch fetch failed, invalid response", "try", i+1, + "peer", remoteIA) } - errList = append(errList, - serrors.WrapStr("fetching policy", err, "try", i+1, "peer", remoteIA), - ) + return &experimental.RemotePolicyDescriptionResponse{Description: policyDescr. + Description}, nil } return &experimental.RemotePolicyDescriptionResponse{}, serrors.WrapStr( "reached max retry attempts fetching remote policy", @@ -78,11 +124,12 @@ func (f *BasicPolicyFetcher) GetRemotePolicy( ) } -func (f *BasicPolicyFetcher) attemptFetchRemotePolicy( +func (f *BasicFabridControlPlaneFetcher) attemptFetchRemote( ctx context.Context, srcIA addr.IA, - remotePolicyIdentifier uint32, -) (*experimental.RemotePolicyDescriptionResponse, error) { + fetchingFunc func(ctx context.Context, client experimental.FABRIDInterServiceClient) ( + interface{}, error), +) (interface{}, error) { path, err := f.pathToDst(ctx, srcIA) if err != nil { @@ -102,15 +149,15 @@ func (f *BasicPolicyFetcher) attemptFetchRemotePolicy( } defer conn.Close() client := experimental.NewFABRIDInterServiceClient(conn) - rep, err := client.LocalPolicyDescription(ctx, - &experimental.LocalPolicyDescriptionRequest{PolicyIdentifier: remotePolicyIdentifier}) + rep, err := fetchingFunc(ctx, client) if err != nil { - return nil, serrors.WrapStr("requesting policy", err) + return nil, serrors.WrapStr("requesting ", err) } - return &experimental.RemotePolicyDescriptionResponse{Description: rep.Description}, nil + return rep, nil } -func (f *BasicPolicyFetcher) pathToDst(ctx context.Context, dst addr.IA) (snet.Path, error) { +func (f *BasicFabridControlPlaneFetcher) pathToDst(ctx context.Context, dst addr.IA) (snet.Path, + error) { paths, err := f.Router.AllRoutes(ctx, dst) if err != nil { return nil, serrors.Wrap(errNotReachable, err) diff --git a/control/fabrid/grpc/fetcher_test.go b/control/fabrid/grpc/fetcher_test.go index 8f3308b04a..04184857e9 100644 --- a/control/fabrid/grpc/fetcher_test.go +++ b/control/fabrid/grpc/fetcher_test.go @@ -27,6 +27,7 @@ import ( "github.com/scionproto/scion/control/fabrid/grpc" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" "github.com/scionproto/scion/pkg/snet" "github.com/scionproto/scion/pkg/snet/mock_snet" ) @@ -81,11 +82,11 @@ func TestFetchRemotePolicy(t *testing.T) { FabridManager: &fabrid.FabridManager{ IdentifierDescriptionMap: tc.IdentifierDescriptions, }, - Fetcher: &grpc.BasicPolicyFetcher{}, + Fetcher: &grpc.BasicFabridControlPlaneFetcher{}, }) server.Start(t) - fetcher := grpc.BasicPolicyFetcher{ + fetcher := grpc.BasicFabridControlPlaneFetcher{ Dialer: server, Router: router, MaxRetries: 1, @@ -98,3 +99,73 @@ func TestFetchRemotePolicy(t *testing.T) { }) } } + +func TestFetchRemoteMap(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + path := mock_snet.NewMockPath(ctrl) + path.EXPECT().Metadata().AnyTimes().Return(&snet.PathMetadata{ + Interfaces: []snet.PathInterface{}, + }) + path.EXPECT().Dataplane().AnyTimes().Return(nil) + path.EXPECT().UnderlayNextHop().AnyTimes().Return(&net.UDPAddr{}) + + router := mock_snet.NewMockRouter(ctrl) + router.EXPECT().AllRoutes(gomock.Any(), gomock.Any()).AnyTimes().Return([]snet.Path{path}, nil) + maps := fabrid_ext.Detached{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMap{ + fabrid_ext.ConnectionPair{ + Ingress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.IPv4Range, + IP: "192.168.2.0", + Prefix: 24, + }, + Egress: fabrid_ext.ConnectionPoint{ + Type: fabrid_ext.Interface, + InterfaceId: 5, + }, + }: []uint8{2, 8, 15}}, + IndexIdentiferMap: fabrid_ext.IndexIdentifierMap{ + 2: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }, + 8: &fabrid_ext.PolicyIdentifier{ + IsLocal: true, + Identifier: 1, + }, + 15: &fabrid_ext.PolicyIdentifier{ + IsLocal: false, + Identifier: 50, + }, + }, + } + t.Run("fabrid manager returns maps", func(t *testing.T) { + server := xtest.NewGRPCService() + experimental.RegisterFABRIDInterServiceServer(server.Server(), grpc.Server{ + FabridManager: &fabrid.FabridManager{ + SupportedIndicesMap: maps.SupportedIndicesMap, + IndexIdentifierMap: maps.IndexIdentiferMap, + }, + Fetcher: &grpc.BasicFabridControlPlaneFetcher{}, + }) + server.Start(t) + + fetcher := grpc.BasicFabridControlPlaneFetcher{ + Dialer: server, + Router: router, + MaxRetries: 1, + } + + fetchedMaps, err := fetcher.GetRemoteMaps(context.Background(), + xtest.MustParseIA("1-ff00:0:111")) + assert.NoError(t, err) + require.Equal(t, fetchedMaps.Maps.SupportedIndicesMap, + fabrid_ext.SupportedIndicesMapToPB(maps.SupportedIndicesMap)) + require.Equal(t, fetchedMaps.Maps.IndexIdentifierMap, + fabrid_ext.IndexIdentifierMapToPB(maps.IndexIdentiferMap)) + + }) + +} diff --git a/control/fabrid/grpc/mock_grpc/BUILD.bazel b/control/fabrid/grpc/mock_grpc/BUILD.bazel index c058a516c7..4621d48c02 100644 --- a/control/fabrid/grpc/mock_grpc/BUILD.bazel +++ b/control/fabrid/grpc/mock_grpc/BUILD.bazel @@ -4,7 +4,7 @@ load("@io_bazel_rules_go//go:def.bzl", "gomock") gomock( name = "go_default_mock", out = "mock.go", - interfaces = ["PolicyFetcher"], + interfaces = ["FabridControlPlaneFetcher"], library = "//control/fabrid/grpc:go_default_library", package = "mock_grpc", ) diff --git a/control/fabrid/grpc/mock_grpc/mock.go b/control/fabrid/grpc/mock_grpc/mock.go index b6056b9d06..aab563927c 100644 --- a/control/fabrid/grpc/mock_grpc/mock.go +++ b/control/fabrid/grpc/mock_grpc/mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/control/fabrid/grpc (interfaces: PolicyFetcher) +// Source: github.com/scionproto/scion/control/fabrid/grpc (interfaces: FabridControlPlaneFetcher) // Package mock_grpc is a generated GoMock package. package mock_grpc @@ -13,32 +13,46 @@ import ( experimental "github.com/scionproto/scion/pkg/proto/control_plane/experimental" ) -// MockPolicyFetcher is a mock of PolicyFetcher interface. -type MockPolicyFetcher struct { +// MockFabridControlPlaneFetcher is a mock of FabridControlPlaneFetcher interface. +type MockFabridControlPlaneFetcher struct { ctrl *gomock.Controller - recorder *MockPolicyFetcherMockRecorder + recorder *MockFabridControlPlaneFetcherMockRecorder } -// MockPolicyFetcherMockRecorder is the mock recorder for MockPolicyFetcher. -type MockPolicyFetcherMockRecorder struct { - mock *MockPolicyFetcher +// MockFabridControlPlaneFetcherMockRecorder is the mock recorder for MockFabridControlPlaneFetcher. +type MockFabridControlPlaneFetcherMockRecorder struct { + mock *MockFabridControlPlaneFetcher } -// NewMockPolicyFetcher creates a new mock instance. -func NewMockPolicyFetcher(ctrl *gomock.Controller) *MockPolicyFetcher { - mock := &MockPolicyFetcher{ctrl: ctrl} - mock.recorder = &MockPolicyFetcherMockRecorder{mock} +// NewMockFabridControlPlaneFetcher creates a new mock instance. +func NewMockFabridControlPlaneFetcher(ctrl *gomock.Controller) *MockFabridControlPlaneFetcher { + mock := &MockFabridControlPlaneFetcher{ctrl: ctrl} + mock.recorder = &MockFabridControlPlaneFetcherMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPolicyFetcher) EXPECT() *MockPolicyFetcherMockRecorder { +func (m *MockFabridControlPlaneFetcher) EXPECT() *MockFabridControlPlaneFetcherMockRecorder { return m.recorder } +// GetRemoteMaps mocks base method. +func (m *MockFabridControlPlaneFetcher) GetRemoteMaps(arg0 context.Context, arg1 addr.IA) (*experimental.DetachedMapsResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRemoteMaps", arg0, arg1) + ret0, _ := ret[0].(*experimental.DetachedMapsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRemoteMaps indicates an expected call of GetRemoteMaps. +func (mr *MockFabridControlPlaneFetcherMockRecorder) GetRemoteMaps(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemoteMaps", reflect.TypeOf((*MockFabridControlPlaneFetcher)(nil).GetRemoteMaps), arg0, arg1) +} + // GetRemotePolicy mocks base method. -func (m *MockPolicyFetcher) GetRemotePolicy(arg0 context.Context, arg1 addr.IA, - arg2 uint32) (*experimental.RemotePolicyDescriptionResponse, error) { +func (m *MockFabridControlPlaneFetcher) GetRemotePolicy(arg0 context.Context, arg1 addr.IA, arg2 uint32) (*experimental.RemotePolicyDescriptionResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetRemotePolicy", arg0, arg1, arg2) ret0, _ := ret[0].(*experimental.RemotePolicyDescriptionResponse) @@ -47,7 +61,7 @@ func (m *MockPolicyFetcher) GetRemotePolicy(arg0 context.Context, arg1 addr.IA, } // GetRemotePolicy indicates an expected call of GetRemotePolicy. -func (mr *MockPolicyFetcherMockRecorder) GetRemotePolicy(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockFabridControlPlaneFetcherMockRecorder) GetRemotePolicy(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemotePolicy", reflect.TypeOf((*MockPolicyFetcher)(nil).GetRemotePolicy), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemotePolicy", reflect.TypeOf((*MockFabridControlPlaneFetcher)(nil).GetRemotePolicy), arg0, arg1, arg2) } diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index e3254e0ce2..bb93df21f3 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -285,6 +285,7 @@ func realMain(ctx context.Context) error { Cfg: globalCfg.SD, }, ), + Dialer: dialer, Engine: engine, RevCache: revCache, DRKeyClient: drkeyClientEngine, diff --git a/daemon/daemon.go b/daemon/daemon.go index 30c92918bc..0e61171754 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -114,6 +114,7 @@ type ServerConfig struct { Engine trust.Engine Topology servers.Topology DRKeyClient *drkey.ClientEngine + Dialer libgrpc.Dialer } // NewServer constructs a daemon API server. @@ -129,6 +130,7 @@ func NewServer(cfg ServerConfig) *servers.DaemonServer { ASInspector: cfg.Engine.Inspector, RevCache: cfg.RevCache, DRKeyClient: cfg.DRKeyClient, + Dialer: cfg.Dialer, Metrics: servers.Metrics{ PathsRequests: servers.RequestMetrics{ Requests: metrics.NewPromCounterFrom(prometheus.CounterOpts{ diff --git a/daemon/internal/servers/BUILD.bazel b/daemon/internal/servers/BUILD.bazel index a5d3a6627e..01e28ca333 100644 --- a/daemon/internal/servers/BUILD.bazel +++ b/daemon/internal/servers/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/experimental/fabrid:go_default_library", + "//pkg/grpc:go_default_library", "//pkg/log:go_default_library", "//pkg/metrics:go_default_library", "//pkg/private/common:go_default_library", @@ -24,8 +25,10 @@ go_library( "//pkg/private/util:go_default_library", "//pkg/proto/control_plane/experimental:go_default_library", "//pkg/proto/daemon:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/path:go_default_library", + "//private/path/combinator:go_default_library", "//private/revcache:go_default_library", "//private/topology:go_default_library", "//private/trust:go_default_library", diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index 0e182058fc..5592ee5606 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -31,6 +31,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/experimental/fabrid" + libgrpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/ctrl/path_mgmt" @@ -41,8 +42,10 @@ import ( "github.com/scionproto/scion/pkg/proto/control_plane/experimental" pb_daemon "github.com/scionproto/scion/pkg/proto/daemon" sdpb "github.com/scionproto/scion/pkg/proto/daemon" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" "github.com/scionproto/scion/pkg/snet" snetpath "github.com/scionproto/scion/pkg/snet/path" + "github.com/scionproto/scion/private/path/combinator" "github.com/scionproto/scion/private/revcache" "github.com/scionproto/scion/private/topology" "github.com/scionproto/scion/private/trust" @@ -64,8 +67,8 @@ type DaemonServer struct { RevCache revcache.RevCache ASInspector trust.Inspector DRKeyClient *drkey_daemon.ClientEngine - - Metrics Metrics + Dialer libgrpc.Dialer + Metrics Metrics foregroundPathDedupe singleflight.Group backgroundPathDedupe singleflight.Group @@ -104,6 +107,13 @@ func (s *DaemonServer) paths(ctx context.Context, "src", srcIA, "dst", dstIA, "refresh", req.Refresh) return nil, err } + if req.FetchFabridDetachedMaps { + detachedHops := findDetachedHops(paths) + if len(detachedHops) > 0 { + log.Info("Detached hops found", "hops", len(detachedHops)) + updateFabridInfo(ctx, s.Dialer, detachedHops) + } + } reply := &sdpb.PathsResponse{} for _, p := range paths { reply.Paths = append(reply.Paths, pathToPB(p)) @@ -111,6 +121,100 @@ func (s *DaemonServer) paths(ctx context.Context, return reply, nil } +type tempHopInfo struct { + IA addr.IA + Meta *snet.PathMetadata + fiIdx int + Ingress uint16 + Egress uint16 +} + +// updateFabridInfo updates the FABRID info that is contained in the path Metadata for detached +// hops, by fetching the corresponding FABRID maps from the corresponding AS. +func updateFabridInfo(ctx context.Context, dialer libgrpc.Dialer, detachedHops []tempHopInfo) { + conn, err := dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) + if err != nil { + log.FromCtx(ctx).Debug("Dialing CS failed", "err", err) + } + defer conn.Close() + client := experimental.NewFABRIDIntraServiceClient(conn) + fabridMaps := make(map[addr.IA]combinator.FabridMapEntry) + for _, detachedHop := range detachedHops { + if _, ok := fabridMaps[detachedHop.IA]; !ok { + fabridMaps[detachedHop.IA] = fetchMaps(ctx, detachedHop.IA, client, + detachedHop.Meta.FabridInfo[detachedHop.fiIdx].Digest) + } + detachedHop.Meta.FabridInfo[detachedHop.fiIdx] = *combinator. + GetFabridInfoForIntfs(detachedHop.IA, detachedHop.Ingress, detachedHop.Egress, + fabridMaps, true) + } +} + +// findDetachedHops finds the hops where the FABRID maps have been detached in a given list of +// paths. +func findDetachedHops(paths []snet.Path) []tempHopInfo { + detachedHops := make([]tempHopInfo, 0) + for _, p := range paths { + if p.Metadata().FabridInfo[0].Enabled && p.Metadata().FabridInfo[0].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[0].IA, + Meta: p.Metadata(), + fiIdx: 0, + Ingress: 0, + Egress: uint16(p.Metadata().Interfaces[0].ID), + }) + } + for i := 1; i < len(p.Metadata().Interfaces)-1; i += 2 { + if p.Metadata().FabridInfo[(i+1)/2].Enabled && + p.Metadata().FabridInfo[(i+1)/2].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[i].IA, + Meta: p.Metadata(), + fiIdx: (i + 1) / 2, + Ingress: uint16(p.Metadata().Interfaces[i].ID), + Egress: uint16(p.Metadata().Interfaces[i+1].ID), + }) + } + } + if p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Enabled && + p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].IA, + Meta: p.Metadata(), + fiIdx: len(p.Metadata().Interfaces) / 2, + Ingress: uint16(p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].ID), + Egress: 0, + }) + } + } + return detachedHops +} + +// fetchMaps retrieves FABRID maps from the Control Service for a given ISD-AS. +// It uses the provided client to communicate with the Control Service and returns a FabridMapEntry +// to be used directly in the combinator. +func fetchMaps(ctx context.Context, ia addr.IA, client experimental.FABRIDIntraServiceClient, + digest []byte) combinator.FabridMapEntry { + maps, err := client.RemoteMaps(ctx, &experimental.RemoteMapsRequest{ + Digest: digest, + IsdAs: uint64(ia), + }) + if err != nil || maps.Maps == nil { + log.FromCtx(ctx).Debug("Retrieving remote map from CS failed", "err", err, "ia", + ia) + return combinator.FabridMapEntry{} + } + + detached := fabrid_ext.Detached{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMapFromPB(maps.Maps.SupportedIndicesMap), + IndexIdentiferMap: fabrid_ext.IndexIdentifierMapFromPB(maps.Maps.IndexIdentifierMap), + } + return combinator.FabridMapEntry{ + Map: &detached, + Ts: time.Now(), + Digest: []byte{}, // leave empty, it can be calculated using detached.Hash() + } +} func (s *DaemonServer) fetchPaths( ctx context.Context, group *singleflight.Group, @@ -167,9 +271,9 @@ func pathToPB(path snet.Path) *sdpb.Path { if nextHop := path.UnderlayNextHop(); nextHop != nil { nextHopStr = nextHop.String() } - fabridPolicies := make([]*sdpb.FabridPolicies, len(meta.FabridPolicies)) - for i, v := range meta.FabridPolicies { - fabridPolicies[i] = fabridPoliciesToPB(v) + fabridInfo := make([]*sdpb.FabridInfo, len(meta.FabridInfo)) + for i, v := range meta.FabridInfo { + fabridInfo[i] = fabridInfoToPB(&v) } epicAuths := &sdpb.EpicAuths{ AuthPhvf: append([]byte(nil), meta.EpicAuths.AuthPHVF...), @@ -192,8 +296,7 @@ func pathToPB(path snet.Path) *sdpb.Path { InternalHops: meta.InternalHops, Notes: meta.Notes, EpicAuths: epicAuths, - FabridEnabled: meta.FabridEnabled, - FabridPolicies: fabridPolicies, + FabridInfo: fabridInfo, } } @@ -207,13 +310,16 @@ func fabridPolicyToPB(fp *fabrid.Policy) *sdpb.FabridPolicy { } } -func fabridPoliciesToPB(fpList []*fabrid.Policy) *sdpb.FabridPolicies { - pbPolicies := make([]*sdpb.FabridPolicy, len(fpList)) - for i, fp := range fpList { +func fabridInfoToPB(fi *snet.FabridInfo) *sdpb.FabridInfo { + pbPolicies := make([]*sdpb.FabridPolicy, len(fi.Policies)) + for i, fp := range fi.Policies { pbPolicies[i] = fabridPolicyToPB(fp) } - return &sdpb.FabridPolicies{ + return &sdpb.FabridInfo{ + Enabled: fi.Enabled, + Digest: fi.Digest, Policies: pbPolicies, + Detached: fi.Detached, } } func linkTypeToPB(lt snet.LinkType) sdpb.LinkType { diff --git a/pkg/daemon/apitypes.go b/pkg/daemon/apitypes.go index 4b4564bef8..0ecb283267 100644 --- a/pkg/daemon/apitypes.go +++ b/pkg/daemon/apitypes.go @@ -27,8 +27,9 @@ import ( ) type PathReqFlags struct { - Refresh bool - Hidden bool + Refresh bool + Hidden bool + FetchFabridDetachedMaps bool } // ASInfo provides information about the local AS. diff --git a/pkg/daemon/grpc.go b/pkg/daemon/grpc.go index 929d99c664..8e2a5ac6c3 100644 --- a/pkg/daemon/grpc.go +++ b/pkg/daemon/grpc.go @@ -111,10 +111,11 @@ func (c grpcConn) Paths(ctx context.Context, dst, src addr.IA, client := sdpb.NewDaemonServiceClient(c.conn) response, err := client.Paths(ctx, &sdpb.PathsRequest{ - SourceIsdAs: uint64(src), - DestinationIsdAs: uint64(dst), - Hidden: f.Hidden, - Refresh: f.Refresh, + SourceIsdAs: uint64(src), + DestinationIsdAs: uint64(dst), + Hidden: f.Hidden, + Refresh: f.Refresh, + FetchFabridDetachedMaps: f.FetchFabridDetachedMaps, }) if err != nil { c.metrics.incPaths(err) @@ -333,9 +334,9 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { linkType[i] = linkTypeFromPB(v) } - policyIdentifiers := make([][]*fabrid.Policy, len(p.FabridPolicies)) - for i, v := range p.FabridPolicies { - policyIdentifiers[i] = fabridPoliciesFromPB(v) + fabridInfo := make([]snet.FabridInfo, len(p.FabridInfo)) + for i, v := range p.FabridInfo { + fabridInfo[i] = fabridInfoFromPB(v) } res := path.Path{ @@ -356,8 +357,7 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { LinkType: linkType, InternalHops: p.InternalHops, Notes: p.Notes, - FabridEnabled: p.FabridEnabled, - FabridPolicies: policyIdentifiers, + FabridInfo: fabridInfo, }, } @@ -371,16 +371,21 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { return res, nil } -func fabridPoliciesFromPB(fpList *sdpb.FabridPolicies) []*fabrid.Policy { - pbPolicies := make([]*fabrid.Policy, len(fpList.Policies)) - for i, fp := range fpList.Policies { +func fabridInfoFromPB(fi *sdpb.FabridInfo) snet.FabridInfo { + pbPolicies := make([]*fabrid.Policy, len(fi.Policies)) + for i, fp := range fi.Policies { pbPolicies[i] = &fabrid.Policy{ IsLocal: fp.PolicyIdentifier.PolicyIsLocal, Identifier: fp.PolicyIdentifier.PolicyIdentifier, Index: fabrid.PolicyID(fp.PolicyIndex), } } - return pbPolicies + return snet.FabridInfo{ + Enabled: fi.Enabled, + Policies: pbPolicies, + Digest: fi.Digest, + Detached: fi.Detached, + } } func linkTypeFromPB(lt sdpb.LinkType) snet.LinkType { diff --git a/pkg/proto/control_plane/experimental/fabrid.pb.go b/pkg/proto/control_plane/experimental/fabrid.pb.go index c9b8037b8a..8b2f8f1195 100755 --- a/pkg/proto/control_plane/experimental/fabrid.pb.go +++ b/pkg/proto/control_plane/experimental/fabrid.pb.go @@ -618,6 +618,193 @@ func (x *LocalPolicyDescriptionResponse) GetDescription() string { return "" } +type RemoteMapsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Digest []byte `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"` + IsdAs uint64 `protobuf:"varint,2,opt,name=isd_as,json=isdAs,proto3" json:"isd_as,omitempty"` +} + +func (x *RemoteMapsRequest) Reset() { + *x = RemoteMapsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoteMapsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoteMapsRequest) ProtoMessage() {} + +func (x *RemoteMapsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoteMapsRequest.ProtoReflect.Descriptor instead. +func (*RemoteMapsRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{12} +} + +func (x *RemoteMapsRequest) GetDigest() []byte { + if x != nil { + return x.Digest + } + return nil +} + +func (x *RemoteMapsRequest) GetIsdAs() uint64 { + if x != nil { + return x.IsdAs + } + return 0 +} + +type RemoteMapsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Maps *FABRIDDetachableMaps `protobuf:"bytes,1,opt,name=maps,proto3" json:"maps,omitempty"` +} + +func (x *RemoteMapsResponse) Reset() { + *x = RemoteMapsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoteMapsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoteMapsResponse) ProtoMessage() {} + +func (x *RemoteMapsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoteMapsResponse.ProtoReflect.Descriptor instead. +func (*RemoteMapsResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{13} +} + +func (x *RemoteMapsResponse) GetMaps() *FABRIDDetachableMaps { + if x != nil { + return x.Maps + } + return nil +} + +type DetachedMapsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DetachedMapsRequest) Reset() { + *x = DetachedMapsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachedMapsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachedMapsRequest) ProtoMessage() {} + +func (x *DetachedMapsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachedMapsRequest.ProtoReflect.Descriptor instead. +func (*DetachedMapsRequest) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{14} +} + +type DetachedMapsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Maps *FABRIDDetachableMaps `protobuf:"bytes,1,opt,name=maps,proto3" json:"maps,omitempty"` +} + +func (x *DetachedMapsResponse) Reset() { + *x = DetachedMapsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachedMapsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachedMapsResponse) ProtoMessage() {} + +func (x *DetachedMapsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachedMapsResponse.ProtoReflect.Descriptor instead. +func (*DetachedMapsResponse) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP(), []int{15} +} + +func (x *DetachedMapsResponse) GetMaps() *FABRIDDetachableMaps { + if x != nil { + return x.Maps + } + return nil +} + var File_proto_control_plane_experimental_v1_fabrid_proto protoreflect.FileDescriptor var file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc = []byte{ @@ -725,50 +912,85 @@ var file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc = []byte{ 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xf1, 0x03, 0x0a, 0x12, 0x46, 0x41, - 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x9a, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x3f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, - 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, - 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x42, 0x0a, 0x11, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x22, 0x63, 0x0a, + 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, + 0x74, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x04, 0x6d, 0x61, + 0x70, 0x73, 0x22, 0x15, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, + 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x65, 0x0a, 0x14, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x04, 0x6d, 0x61, 0x70, 0x73, + 0x32, 0xf9, 0x04, 0x0a, 0x12, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, + 0x3f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x40, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x3e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x85, + 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, 0x12, + 0x38, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, + 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x97, 0x01, - 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x4d, 0x61, 0x70, 0x12, 0x3e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, - 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, - 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4d, 0x61, 0x70, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa3, 0x01, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x42, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, - 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0xb5, 0x02, - 0x0a, 0x12, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, - 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x6c, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xa3, 0x01, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x42, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, - 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, + 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0xb6, 0x03, 0x0a, + 0x12, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x43, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, + 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7f, 0x0a, 0x0a, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x36, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4d, + 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x07, 0x4d, 0x50, 0x4c, 0x53, 0x4d, 0x61, 0x70, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4d, @@ -796,7 +1018,7 @@ func file_proto_control_plane_experimental_v1_fabrid_proto_rawDescGZIP() []byte return file_proto_control_plane_experimental_v1_fabrid_proto_rawDescData } -var file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_proto_control_plane_experimental_v1_fabrid_proto_goTypes = []interface{}{ (*MPLSIPArray)(nil), // 0: proto.control_plane.experimental.v1.MPLSIPArray (*MPLSIP)(nil), // 1: proto.control_plane.experimental.v1.MPLSIP @@ -810,35 +1032,46 @@ var file_proto_control_plane_experimental_v1_fabrid_proto_goTypes = []interface{ (*RemotePolicyDescriptionResponse)(nil), // 9: proto.control_plane.experimental.v1.RemotePolicyDescriptionResponse (*LocalPolicyDescriptionRequest)(nil), // 10: proto.control_plane.experimental.v1.LocalPolicyDescriptionRequest (*LocalPolicyDescriptionResponse)(nil), // 11: proto.control_plane.experimental.v1.LocalPolicyDescriptionResponse - nil, // 12: proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry - nil, // 13: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry - nil, // 14: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry - (*FABRIDIndexMapEntry)(nil), // 15: proto.control_plane.experimental.v1.FABRIDIndexMapEntry - (*FABRIDPolicyIdentifier)(nil), // 16: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + (*RemoteMapsRequest)(nil), // 12: proto.control_plane.experimental.v1.RemoteMapsRequest + (*RemoteMapsResponse)(nil), // 13: proto.control_plane.experimental.v1.RemoteMapsResponse + (*DetachedMapsRequest)(nil), // 14: proto.control_plane.experimental.v1.DetachedMapsRequest + (*DetachedMapsResponse)(nil), // 15: proto.control_plane.experimental.v1.DetachedMapsResponse + nil, // 16: proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry + nil, // 17: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry + nil, // 18: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry + (*FABRIDIndexMapEntry)(nil), // 19: proto.control_plane.experimental.v1.FABRIDIndexMapEntry + (*FABRIDDetachableMaps)(nil), // 20: proto.control_plane.experimental.v1.FABRIDDetachableMaps + (*FABRIDPolicyIdentifier)(nil), // 21: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier } var file_proto_control_plane_experimental_v1_fabrid_proto_depIdxs = []int32{ 1, // 0: proto.control_plane.experimental.v1.MPLSIPArray.entry:type_name -> proto.control_plane.experimental.v1.MPLSIP - 12, // 1: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_interface_policies_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry - 13, // 2: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_ip_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry - 15, // 3: proto.control_plane.experimental.v1.SupportedIndicesMapResponse.supported_indices_map:type_name -> proto.control_plane.experimental.v1.FABRIDIndexMapEntry - 14, // 4: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.index_identifier_map:type_name -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry - 0, // 5: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry.value:type_name -> proto.control_plane.experimental.v1.MPLSIPArray - 16, // 6: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry.value:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier - 4, // 7: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:input_type -> proto.control_plane.experimental.v1.SupportedIndicesMapRequest - 6, // 8: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:input_type -> proto.control_plane.experimental.v1.IndexIdentifierMapRequest - 10, // 9: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:input_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionRequest - 8, // 10: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:input_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionRequest - 2, // 11: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:input_type -> proto.control_plane.experimental.v1.MPLSMapRequest - 5, // 12: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:output_type -> proto.control_plane.experimental.v1.SupportedIndicesMapResponse - 7, // 13: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:output_type -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse - 11, // 14: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:output_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionResponse - 9, // 15: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:output_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionResponse - 3, // 16: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:output_type -> proto.control_plane.experimental.v1.MPLSMapResponse - 12, // [12:17] is the sub-list for method output_type - 7, // [7:12] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 16, // 1: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_interface_policies_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsInterfacePoliciesMapEntry + 17, // 2: proto.control_plane.experimental.v1.MPLSMapResponse.mpls_ip_map:type_name -> proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry + 19, // 3: proto.control_plane.experimental.v1.SupportedIndicesMapResponse.supported_indices_map:type_name -> proto.control_plane.experimental.v1.FABRIDIndexMapEntry + 18, // 4: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.index_identifier_map:type_name -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry + 20, // 5: proto.control_plane.experimental.v1.RemoteMapsResponse.maps:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps + 20, // 6: proto.control_plane.experimental.v1.DetachedMapsResponse.maps:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps + 0, // 7: proto.control_plane.experimental.v1.MPLSMapResponse.MplsIpMapEntry.value:type_name -> proto.control_plane.experimental.v1.MPLSIPArray + 21, // 8: proto.control_plane.experimental.v1.IndexIdentifierMapResponse.IndexIdentifierMapEntry.value:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 4, // 9: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:input_type -> proto.control_plane.experimental.v1.SupportedIndicesMapRequest + 6, // 10: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:input_type -> proto.control_plane.experimental.v1.IndexIdentifierMapRequest + 14, // 11: proto.control_plane.experimental.v1.FABRIDInterService.DetachedMaps:input_type -> proto.control_plane.experimental.v1.DetachedMapsRequest + 10, // 12: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:input_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionRequest + 8, // 13: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:input_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionRequest + 12, // 14: proto.control_plane.experimental.v1.FABRIDIntraService.RemoteMaps:input_type -> proto.control_plane.experimental.v1.RemoteMapsRequest + 2, // 15: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:input_type -> proto.control_plane.experimental.v1.MPLSMapRequest + 5, // 16: proto.control_plane.experimental.v1.FABRIDInterService.SupportedIndicesMap:output_type -> proto.control_plane.experimental.v1.SupportedIndicesMapResponse + 7, // 17: proto.control_plane.experimental.v1.FABRIDInterService.IndexIdentifierMap:output_type -> proto.control_plane.experimental.v1.IndexIdentifierMapResponse + 15, // 18: proto.control_plane.experimental.v1.FABRIDInterService.DetachedMaps:output_type -> proto.control_plane.experimental.v1.DetachedMapsResponse + 11, // 19: proto.control_plane.experimental.v1.FABRIDInterService.LocalPolicyDescription:output_type -> proto.control_plane.experimental.v1.LocalPolicyDescriptionResponse + 9, // 20: proto.control_plane.experimental.v1.FABRIDIntraService.RemotePolicyDescription:output_type -> proto.control_plane.experimental.v1.RemotePolicyDescriptionResponse + 13, // 21: proto.control_plane.experimental.v1.FABRIDIntraService.RemoteMaps:output_type -> proto.control_plane.experimental.v1.RemoteMapsResponse + 3, // 22: proto.control_plane.experimental.v1.FABRIDIntraService.MPLSMap:output_type -> proto.control_plane.experimental.v1.MPLSMapResponse + 16, // [16:23] is the sub-list for method output_type + 9, // [9:16] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_proto_control_plane_experimental_v1_fabrid_proto_init() } @@ -992,6 +1225,54 @@ func file_proto_control_plane_experimental_v1_fabrid_proto_init() { return nil } } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoteMapsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoteMapsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachedMapsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_control_plane_experimental_v1_fabrid_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachedMapsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -999,7 +1280,7 @@ func file_proto_control_plane_experimental_v1_fabrid_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_control_plane_experimental_v1_fabrid_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 19, NumExtensions: 0, NumServices: 2, }, @@ -1027,6 +1308,7 @@ const _ = grpc.SupportPackageIsVersion6 type FABRIDInterServiceClient interface { SupportedIndicesMap(ctx context.Context, in *SupportedIndicesMapRequest, opts ...grpc.CallOption) (*SupportedIndicesMapResponse, error) IndexIdentifierMap(ctx context.Context, in *IndexIdentifierMapRequest, opts ...grpc.CallOption) (*IndexIdentifierMapResponse, error) + DetachedMaps(ctx context.Context, in *DetachedMapsRequest, opts ...grpc.CallOption) (*DetachedMapsResponse, error) LocalPolicyDescription(ctx context.Context, in *LocalPolicyDescriptionRequest, opts ...grpc.CallOption) (*LocalPolicyDescriptionResponse, error) } @@ -1056,6 +1338,15 @@ func (c *fABRIDInterServiceClient) IndexIdentifierMap(ctx context.Context, in *I return out, nil } +func (c *fABRIDInterServiceClient) DetachedMaps(ctx context.Context, in *DetachedMapsRequest, opts ...grpc.CallOption) (*DetachedMapsResponse, error) { + out := new(DetachedMapsResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDInterService/DetachedMaps", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *fABRIDInterServiceClient) LocalPolicyDescription(ctx context.Context, in *LocalPolicyDescriptionRequest, opts ...grpc.CallOption) (*LocalPolicyDescriptionResponse, error) { out := new(LocalPolicyDescriptionResponse) err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDInterService/LocalPolicyDescription", in, out, opts...) @@ -1069,6 +1360,7 @@ func (c *fABRIDInterServiceClient) LocalPolicyDescription(ctx context.Context, i type FABRIDInterServiceServer interface { SupportedIndicesMap(context.Context, *SupportedIndicesMapRequest) (*SupportedIndicesMapResponse, error) IndexIdentifierMap(context.Context, *IndexIdentifierMapRequest) (*IndexIdentifierMapResponse, error) + DetachedMaps(context.Context, *DetachedMapsRequest) (*DetachedMapsResponse, error) LocalPolicyDescription(context.Context, *LocalPolicyDescriptionRequest) (*LocalPolicyDescriptionResponse, error) } @@ -1082,6 +1374,9 @@ func (*UnimplementedFABRIDInterServiceServer) SupportedIndicesMap(context.Contex func (*UnimplementedFABRIDInterServiceServer) IndexIdentifierMap(context.Context, *IndexIdentifierMapRequest) (*IndexIdentifierMapResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method IndexIdentifierMap not implemented") } +func (*UnimplementedFABRIDInterServiceServer) DetachedMaps(context.Context, *DetachedMapsRequest) (*DetachedMapsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DetachedMaps not implemented") +} func (*UnimplementedFABRIDInterServiceServer) LocalPolicyDescription(context.Context, *LocalPolicyDescriptionRequest) (*LocalPolicyDescriptionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method LocalPolicyDescription not implemented") } @@ -1126,6 +1421,24 @@ func _FABRIDInterService_IndexIdentifierMap_Handler(srv interface{}, ctx context return interceptor(ctx, in, info, handler) } +func _FABRIDInterService_DetachedMaps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DetachedMapsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDInterServiceServer).DetachedMaps(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDInterService/DetachedMaps", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDInterServiceServer).DetachedMaps(ctx, req.(*DetachedMapsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _FABRIDInterService_LocalPolicyDescription_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(LocalPolicyDescriptionRequest) if err := dec(in); err != nil { @@ -1156,6 +1469,10 @@ var _FABRIDInterService_serviceDesc = grpc.ServiceDesc{ MethodName: "IndexIdentifierMap", Handler: _FABRIDInterService_IndexIdentifierMap_Handler, }, + { + MethodName: "DetachedMaps", + Handler: _FABRIDInterService_DetachedMaps_Handler, + }, { MethodName: "LocalPolicyDescription", Handler: _FABRIDInterService_LocalPolicyDescription_Handler, @@ -1170,6 +1487,7 @@ var _FABRIDInterService_serviceDesc = grpc.ServiceDesc{ // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type FABRIDIntraServiceClient interface { RemotePolicyDescription(ctx context.Context, in *RemotePolicyDescriptionRequest, opts ...grpc.CallOption) (*RemotePolicyDescriptionResponse, error) + RemoteMaps(ctx context.Context, in *RemoteMapsRequest, opts ...grpc.CallOption) (*RemoteMapsResponse, error) MPLSMap(ctx context.Context, in *MPLSMapRequest, opts ...grpc.CallOption) (*MPLSMapResponse, error) } @@ -1190,6 +1508,15 @@ func (c *fABRIDIntraServiceClient) RemotePolicyDescription(ctx context.Context, return out, nil } +func (c *fABRIDIntraServiceClient) RemoteMaps(ctx context.Context, in *RemoteMapsRequest, opts ...grpc.CallOption) (*RemoteMapsResponse, error) { + out := new(RemoteMapsResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDIntraService/RemoteMaps", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *fABRIDIntraServiceClient) MPLSMap(ctx context.Context, in *MPLSMapRequest, opts ...grpc.CallOption) (*MPLSMapResponse, error) { out := new(MPLSMapResponse) err := c.cc.Invoke(ctx, "/proto.control_plane.experimental.v1.FABRIDIntraService/MPLSMap", in, out, opts...) @@ -1202,6 +1529,7 @@ func (c *fABRIDIntraServiceClient) MPLSMap(ctx context.Context, in *MPLSMapReque // FABRIDIntraServiceServer is the server API for FABRIDIntraService service. type FABRIDIntraServiceServer interface { RemotePolicyDescription(context.Context, *RemotePolicyDescriptionRequest) (*RemotePolicyDescriptionResponse, error) + RemoteMaps(context.Context, *RemoteMapsRequest) (*RemoteMapsResponse, error) MPLSMap(context.Context, *MPLSMapRequest) (*MPLSMapResponse, error) } @@ -1212,6 +1540,9 @@ type UnimplementedFABRIDIntraServiceServer struct { func (*UnimplementedFABRIDIntraServiceServer) RemotePolicyDescription(context.Context, *RemotePolicyDescriptionRequest) (*RemotePolicyDescriptionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemotePolicyDescription not implemented") } +func (*UnimplementedFABRIDIntraServiceServer) RemoteMaps(context.Context, *RemoteMapsRequest) (*RemoteMapsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoteMaps not implemented") +} func (*UnimplementedFABRIDIntraServiceServer) MPLSMap(context.Context, *MPLSMapRequest) (*MPLSMapResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method MPLSMap not implemented") } @@ -1238,6 +1569,24 @@ func _FABRIDIntraService_RemotePolicyDescription_Handler(srv interface{}, ctx co return interceptor(ctx, in, info, handler) } +func _FABRIDIntraService_RemoteMaps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoteMapsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FABRIDIntraServiceServer).RemoteMaps(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.experimental.v1.FABRIDIntraService/RemoteMaps", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FABRIDIntraServiceServer).RemoteMaps(ctx, req.(*RemoteMapsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _FABRIDIntraService_MPLSMap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(MPLSMapRequest) if err := dec(in); err != nil { @@ -1264,6 +1613,10 @@ var _FABRIDIntraService_serviceDesc = grpc.ServiceDesc{ MethodName: "RemotePolicyDescription", Handler: _FABRIDIntraService_RemotePolicyDescription_Handler, }, + { + MethodName: "RemoteMaps", + Handler: _FABRIDIntraService_RemoteMaps_Handler, + }, { MethodName: "MPLSMap", Handler: _FABRIDIntraService_MPLSMap_Handler, diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index cf32075acb..63de459029 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -86,10 +86,11 @@ type PathsRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SourceIsdAs uint64 `protobuf:"varint,1,opt,name=source_isd_as,json=sourceIsdAs,proto3" json:"source_isd_as,omitempty"` - DestinationIsdAs uint64 `protobuf:"varint,2,opt,name=destination_isd_as,json=destinationIsdAs,proto3" json:"destination_isd_as,omitempty"` - Refresh bool `protobuf:"varint,3,opt,name=refresh,proto3" json:"refresh,omitempty"` - Hidden bool `protobuf:"varint,4,opt,name=hidden,proto3" json:"hidden,omitempty"` + SourceIsdAs uint64 `protobuf:"varint,1,opt,name=source_isd_as,json=sourceIsdAs,proto3" json:"source_isd_as,omitempty"` + DestinationIsdAs uint64 `protobuf:"varint,2,opt,name=destination_isd_as,json=destinationIsdAs,proto3" json:"destination_isd_as,omitempty"` + Refresh bool `protobuf:"varint,3,opt,name=refresh,proto3" json:"refresh,omitempty"` + Hidden bool `protobuf:"varint,4,opt,name=hidden,proto3" json:"hidden,omitempty"` + FetchFabridDetachedMaps bool `protobuf:"varint,5,opt,name=fetch_fabrid_detached_maps,json=fetchFabridDetachedMaps,proto3" json:"fetch_fabrid_detached_maps,omitempty"` } func (x *PathsRequest) Reset() { @@ -152,6 +153,13 @@ func (x *PathsRequest) GetHidden() bool { return false } +func (x *PathsRequest) GetFetchFabridDetachedMaps() bool { + if x != nil { + return x.FetchFabridDetachedMaps + } + return false +} + type PathsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -217,8 +225,7 @@ type Path struct { Notes []string `protobuf:"bytes,11,rep,name=notes,proto3" json:"notes,omitempty"` EpicAuths *EpicAuths `protobuf:"bytes,12,opt,name=epic_auths,json=epicAuths,proto3" json:"epic_auths,omitempty"` CarbonIntensity []int64 `protobuf:"varint,13,rep,packed,name=carbon_intensity,json=carbonIntensity,proto3" json:"carbon_intensity,omitempty"` - FabridEnabled []bool `protobuf:"varint,14,rep,packed,name=fabrid_enabled,json=fabridEnabled,proto3" json:"fabrid_enabled,omitempty"` - FabridPolicies []*FabridPolicies `protobuf:"bytes,15,rep,name=fabrid_policies,json=fabridPolicies,proto3" json:"fabrid_policies,omitempty"` + FabridInfo []*FabridInfo `protobuf:"bytes,14,rep,name=fabrid_info,json=fabridInfo,proto3" json:"fabrid_info,omitempty"` } func (x *Path) Reset() { @@ -344,30 +351,26 @@ func (x *Path) GetCarbonIntensity() []int64 { return nil } -func (x *Path) GetFabridEnabled() []bool { - if x != nil { - return x.FabridEnabled - } - return nil -} - -func (x *Path) GetFabridPolicies() []*FabridPolicies { +func (x *Path) GetFabridInfo() []*FabridInfo { if x != nil { - return x.FabridPolicies + return x.FabridInfo } return nil } -type FabridPolicies struct { +type FabridInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Policies []*FabridPolicy `protobuf:"bytes,1,rep,name=policies,proto3" json:"policies,omitempty"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Digest []byte `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"` + Policies []*FabridPolicy `protobuf:"bytes,3,rep,name=policies,proto3" json:"policies,omitempty"` + Detached bool `protobuf:"varint,4,opt,name=detached,proto3" json:"detached,omitempty"` } -func (x *FabridPolicies) Reset() { - *x = FabridPolicies{} +func (x *FabridInfo) Reset() { + *x = FabridInfo{} if protoimpl.UnsafeEnabled { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -375,13 +378,13 @@ func (x *FabridPolicies) Reset() { } } -func (x *FabridPolicies) String() string { +func (x *FabridInfo) String() string { return protoimpl.X.MessageStringOf(x) } -func (*FabridPolicies) ProtoMessage() {} +func (*FabridInfo) ProtoMessage() {} -func (x *FabridPolicies) ProtoReflect() protoreflect.Message { +func (x *FabridInfo) ProtoReflect() protoreflect.Message { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -393,18 +396,39 @@ func (x *FabridPolicies) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use FabridPolicies.ProtoReflect.Descriptor instead. -func (*FabridPolicies) Descriptor() ([]byte, []int) { +// Deprecated: Use FabridInfo.ProtoReflect.Descriptor instead. +func (*FabridInfo) Descriptor() ([]byte, []int) { return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} } -func (x *FabridPolicies) GetPolicies() []*FabridPolicy { +func (x *FabridInfo) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *FabridInfo) GetDigest() []byte { + if x != nil { + return x.Digest + } + return nil +} + +func (x *FabridInfo) GetPolicies() []*FabridPolicy { if x != nil { return x.Policies } return nil } +func (x *FabridInfo) GetDetached() bool { + if x != nil { + return x.Detached + } + return false +} + type FabridPolicy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1889,7 +1913,7 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, @@ -1898,188 +1922,84 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x22, 0x3c, 0x0a, 0x0d, 0x50, - 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, - 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, - 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x05, 0x0a, 0x04, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x03, 0x72, 0x61, 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x3e, - 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x10, - 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, - 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x07, - 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, - 0x31, 0x0a, 0x03, 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x03, 0x67, - 0x65, 0x6f, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x09, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x0d, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, 0x69, 0x63, 0x5f, 0x61, 0x75, - 0x74, 0x68, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x69, 0x63, - 0x41, 0x75, 0x74, 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, - 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, - 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x66, - 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, - 0x03, 0x28, 0x08, 0x52, 0x0d, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x48, 0x0a, 0x0f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x0e, 0x66, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x0e, - 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x39, - 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, - 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x0c, 0x46, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x68, 0x0a, 0x11, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, - 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, - 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, 0x11, 0x46, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, - 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x41, 0x73, 0x12, - 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x41, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x08, - 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, - 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x9b, 0x01, 0x0a, 0x11, 0x46, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xb9, 0x01, 0x0a, 0x12, 0x46, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, - 0x0a, 0x0c, 0x61, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x61, 0x73, 0x48, 0x6f, 0x73, 0x74, - 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, - 0x00, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x88, 0x01, - 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x6b, 0x65, 0x79, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, - 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, 0x66, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, 0x66, 0x12, 0x1b, 0x0a, - 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, 0x0a, 0x0d, 0x50, 0x61, - 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, - 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, - 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, - 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, 0x41, 0x53, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x22, 0x49, 0x0a, 0x0a, - 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, - 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, - 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, - 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0d, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x07, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, 0x72, - 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x43, 0x0a, - 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, - 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, - 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, - 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x65, 0x6e, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, - 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, - 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, - 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, - 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x66, + 0x65, 0x74, 0x63, 0x68, 0x5f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x64, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x17, 0x66, 0x65, 0x74, 0x63, 0x68, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, 0x22, 0x3c, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x61, 0x74, + 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, + 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, + 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, + 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x3a, 0x0a, + 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x07, 0x6c, 0x61, 0x74, + 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1c, + 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x03, + 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, + 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x03, 0x67, 0x65, 0x6f, 0x12, + 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6c, + 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, + 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x73, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, + 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, + 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x0b, 0x66, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x66, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, + 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x22, 0x9b, + 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x68, 0x0a, 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, + 0x11, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x0a, + 0x06, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, + 0x73, 0x74, 0x41, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x41, 0x73, 0x65, + 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x88, 0x01, + 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x9b, + 0x01, 0x0a, 0x11, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, @@ -2088,121 +2008,231 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, - 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, - 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, - 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, - 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, - 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, - 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xec, - 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, - 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, - 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, - 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, - 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, - 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9f, 0x01, - 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, - 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x2a, - 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, - 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, - 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, - 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0xf8, 0x06, - 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, 0x41, 0x53, 0x12, - 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xb9, 0x01, 0x0a, + 0x12, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x61, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, + 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x61, + 0x73, 0x48, 0x6f, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, + 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, + 0x76, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, + 0x76, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, + 0x36, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, + 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, + 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, + 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, + 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, + 0x09, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, + 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, + 0x73, 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, + 0x75, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, - 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x2e, + 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, + 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, + 0x79, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, + 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, + 0x59, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, + 0x1b, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, + 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, + 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, + 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, + 0x72, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, + 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, + 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, + 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, + 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, + 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, + 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, + 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, + 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, + 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, + 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, + 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, + 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, + 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, + 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, + 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, + 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, + 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, + 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, + 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, + 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, + 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, + 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, + 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, + 0x10, 0x03, 0x32, 0xf8, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, + 0x0a, 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x57, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, - 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x09, 0x50, 0x6f, - 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, - 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, - 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, + 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x49, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, + 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, - 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, - 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x25, + 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, + 0x6f, 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x57, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x22, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, + 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, + 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, + 0x79, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, + 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, + 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, + 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2224,7 +2254,7 @@ var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest (*PathsResponse)(nil), // 2: proto.daemon.v1.PathsResponse (*Path)(nil), // 3: proto.daemon.v1.Path - (*FabridPolicies)(nil), // 4: proto.daemon.v1.FabridPolicies + (*FabridInfo)(nil), // 4: proto.daemon.v1.FabridInfo (*FabridPolicy)(nil), // 5: proto.daemon.v1.FabridPolicy (*FabridKeysRequest)(nil), // 6: proto.daemon.v1.FabridKeysRequest (*FabridKeyResponse)(nil), // 7: proto.daemon.v1.FabridKeyResponse @@ -2268,8 +2298,8 @@ var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 11, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates 0, // 6: proto.daemon.v1.Path.link_type:type_name -> proto.daemon.v1.LinkType 9, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths - 4, // 8: proto.daemon.v1.Path.fabrid_policies:type_name -> proto.daemon.v1.FabridPolicies - 5, // 9: proto.daemon.v1.FabridPolicies.policies:type_name -> proto.daemon.v1.FabridPolicy + 4, // 8: proto.daemon.v1.Path.fabrid_info:type_name -> proto.daemon.v1.FabridInfo + 5, // 9: proto.daemon.v1.FabridInfo.policies:type_name -> proto.daemon.v1.FabridPolicy 35, // 10: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier 33, // 11: proto.daemon.v1.FabridKeyResponse.epoch_begin:type_name -> google.protobuf.Timestamp 33, // 12: proto.daemon.v1.FabridKeyResponse.epoch_end:type_name -> google.protobuf.Timestamp @@ -2363,7 +2393,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridPolicies); i { + switch v := v.(*FabridInfo); i { case 0: return &v.state case 1: diff --git a/pkg/snet/path.go b/pkg/snet/path.go index 4274080907..c15e32b7d0 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -96,6 +96,20 @@ func (ea *EpicAuths) SupportsEpic() bool { return (len(ea.AuthPHVF) == 16 && len(ea.AuthLHVF) == 16) } +type FabridInfo struct { + // Enabled contains a boolean indicating whether the hop supports FABRID. + Enabled bool + // Policies Contains the policy identifiers that can be used on this hop + Policies []*fabrid.Policy + // Digest contains the FABRID digest for the AS. This is used when the + // FABRID extension is detached. + Digest []byte + // Detached indicates whether the FABRID maps have been detached from the PCB for this hop. + // This can happen as the PCB is propagated, or when the AS does not add the detachable FABRID + // extension. + Detached bool +} + // PathMetadata contains supplementary information about a path. // // The information about MTU, Latency, Bandwidth etc. are based solely on data @@ -153,21 +167,24 @@ type PathMetadata struct { // EpicAuths contains the EPIC authenticators. EpicAuths EpicAuths - // FabridEnabled contains a boolean for each AS, indicating whether it supports FABRID. - FabridEnabled []bool - - // FabridPolicies Contains the policy identifiers of interfaces on the path - FabridPolicies [][]*fabrid.Policy + // FabridInfo contains information about the FABRID policies and support for each hop. + FabridInfo []FabridInfo } func (pm *PathMetadata) Copy() *PathMetadata { if pm == nil { return nil } - fabridPoliciesCopy := make([][]*fabrid.Policy, len(pm.FabridPolicies)) - for i := range pm.FabridPolicies { - fabridPoliciesCopy[i] = make([]*fabrid.Policy, len(pm.FabridPolicies[i])) - copy(fabridPoliciesCopy[i], pm.FabridPolicies[i]) + fabridInfoCopy := make([]FabridInfo, len(pm.FabridInfo)) + for i := range pm.FabridInfo { + fabridInfoCopy[i] = FabridInfo{ + Enabled: pm.FabridInfo[i].Enabled, + Policies: make([]*fabrid.Policy, len(pm.FabridInfo[i].Policies)), + Digest: make([]byte, len(pm.FabridInfo[i].Digest)), + Detached: pm.FabridInfo[i].Detached, + } + copy(fabridInfoCopy[i].Policies, pm.FabridInfo[i].Policies) + copy(fabridInfoCopy[i].Digest, pm.FabridInfo[i].Digest) } return &PathMetadata{ Interfaces: append(pm.Interfaces[:0:0], pm.Interfaces...), @@ -180,9 +197,7 @@ func (pm *PathMetadata) Copy() *PathMetadata { LinkType: append(pm.LinkType[:0:0], pm.LinkType...), InternalHops: append(pm.InternalHops[:0:0], pm.InternalHops...), Notes: append(pm.Notes[:0:0], pm.Notes...), - FabridEnabled: append(pm.FabridEnabled[:0:0], pm.FabridEnabled...), - FabridPolicies: fabridPoliciesCopy, - + FabridInfo: fabridInfoCopy, EpicAuths: EpicAuths{ AuthPHVF: append([]byte(nil), pm.EpicAuths.AuthPHVF...), AuthLHVF: append([]byte(nil), pm.EpicAuths.AuthLHVF...), diff --git a/private/path/combinator/BUILD.bazel b/private/path/combinator/BUILD.bazel index fdd55e4adf..de9b76cb07 100644 --- a/private/path/combinator/BUILD.bazel +++ b/private/path/combinator/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "combinator.go", + "fabrid_accumulator.go", "graph.go", "staticinfo_accumulator.go", ], @@ -11,10 +12,12 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/ctrl/path_mgmt/proto:go_default_library", "//pkg/private/util:go_default_library", "//pkg/segment:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/segment/extensions/staticinfo:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/scion:go_default_library", diff --git a/private/path/combinator/fabrid_accumulator.go b/private/path/combinator/fabrid_accumulator.go new file mode 100644 index 0000000000..35f735bda9 --- /dev/null +++ b/private/path/combinator/fabrid_accumulator.go @@ -0,0 +1,80 @@ +// Copyright 2018 ETH Zurich, Anapaya Systems +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package combinator + +import ( + "time" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" + "github.com/scionproto/scion/pkg/snet" +) + +// We go through the list of ASEntries and store for each IA a pointer to the FABRID +// Map found in the ASEntries' extensions. If there is already a map stored, check the info time, +// and replace with the newer FABRID maps. This results in a map[IA]FabridMapEntry, which can be +// used to find the policies that are available for each of the interface pairs on the path. +type FabridMapEntry struct { + Map *fabrid_ext.Detached + Ts time.Time + // The Digest of the Fabrid Maps, this can be empty. + Digest []byte +} + +func GetFabridInfoForIntfs(ia addr.IA, ig, eg uint16, maps map[addr.IA]FabridMapEntry, + allowIpPolicies bool) *snet.FabridInfo { + policies := make([]*fabrid.Policy, 0) + fabridMap, exist := maps[ia] + if !exist { + return &snet.FabridInfo{ + Enabled: false, + Policies: policies, + Digest: []byte{}, + Detached: false, + } + } else if fabridMap.Map == nil { + return &snet.FabridInfo{ + Enabled: true, + Policies: policies, + Digest: fabridMap.Digest, + Detached: len(fabridMap.Digest) > 0, + } + } + for k, v := range fabridMap.Map.SupportedIndicesMap { + if !k.Matches(ig, eg, allowIpPolicies) { + continue + } + for _, policy := range v { + val, ok := fabridMap.Map.IndexIdentiferMap[policy] + if !ok { + continue + } + policies = append(policies, &fabrid.Policy{ + IsLocal: val.IsLocal, + Identifier: val.Identifier, + Index: fabrid.PolicyID(policy), + }) + + } + } + + return &snet.FabridInfo{ + Enabled: true, + Policies: policies, + Digest: fabridMap.Digest, + Detached: false, + } +} diff --git a/proto/control_plane/experimental/v1/fabrid.proto b/proto/control_plane/experimental/v1/fabrid.proto index daa98978ad..f6183f9168 100644 --- a/proto/control_plane/experimental/v1/fabrid.proto +++ b/proto/control_plane/experimental/v1/fabrid.proto @@ -25,7 +25,8 @@ service FABRIDInterService{ rpc SupportedIndicesMap(SupportedIndicesMapRequest) returns (SupportedIndicesMapResponse) {} // Gets the D-Map for a local AS, mapping policy indices to policy identifiers rpc IndexIdentifierMap(IndexIdentifierMapRequest) returns (IndexIdentifierMapResponse) {} -// todo(jvanbommel): Q signatures on the maps ? (hash in pcb?) + // Gets the detached maps (both the supported indices map and index identifier map) + rpc DetachedMaps(DetachedMapsRequest) returns (DetachedMapsResponse) {} // Gets a string description for a local policy rpc LocalPolicyDescription(LocalPolicyDescriptionRequest) returns (LocalPolicyDescriptionResponse) {} @@ -37,7 +38,9 @@ service FABRIDIntraService { // control service. rpc RemotePolicyDescription(RemotePolicyDescriptionRequest) returns (RemotePolicyDescriptionResponse) {} - + // Used by a host in the AS to request the supported indices map, as well as the index + // identifier map for a remote AS. + rpc RemoteMaps(RemoteMapsRequest) returns (RemoteMapsResponse) {} // Used by border routers in the AS to request the mapping of supported policy indices to local MPLS labels rpc MPLSMap(MPLSMapRequest) returns (MPLSMapResponse) {} } @@ -117,5 +120,24 @@ message LocalPolicyDescriptionResponse { string description = 1; } +message RemoteMapsRequest { + // The digest corresponding to the maps that the end host is requesting, the end host + // receives this digest in a PCB. + bytes digest = 1; + // Remote ISD-AS + uint64 isd_as = 2; +} + +message RemoteMapsResponse { + // The maps that the remote AS has detached from the PCB + FABRIDDetachableMaps maps = 1; +} + +message DetachedMapsRequest { } + +message DetachedMapsResponse { + // The maps that the local AS has detached from the PCB + FABRIDDetachableMaps maps = 1; +} diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index df3f276147..e39cd2b0b3 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -59,6 +59,9 @@ message PathsRequest { bool refresh = 3; // Request hidden paths instead of standard paths. bool hidden = 4; + // Choose to have the daemon fetch any detached fabrid maps to fill the policies attribute in + // the metadata. + bool fetch_fabrid_detached_maps = 5; } message PathsResponse { @@ -117,17 +120,24 @@ message Path { // Entry i describes the carbon intensity between interface i and i+1. // Consequently, there are N-1 entries for N interfaces. repeated int64 carbon_intensity = 13; - // FabridEnabled describes which hops support Fabrid. - repeated bool fabrid_enabled = 14; - // FabridPolicies contains the fabrid policy identifiers that are supported for an interface - // Entry i describes the policies between interfaces i and i+1. - repeated FabridPolicies fabrid_policies = 15; + // FabridInfo contains the FABRID-specific information for each hop on the path, specifically + // whether the AS in the hop supports FABRID, the possible policies, and whether the AS's FABRID + // maps were detached during beaconing (requiring manual fetching by the end host to fill the + // missing policies list). + repeated FabridInfo fabrid_info = 14; } -message FabridPolicies { - // A list of policies for a specific interface - repeated FabridPolicy policies = 1; +message FabridInfo { + // Enabled describes whether the hop supports Fabrid. + bool enabled = 1; + // Digest contains the digest for the FABRID map of this hop. + bytes digest = 2; + // Policies contains the fabrid policy identifiers that are supported for this hop. + repeated FabridPolicy policies = 3; + // Detached indicates whether the FABRID map has been detached for this hop. + bool detached = 4; } + message FabridPolicy { // The identifier for the policy, either local or global: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier policy_identifier = 1; From 62c8dc4667d91b43acde85f1eb12db6a04be2a98 Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:53:53 +0200 Subject: [PATCH 05/26] modified fetcher used by daemon for drkey --- daemon/cmd/daemon/main.go | 16 +++++++------- daemon/drkey/grpc/fetcher.go | 35 ------------------------------ pkg/grpc/dialer.go | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/daemon/cmd/daemon/main.go b/daemon/cmd/daemon/main.go index bb93df21f3..06c911182d 100644 --- a/daemon/cmd/daemon/main.go +++ b/daemon/cmd/daemon/main.go @@ -202,10 +202,6 @@ func realMain(ctx context.Context) error { }, } defer level2DB.Close() - csAddr, err := net.ResolveTCPAddr("tcp", topo.ControlServiceAddresses()[0].String()) - if err != nil { - return serrors.WrapStr("resolve control service address", err) - } localAddrIPString, _, err := net.SplitHostPort(globalCfg.SD.Address) if err != nil { return serrors.WrapStr("resolve local address", err) @@ -215,11 +211,15 @@ func realMain(ctx context.Context) error { IP: localAddrIP, Port: 0, } - drkeyFetcher := sd_grpc.SetupFetcher(csAddr, localAddr) drkeyClientEngine = &sd_drkey.ClientEngine{ - IA: topo.IA(), - DB: level2DB, - Fetcher: drkeyFetcher, + IA: topo.IA(), + DB: level2DB, + Fetcher: &sd_grpc.Fetcher{ + Dialer: &libgrpc.FixedLocalIPTCPDialer{ + LocalAddr: localAddr, + SvcResolver: dialer.SvcResolver, + }, + }, } cleaners := drkeyClientEngine.CreateStorageCleaners() for _, cleaner := range cleaners { diff --git a/daemon/drkey/grpc/fetcher.go b/daemon/drkey/grpc/fetcher.go index b66250a8b2..a6e51ffe75 100644 --- a/daemon/drkey/grpc/fetcher.go +++ b/daemon/drkey/grpc/fetcher.go @@ -16,9 +16,6 @@ package grpc import ( "context" - "net" - - "google.golang.org/grpc" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" @@ -33,38 +30,6 @@ type Fetcher struct { Dialer sc_grpc.Dialer } -func SetupFetcher(csAddr *net.TCPAddr, localAddr *net.TCPAddr) *Fetcher { - return &Fetcher{ - Dialer: &CustomDialer{ - CsAddr: csAddr, - LocalAddr: localAddr, - }, - } -} - -type CustomDialer struct { - CsAddr *net.TCPAddr - LocalAddr *net.TCPAddr -} - -// This custom dialer is used for communication with the local control service. Therefore -// the destination address is already configured during the setup and any passed -// address will be ignored. -func (d *CustomDialer) Dial(ctx context.Context, _ net.Addr) (*grpc.ClientConn, error) { - // this custom dialer modifies its local address. Otherwise in the local setup - // grpc might use 127.0.0.1 as local address and therefore the control service - // would reject the drkey request - dialer := func(ctx context.Context, addr string) (net.Conn, error) { - return net.DialTCP("tcp", d.LocalAddr, d.CsAddr) - } - return grpc.DialContext(ctx, d.CsAddr.String(), - grpc.WithInsecure(), - grpc.WithContextDialer(dialer), - sc_grpc.UnaryClientInterceptor(), - sc_grpc.StreamClientInterceptor(), - ) -} - func (f *Fetcher) ASHostKey( ctx context.Context, meta drkey.ASHostMeta, diff --git a/pkg/grpc/dialer.go b/pkg/grpc/dialer.go index abaf419852..f67eae2d20 100644 --- a/pkg/grpc/dialer.go +++ b/pkg/grpc/dialer.go @@ -50,6 +50,47 @@ func (SimpleDialer) Dial(ctx context.Context, address net.Addr) (*grpc.ClientCon ) } +// The FixedLocalIPTCPDialer behaves the same as the TCP Dialer but allows for setting a local +// IP address. Without this it would not be possible to call IP sensitive endpoints like +// control service drkey. +type FixedLocalIPTCPDialer struct { + LocalAddr *net.TCPAddr + SvcResolver func(addr.SVC) []resolver.Address +} + +func (d *FixedLocalIPTCPDialer) Dial(ctx context.Context, dst net.Addr) (*grpc.ClientConn, error) { + dialer := func(ctx context.Context, addr string) (net.Conn, error) { + csAddr, err := net.ResolveTCPAddr("tcp", addr) + if err != nil { + return nil, err + } + return net.DialTCP("tcp", d.LocalAddr, csAddr) + } + if v, ok := dst.(*snet.SVCAddr); ok { + targets := d.SvcResolver(v.SVC) + r := manual.NewBuilderWithScheme("svc") + r.InitialState(resolver.State{Addresses: targets}) + if len(targets) == 0 { + return nil, serrors.New("could not resolve") + } + return grpc.DialContext(ctx, r.Scheme()+":///"+v.SVC.BaseString(), + grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`), + grpc.WithInsecure(), + grpc.WithContextDialer(dialer), + grpc.WithResolvers(r), + UnaryClientInterceptor(), + StreamClientInterceptor(), + ) + } else { + return grpc.DialContext(ctx, dst.String(), + grpc.WithInsecure(), + grpc.WithContextDialer(dialer), + UnaryClientInterceptor(), + StreamClientInterceptor(), + ) + } +} + // XXX(roosd): // // Dialing a grpc.ClientConn is hidden behind the dialer interface due to From a3ea69f53c56ee9d71f8624e3b340a7bfb287fc8 Mon Sep 17 00:00:00 2001 From: jelte Date: Tue, 6 Aug 2024 16:17:54 +0200 Subject: [PATCH 06/26] Fixing minor issues from last review round. --- control/fabrid/grpc/fabrid_service.go | 3 ++- control/fabrid/mpls_map.go | 5 ++--- daemon/drkey/client_engine.go | 2 +- pkg/segment/extensions/digest/digest_test.go | 6 +++++- pkg/segment/extensions/fabrid/fabrid.go | 4 ++-- pkg/segment/unsigned_test.go | 6 +++++- private/path/combinator/fabrid_accumulator.go | 2 +- 7 files changed, 18 insertions(+), 10 deletions(-) diff --git a/control/fabrid/grpc/fabrid_service.go b/control/fabrid/grpc/fabrid_service.go index 802c08a24a..cdb0f3bd03 100644 --- a/control/fabrid/grpc/fabrid_service.go +++ b/control/fabrid/grpc/fabrid_service.go @@ -65,7 +65,8 @@ func (s Server) MPLSMap(ctx context.Context, request *experimental.MPLSMapReques func (s Server) RemotePolicyDescription(ctx context.Context, request *experimental.RemotePolicyDescriptionRequest) ( *experimental.RemotePolicyDescriptionResponse, error) { - //TODO(jvanbommel): signature / hash? + //TODO(jvanbommel): In a future PR we will add a third description map, which maps identifiers + // to descriptions, protecting this data by adding it into the digest in the signed AS entry. identifier := fabrid.RemotePolicyIdentifier{ ISDAS: request.IsdAs, Identifier: request.PolicyIdentifier, diff --git a/control/fabrid/mpls_map.go b/control/fabrid/mpls_map.go index 607c2abe89..0635b32623 100644 --- a/control/fabrid/mpls_map.go +++ b/control/fabrid/mpls_map.go @@ -83,9 +83,8 @@ func sortedKeys[K uint32 | uint64, V any](m map[K]V) []K { return keys } -// This method is to be called after all inserts and removes from the internal map -// TODO(jvanbommel): this feels too expensive for what a relatively simple synchronization need. -// Revise? +// This method is to be called after all inserts and removes from the internal map and calculates +// the hash for the MPLS map according to the entries. The order of insertion is not relevant here. func (m *MplsMaps) UpdateHash() { h := fnv.New64() for _, polIdx := range sortedKeys(m.IPPoliciesMap) { diff --git a/daemon/drkey/client_engine.go b/daemon/drkey/client_engine.go index 987dda9957..9546482178 100644 --- a/daemon/drkey/client_engine.go +++ b/daemon/drkey/client_engine.go @@ -43,7 +43,7 @@ type ClientEngine struct { func (e *ClientEngine) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, ) (drkey.FabridKeysResponse, error) { now := time.Now() - var hostHostKey drkey.FabridKey = drkey.FabridKey{} + hostHostKey := drkey.FabridKey{} if meta.DstHost != nil && len(meta.PathASes) > 0 { key, err := e.GetHostHostKey(ctx, drkey.HostHostMeta{ ProtoId: drkey.FABRID, diff --git a/pkg/segment/extensions/digest/digest_test.go b/pkg/segment/extensions/digest/digest_test.go index 2510a97c5a..19f2fe077c 100644 --- a/pkg/segment/extensions/digest/digest_test.go +++ b/pkg/segment/extensions/digest/digest_test.go @@ -47,7 +47,11 @@ func TestDecodeEncode(t *testing.T) { Type: fabrid.Interface, InterfaceId: 44, }}: []uint8{1}}, - IndexIdentiferMap: fabrid.IndexIdentifierMap{}, + IndexIdentiferMap: fabrid.IndexIdentifierMap{ + 1: &fabrid.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }}, } var d digest.Digest diff --git a/pkg/segment/extensions/fabrid/fabrid.go b/pkg/segment/extensions/fabrid/fabrid.go index 464420e8b3..570c68a2be 100644 --- a/pkg/segment/extensions/fabrid/fabrid.go +++ b/pkg/segment/extensions/fabrid/fabrid.go @@ -75,8 +75,8 @@ type ConnectionPoint struct { InterfaceId uint16 } -// To ensure that the connection point strings are identical, i.e. without padding, -// parse using the net library +// IPConnectionPointFromString parses a string IP address and Prefix, then masks the IP with the +// prefix and returns a ConnectionPoint with the parsed IP, type and prefix. func IPConnectionPointFromString(IP string, Prefix uint32, Type ConnectionPointType) ConnectionPoint { var m net.IPMask diff --git a/pkg/segment/unsigned_test.go b/pkg/segment/unsigned_test.go index c53c9ed670..931e6347f2 100644 --- a/pkg/segment/unsigned_test.go +++ b/pkg/segment/unsigned_test.go @@ -46,7 +46,11 @@ func TestDecodeEncode(t *testing.T) { Type: fabrid.Interface, InterfaceId: 44, }}: []uint8{1}}, - IndexIdentiferMap: fabrid.IndexIdentifierMap{}, + IndexIdentiferMap: fabrid.IndexIdentifierMap{ + 1: &fabrid.PolicyIdentifier{ + IsLocal: false, + Identifier: 22, + }}, } ue := UnsignedExtensions{ diff --git a/private/path/combinator/fabrid_accumulator.go b/private/path/combinator/fabrid_accumulator.go index 35f735bda9..b9ac57884c 100644 --- a/private/path/combinator/fabrid_accumulator.go +++ b/private/path/combinator/fabrid_accumulator.go @@ -1,4 +1,4 @@ -// Copyright 2018 ETH Zurich, Anapaya Systems +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 4e57df1da2a8085bd86d4e469f91a742f7e81d95 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Tue, 6 Aug 2024 18:11:00 +0200 Subject: [PATCH 07/26] Refactored FABRID policy validation Also fixed linting error --- control/config/fabrid.go | 112 +++++++++++++++----------- control/config/fabrid_test.go | 42 +++++++++- control/fabrid/fabrid_manager_test.go | 2 +- daemon/drkey/grpc/BUILD.bazel | 1 - 4 files changed, 105 insertions(+), 52 deletions(-) diff --git a/control/config/fabrid.go b/control/config/fabrid.go index 5baa0e408d..cb35c0f04e 100644 --- a/control/config/fabrid.go +++ b/control/config/fabrid.go @@ -17,6 +17,7 @@ package config import ( "io" "net" + "slices" "strings" "github.com/scionproto/scion/pkg/private/serrors" @@ -34,17 +35,30 @@ type FABRIDPolicy struct { // Validate validates that all values are parsable. func (cfg *FABRIDPolicy) Validate(asInterfaceIDs []uint16) error { - for _, connectionPoint := range cfg.SupportedBy { - connectionPoint.asInterfaceIDs = asInterfaceIDs - if err := config.ValidateAll(&connectionPoint); err != nil { - return serrors.WrapStr("Validating supported interfaces failed", err) + for _, connectionPoints := range cfg.SupportedBy { + if err := connectionPoints.Validate(asInterfaceIDs); err != nil { + return serrors.WrapStr("Failed to validate connection points", err) } - connectionPoint.asInterfaceIDs = nil } - if cfg.IsLocalPolicy && (cfg.LocalIdentifier == 0 || cfg.LocalDescription == "") { - return serrors.New("Local policy configuration must not be empty.") - } else if !cfg.IsLocalPolicy && cfg.GlobalIdentifier == 0 { - return serrors.New("Global policy identifier must be valid.") + if cfg.IsLocalPolicy { + if cfg.LocalIdentifier == 0 { + return serrors.New("Local policy identifier missing.") + } else if cfg.LocalDescription == "" { + return serrors.New("Local policy description missing.") + } else if cfg.GlobalIdentifier != 0 { + return serrors.New("Unexpected global identifier", + "global_identifier", cfg.GlobalIdentifier) + } + } else { + if cfg.GlobalIdentifier == 0 { + return serrors.New("Global policy identifier missing.") + } else if cfg.LocalDescription != "" { + return serrors.New("Unexpected local description", + "local_description", cfg.LocalDescription) + } else if cfg.LocalIdentifier != 0 { + return serrors.New("Unexpected local identifier", + "local_identifier", cfg.LocalIdentifier) + } } return nil @@ -59,49 +73,29 @@ type FABRIDConnectionPoints struct { Ingress FABRIDConnectionPoint `yaml:"ingress,omitempty"` Egress FABRIDConnectionPoint `yaml:"egress,omitempty"` MPLSLabel uint32 `yaml:"mpls_label,omitempty"` - // asInterfaceIDs is manually set to verify that both the provided - // ingress and egress actually belong to valid AS interfaces if their - // type is interface - asInterfaceIDs []uint16 } // Validate validates that all values are parsable. -func (cfg *FABRIDConnectionPoints) Validate() error { - doInterfacesExist := func(connectionPoints ...*FABRIDConnectionPoint) bool { - for _, cp := range connectionPoints { - if cp.Type == fabrid.Interface { - found := cp.Interface == 0 - for i := 0; i < len(cfg.asInterfaceIDs); i++ { - if cp.Interface == cfg.asInterfaceIDs[i] { - found = true - break - } - } - if !found { - return false - } - } - } - return true - } +func (cfg *FABRIDConnectionPoints) Validate(asInterfaceIDs []uint16) error { if cfg.Ingress.Type != fabrid.Interface && cfg.Ingress.Type != fabrid.Wildcard { return serrors.New("FABRID policies are only supported from an interface to an IP" + " range or other interface.") - } else if cfg.Ingress.Type == fabrid.Interface && cfg.Ingress.Interface == 0 { - return serrors.New("Invalid interface for connection point") } else if cfg.Ingress.Type == fabrid.Interface && cfg.Egress.Type == fabrid.Interface && cfg. Ingress.Interface == cfg.Egress.Interface { - return serrors.New("Interfaces should be distinct") + return serrors.New("Interfaces should be distinct.") + } + if err := cfg.Ingress.Validate(asInterfaceIDs); err != nil { + return serrors.WrapStr("Failed to validate ingress connection point", err) } - if !doInterfacesExist(&cfg.Ingress, &cfg.Egress) { - return serrors.New("Interfaces do not exist") + if err := cfg.Egress.Validate(asInterfaceIDs); err != nil { + return serrors.WrapStr("Failed to validate egress connection point", err) } - return config.ValidateAll(&cfg.Ingress, &cfg.Egress) + return nil } -// A connection point describes a specific interface, or an IP range. A FABRID policy can be valid -// for a pair of connection points. +// FABRIDConnectionPoint describes a specific interface, or an IP range. A FABRID policy can be +// supported on a pair of connection points. type FABRIDConnectionPoint struct { Type fabrid.ConnectionPointType `yaml:"type,omitempty"` IPAddress string `yaml:"ip,omitempty"` @@ -110,27 +104,49 @@ type FABRIDConnectionPoint struct { } // Validate validates that all values are parsable. -func (cfg *FABRIDConnectionPoint) Validate() error { +func (cfg *FABRIDConnectionPoint) Validate(asInterfaceIDs []uint16) error { switch strings.ToLower(string(cfg.Type)) { case string(fabrid.Wildcard): cfg.Type = fabrid.Wildcard case string(fabrid.IPv4Range): cfg.Type = fabrid.IPv4Range + if net.ParseIP(cfg.IPAddress).To4() == nil { + return serrors.New("Invalid IPv4 address for connection point", + "ip", cfg.IPAddress) + } else if cfg.Prefix > 32 { + return serrors.New("IPv4 prefix too large", + "ip", cfg.IPAddress, "prefix", cfg.Prefix) + } case string(fabrid.IPv6Range): cfg.Type = fabrid.IPv6Range + ip := net.ParseIP(cfg.IPAddress) + if ip == nil || len(ip) != net.IPv6len { + return serrors.New("Invalid IPv6 address for connection point", + "ip", cfg.IPAddress) + } else if cfg.Prefix > 128 { + return serrors.New("IPv6 prefix too large", + "ip", cfg.IPAddress, "prefix", cfg.Prefix) + } case string(fabrid.Interface): cfg.Type = fabrid.Interface + if cfg.Interface == 0 { + return serrors.New("Interface ID missing", "type", cfg.Type) + } + if !slices.Contains(asInterfaceIDs, cfg.Interface) { + return serrors.New("Interface does not exist", "interface", cfg.Interface) + } default: - return serrors.New("unknown FABRID connection point", "type", cfg.Type) + return serrors.New("Unknown FABRID connection point", "type", cfg.Type) } - if cfg.Type == fabrid.IPv6Range && (net.ParseIP(cfg.IPAddress) == nil || cfg.Prefix > 128) { - return serrors.New("Invalid IPv6 Address range for connection point", - "ip", cfg.IPAddress, "prefix", cfg.Prefix) - } else if cfg.Type == fabrid.IPv4Range && - (net.ParseIP(cfg.IPAddress) == nil || cfg.Prefix > 32) { - return serrors.New("Invalid IPv4 Address range for connection point", - "ip", cfg.IPAddress, "prefix", cfg.Prefix) + if cfg.Type != fabrid.Interface && cfg.Interface != 0 { + return serrors.New("Unexpected interface ID", "type", cfg.Type) + } else if cfg.Type != fabrid.IPv4Range && cfg.Type != fabrid.IPv6Range { + if cfg.IPAddress != "" { + return serrors.New("Unexpected IP address", "type", cfg.Type, "ip", cfg.IPAddress) + } else if cfg.Prefix != 0 { + return serrors.New("Unexpected prefix", "type", cfg.Type, "prefix", cfg.Prefix) + } } return nil } diff --git a/control/config/fabrid_test.go b/control/config/fabrid_test.go index e4e2a28d83..6ffe65ed92 100644 --- a/control/config/fabrid_test.go +++ b/control/config/fabrid_test.go @@ -44,8 +44,8 @@ func TestIPRangePolicyWithInvalidIP(t *testing.T) { IPAddress: "192.168.5", Prefix: 24, } - err := cp.Validate() - assert.ErrorContains(t, err, "Invalid IPv4 Address range for connection point") + err := cp.Validate([]uint16{}) + assert.ErrorContains(t, err, "Invalid IPv4 address for connection point") } func TestFabridPolicyValidation(t *testing.T) { @@ -123,6 +123,44 @@ local_identifier: 55 local_description: Fabrid Example Policy`, assert: assert.Error, }, + "missing local identifier": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv6 + ip: 2001::1a2b + prefix: 33 +local: true +local_description: Fabrid Example Policy`, + assert: assert.Error, + }, + "missing local description": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv6 + ip: 2001::1a2b + prefix: 33 +local: true +local_identifier: 55`, + assert: assert.Error, + }, + "missing global identifier": { + Policy: `connections: + - ingress: + type: interface + interface: 1 + egress: + type: ipv6 + ip: 2001::1a2b + prefix: 33 +local: false`, + assert: assert.Error, + }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { diff --git a/control/fabrid/fabrid_manager_test.go b/control/fabrid/fabrid_manager_test.go index 53f9d9f074..3aecb2b7c5 100644 --- a/control/fabrid/fabrid_manager_test.go +++ b/control/fabrid/fabrid_manager_test.go @@ -34,7 +34,7 @@ func TestLoadInvalidPolicies(t *testing.T) { func TestLoadPolicyWithNonExistingInterfaces(t *testing.T) { fm := NewFabridManager([]uint16{1}, 5*time.Second) err := fm.Load("testdata/correct") - require.ErrorContains(t, err, "Interfaces do not exist") + require.ErrorContains(t, err, "Interface does not exist") } func TestLoadPolicies(t *testing.T) { diff --git a/daemon/drkey/grpc/BUILD.bazel b/daemon/drkey/grpc/BUILD.bazel index b82537d328..c1fdb982c8 100644 --- a/daemon/drkey/grpc/BUILD.bazel +++ b/daemon/drkey/grpc/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "//pkg/proto/drkey:go_default_library", "//pkg/scrypto/cppki:go_default_library", "//pkg/snet:go_default_library", - "@org_golang_google_grpc//:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) From d0ccff6b9b533c637bd7874faa4b0f83324abc8b Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Fri, 26 Jul 2024 09:01:02 +0200 Subject: [PATCH 08/26] FABRID detachable extensions --- proto/daemon/v1/daemon.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index e39cd2b0b3..5438bc7fdc 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -107,7 +107,7 @@ message Path { // Consequently, there are no entries for the first and last ASes, as these // are not traversed completely by the path. repeated uint32 internal_hops = 10; - // Notes contains the notes added by ASes on the path, in the order of + // Notes contains the notes added by ASes on the path, in the lorder of // occurrence. // Entry i is the note of AS i on the path. repeated string notes = 11; From fa947fc84231ce673daba68b4a5dc2b37ff599e0 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 12:33:40 +0200 Subject: [PATCH 09/26] Enable header extensions SetExtensions method on dataplane paths is called during serialization, setting the HBH and E2E extension headers --- pkg/snet/packet.go | 46 ++++++++++++++++++++++++++++++++++++---- pkg/snet/path.go | 2 ++ pkg/snet/path/empty.go | 5 +++++ pkg/snet/path/epic.go | 4 ++++ pkg/snet/path/onehop.go | 5 +++++ pkg/snet/path/scion.go | 5 +++++ pkg/snet/reply_pather.go | 3 +++ 7 files changed, 66 insertions(+), 4 deletions(-) diff --git a/pkg/snet/packet.go b/pkg/snet/packet.go index 31f7592398..7e6a89b2f8 100644 --- a/pkg/snet/packet.go +++ b/pkg/snet/packet.go @@ -360,6 +360,10 @@ func (r RawPath) SetPath(s *slayers.SCION) error { return serrors.New("snet.RawPath does not support SetPath") } +func (r RawPath) SetExtensions(s *slayers.SCION, p *PacketInfo) error { + return serrors.New("snet.RawPath does not support SetExtensions") +} + // Packet describes a SCION packet. type Packet struct { Bytes @@ -370,8 +374,8 @@ type Packet struct { func (p *Packet) Decode() error { var ( scionLayer slayers.SCION - hbhLayer slayers.HopByHopExtnSkipper - e2eLayer slayers.EndToEndExtnSkipper + hbhLayer slayers.HopByHopExtn + e2eLayer slayers.EndToEndExtn udpLayer slayers.UDP scmpLayer slayers.SCMP ) @@ -379,7 +383,7 @@ func (p *Packet) Decode() error { slayers.LayerTypeSCION, &scionLayer, &hbhLayer, &e2eLayer, &udpLayer, &scmpLayer, ) parser.IgnoreUnsupported = true - decoded := make([]gopacket.LayerType, 0, 4) + decoded := make([]gopacket.LayerType, 0, 6) if err := parser.DecodeLayers(p.Bytes, &decoded); err != nil { return err } @@ -411,6 +415,12 @@ func (p *Packet) Decode() error { } } p.Path = rpath + if len(hbhLayer.Options) != 0 { + p.HbhExtension = &hbhLayer + } + if len(e2eLayer.Options) != 0 { + p.E2eExtension = &e2eLayer + } switch l4 { case slayers.LayerTypeSCIONUDP: @@ -581,10 +591,36 @@ func (p *Packet) Serialize() error { if err := p.Path.SetPath(&scionLayer); err != nil { return serrors.WrapStr("setting path", err) } + if err := p.Path.SetExtensions(&scionLayer, &p.PacketInfo); err != nil { + return serrors.WrapStr("error setting the header extensions", err) + } packetLayers = append(packetLayers, &scionLayer) + if p.HbhExtension != nil { + packetLayers = append(packetLayers, p.HbhExtension) + } + if p.E2eExtension != nil { + packetLayers = append(packetLayers, p.E2eExtension) + } + packetLayers = append(packetLayers, p.Payload.toLayers(&scionLayer)...) + if p.HbhExtension != nil { + tmp := scionLayer.NextHdr + scionLayer.NextHdr = slayers.HopByHopClass + p.HbhExtension.NextHdr = tmp + + if p.E2eExtension != nil { + tmp = p.HbhExtension.NextHdr + p.HbhExtension.NextHdr = slayers.End2EndClass + p.E2eExtension.NextHdr = tmp + } + } else if p.E2eExtension != nil { + tmp := scionLayer.NextHdr + scionLayer.NextHdr = slayers.End2EndClass + p.E2eExtension.NextHdr = tmp + } + buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{ ComputeChecksums: true, @@ -616,5 +652,7 @@ type PacketInfo struct { // Path contains a SCION forwarding path. This field must not be nil. Path DataplanePath // Payload is the Payload of the message. - Payload Payload + Payload Payload + HbhExtension *slayers.HopByHopExtn + E2eExtension *slayers.EndToEndExtn } diff --git a/pkg/snet/path.go b/pkg/snet/path.go index c15e32b7d0..f55d9c35b1 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -42,6 +42,8 @@ type DataplanePath interface { // SetPath sets the path in the SCION header. It assumes that all the fields // except the path and path type are set correctly. SetPath(scion *slayers.SCION) error + + SetExtensions(s *slayers.SCION, p *PacketInfo) error } // Path is an abstract representation of a path. Most applications do not need diff --git a/pkg/snet/path/empty.go b/pkg/snet/path/empty.go index f0e7c60864..c1be3f997b 100644 --- a/pkg/snet/path/empty.go +++ b/pkg/snet/path/empty.go @@ -17,6 +17,7 @@ package path import ( "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path/empty" + "github.com/scionproto/scion/pkg/snet" ) type Empty struct{} @@ -25,3 +26,7 @@ func (e Empty) SetPath(s *slayers.SCION) error { s.Path, s.PathType = empty.Path{}, empty.PathType return nil } + +func (e Empty) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { + return nil +} diff --git a/pkg/snet/path/epic.go b/pkg/snet/path/epic.go index a3e44bb585..ef064dfc97 100644 --- a/pkg/snet/path/epic.go +++ b/pkg/snet/path/epic.go @@ -94,3 +94,7 @@ func (e *EPIC) SetPath(s *slayers.SCION) error { s.Path, s.PathType = ep, ep.Type() return nil } + +func (e *EPIC) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { + return nil +} diff --git a/pkg/snet/path/onehop.go b/pkg/snet/path/onehop.go index 6c6bcf0c56..255f911fde 100644 --- a/pkg/snet/path/onehop.go +++ b/pkg/snet/path/onehop.go @@ -24,6 +24,7 @@ import ( "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/onehop" + "github.com/scionproto/scion/pkg/snet" ) type OneHop struct { @@ -42,6 +43,10 @@ func (p OneHop) SetPath(s *slayers.SCION) error { return nil } +func (p OneHop) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { + return nil +} + // NewOneHop creates a onehop path that has the first hopfield initialized. func NewOneHop( egress uint16, diff --git a/pkg/snet/path/scion.go b/pkg/snet/path/scion.go index a146e4a7ee..a9b6a3ee68 100644 --- a/pkg/snet/path/scion.go +++ b/pkg/snet/path/scion.go @@ -18,6 +18,7 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/snet" ) type SCION struct { @@ -43,3 +44,7 @@ func (p SCION) SetPath(s *slayers.SCION) error { s.Path, s.PathType = &sp, sp.Type() return nil } + +func (p SCION) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { + return nil +} diff --git a/pkg/snet/reply_pather.go b/pkg/snet/reply_pather.go index 62e8e53d78..cbd6c8c7af 100644 --- a/pkg/snet/reply_pather.go +++ b/pkg/snet/reply_pather.go @@ -58,3 +58,6 @@ func (p RawReplyPath) SetPath(s *slayers.SCION) error { s.Path, s.PathType = p.Path, p.Path.Type() return nil } +func (p RawReplyPath) SetExtensions(s *slayers.SCION, pi *PacketInfo) error { + return nil +} From 69a6bc571b505b4696a07df82cb445406b6d3edd Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 12:49:35 +0200 Subject: [PATCH 10/26] FABRID header extensions and crypto - Fabrid and Identifier HBH extensions for sending FABRID traffic - Fabrid crypto library for computing HVFs and the path validator --- pkg/experimental/fabrid/crypto/BUILD.bazel | 33 ++ .../fabrid/crypto/fabrid_crypto.go | 263 ++++++++++++++++ .../fabrid/crypto/fabrid_crypto_test.go | 282 ++++++++++++++++++ pkg/slayers/extension/BUILD.bazel | 28 ++ pkg/slayers/extension/fabrid.go | 201 +++++++++++++ pkg/slayers/extension/fabrid_test.go | 209 +++++++++++++ pkg/slayers/extension/identifier.go | 94 ++++++ pkg/slayers/extension/identifier_test.go | 142 +++++++++ pkg/slayers/extn.go | 2 + pkg/snet/path.go | 14 + 10 files changed, 1268 insertions(+) create mode 100644 pkg/experimental/fabrid/crypto/BUILD.bazel create mode 100644 pkg/experimental/fabrid/crypto/fabrid_crypto.go create mode 100644 pkg/experimental/fabrid/crypto/fabrid_crypto_test.go create mode 100644 pkg/slayers/extension/BUILD.bazel create mode 100644 pkg/slayers/extension/fabrid.go create mode 100644 pkg/slayers/extension/fabrid_test.go create mode 100644 pkg/slayers/extension/identifier.go create mode 100644 pkg/slayers/extension/identifier_test.go diff --git a/pkg/experimental/fabrid/crypto/BUILD.bazel b/pkg/experimental/fabrid/crypto/BUILD.bazel new file mode 100644 index 0000000000..626297da42 --- /dev/null +++ b/pkg/experimental/fabrid/crypto/BUILD.bazel @@ -0,0 +1,33 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["fabrid_crypto.go"], + importpath = "github.com/scionproto/scion/pkg/experimental/fabrid/crypto", + visibility = ["//visibility:public"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", + "//pkg/snet:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["fabrid_crypto_test.go"], + deps = [ + ":go_default_library", + "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/private/common:go_default_library", + "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", + "//pkg/snet:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + ], +) diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto.go b/pkg/experimental/fabrid/crypto/fabrid_crypto.go new file mode 100644 index 0000000000..614de736b9 --- /dev/null +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto.go @@ -0,0 +1,263 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package crypto + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "encoding/binary" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" + ext "github.com/scionproto/scion/pkg/slayers/extension" + "github.com/scionproto/scion/pkg/snet" +) + +const FabridMacInputSize int = 46 + +// MAC input: +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Identifier (8B) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Cons Ingress (2B) | Cons Egress (2B) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |ePolicyID(1B)|sHostLen(1B)| SrcHostAddr (4-16 B) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +func computeFabridHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + s *slayers.SCION, tmpBuffer []byte, resultBuffer []byte, + key []byte, ingress uint16, egress uint16) error { + if len(key) != 16 { + return serrors.New("Wrong key length", "expected", 16, "actual", len(key)) + } + if len(tmpBuffer) < FabridMacInputSize { + return serrors.New("tmpBuffer too small", "expected", + FabridMacInputSize, "actual", len(tmpBuffer)) + } + if len(resultBuffer) < 16 { + return serrors.New("resultBuffer too small", "expected", + 16, "actual", len(resultBuffer)) + } + + if err := id.Serialize(tmpBuffer[0:8]); err != nil { + return err + } + srcAddr := s.RawSrcAddr + requiredLen := 14 + len(srcAddr) + binary.BigEndian.PutUint16(tmpBuffer[8:10], ingress) + binary.BigEndian.PutUint16(tmpBuffer[10:12], egress) + tmpBuffer[12] = f.EncryptedPolicyID + tmpBuffer[13] = byte(s.SrcAddrType.Length()) + copy(tmpBuffer[14:requiredLen], srcAddr) + + if err := macBlock(key, tmpBuffer[30:46], tmpBuffer[:requiredLen], + resultBuffer[:]); err != nil { + return err + } + return nil +} + +func ComputeBaseHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { + computedHVF := make([]byte, 16) + err := computeFabridHVF(f, id, s, tmpBuffer, computedHVF, key, ingress, egress) + if err != nil { + return err + } + computedHVF[0] &= 0x3f // ignore first two (left) bits + copy(f.HopValidationField[:], computedHVF[0:3]) + return nil +} + +func ComputeVerifiedHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { + computedHVF := make([]byte, 16) + err := computeFabridHVF(f, id, s, tmpBuffer, computedHVF, key, ingress, egress) + if err != nil { + return err + } + computedHVF[3] &= 0x3f // ignore first two (left) bits + copy(f.HopValidationField[:], computedHVF[3:6]) + return nil +} + +func VerifyAndUpdate(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { + computedHVF := make([]byte, 16) + err := computeFabridHVF(f, id, s, tmpBuffer, computedHVF, key, ingress, egress) + if err != nil { + return err + } + computedHVF[0] &= 0x3f // ignore first two (left) bits + if !bytes.Equal(computedHVF[:3], f.HopValidationField[:]) { + return serrors.New("HVF is not valid") + } + computedHVF[3] &= 0x3f // ignore first two (left) bits + copy(f.HopValidationField[:], computedHVF[3:6]) + return nil +} + +func ComputePolicyID(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + key []byte) (fabrid.PolicyID, error) { + + cipher, err := aes.NewCipher(key) + if err != nil { + return 0, err + } + buf := make([]byte, aes.BlockSize) + if err = id.Serialize(buf); err != nil { + return 0, err + } + cipher.Encrypt(buf, buf) + return fabrid.PolicyID(f.EncryptedPolicyID ^ buf[0]), nil +} + +func EncryptPolicyID(f fabrid.PolicyID, id *ext.IdentifierOption, + key []byte) (uint8, error) { + + cipher, err := aes.NewCipher(key) + if err != nil { + return 0, err + } + buf := make([]byte, aes.BlockSize) + if err = id.Serialize(buf); err != nil { + return 0, err + } + cipher.Encrypt(buf, buf) + return uint8(f) ^ buf[0], nil +} + +// VerifyPathValidator recomputes the path validator from the updated HVFs and compares it +// with the path validator in the packet. Returns the secret 5th byte of the computed validator. +// `tmpBuffer` requires at least (numHops*3 rounded up to next multiple of 16) + 16 bytes +func VerifyPathValidator(f *ext.FabridOption, tmpBuffer []byte, pathKey []byte) (uint8, error) { + inputLength := 3 * len(f.HopfieldMetadata) + requiredBufferLength := 16 + (inputLength+15)&^15 + if len(tmpBuffer) < requiredBufferLength { + return 0, serrors.New("tmpBuffer length is invalid", "expected", + requiredBufferLength, + "actual", len(tmpBuffer)) + } + for i, meta := range f.HopfieldMetadata { + copy(tmpBuffer[16+i*3:16+(i+1)*3], meta.HopValidationField[:3]) + } + err := macBlock(pathKey, tmpBuffer[:16], tmpBuffer[16:16+inputLength], tmpBuffer[16:]) + if err != nil { + return 0, err + } + validationNumber := tmpBuffer[20] + if !bytes.Equal(tmpBuffer[16:20], f.PathValidator[:]) { + return validationNumber, serrors.New("Path validator is not valid", + "validator", base64.StdEncoding.EncodeToString(f.PathValidator[:]), + "computed", base64.StdEncoding.EncodeToString(tmpBuffer[16:20])) + } + return validationNumber, nil +} + +// InitValidators sets all HVFs of the FABRID option and computes the +// path validator. +func InitValidators(f *ext.FabridOption, id *ext.IdentifierOption, s *slayers.SCION, + tmpBuffer []byte, pathKey *drkey.FabridKey, asHostKeys map[addr.IA]*drkey.FabridKey, + asAsKeys map[addr.IA]drkey.FabridKey, hops []snet.HopInterface) error { + + outBuffer := make([]byte, 16) + var pathValInputLength int + var pathValBuffer []byte + if pathKey != nil { + pathValInputLength = 3 * len(f.HopfieldMetadata) + pathValBuffer = make([]byte, (pathValInputLength+15)&^15) + } + for i, meta := range f.HopfieldMetadata { + if meta.FabridEnabled { + var key drkey.Key + if meta.ASLevelKey { + asAsKey, found := asAsKeys[hops[i].IA] + if !found { + return serrors.New("InitValidators expected AS to AS key but was not in"+ + " dictionary", "AS", hops[i].IA) + } + key = asAsKey.Key + } else { + asHostKey, found := asHostKeys[hops[i].IA] + if !found { + return serrors.New("InitValidators expected AS to AS key but was not in"+ + " dictionary", "AS", hops[i].IA) + } + key = asHostKey.Key + } + + err := computeFabridHVF(meta, id, s, tmpBuffer, outBuffer, key[:], + uint16(hops[i].IgIf), uint16(hops[i].EgIf)) + if err != nil { + return err + } + outBuffer[0] &= 0x3f // ignore first two (left) bits + outBuffer[3] &= 0x3f // ignore first two (left) bits + copy(meta.HopValidationField[:3], outBuffer[:3]) + if pathKey != nil { + copy(pathValBuffer[i*3:(i+1)*3], outBuffer[3:6]) + } + } + } + if pathKey != nil { + err := macBlock(pathKey.Key[:], tmpBuffer[:16], pathValBuffer[:pathValInputLength], + pathValBuffer) + if err != nil { + return err + } + copy(f.PathValidator[:4], pathValBuffer[:4]) + } + return nil +} + +var zeroBlock [16]byte + +func macBlock(key []byte, tmp []byte, src []byte, dst []byte) error { + block, err := aes.NewCipher(key) + if err != nil { + return serrors.WrapStr("unable to initialize AES cipher", err) + } + if len(dst) < 16 { + return serrors.New("Dst length is invalid", "expected", 16, "actual", len(dst)) + } + if len(src) == 0 { + return serrors.New("Src length cannot be 0") + } + if len(tmp) < 16 { + return serrors.New("tmp length is invalid", "expected", 16, "actual", len(tmp)) + } + encryptor := cipher.NewCBCEncrypter(block, zeroBlock[:]) + paddingLength := (16 - len(src)%16) % 16 + blockCount := len(src) / block.BlockSize() + + if blockCount != 0 { + encryptor.CryptBlocks(dst, src[:16*blockCount]) + } + if paddingLength != 0 { + copy(tmp, src[16*blockCount:]) + copy(tmp[16-paddingLength:], zeroBlock[:paddingLength]) + encryptor.CryptBlocks(dst, tmp) + } + return nil +} diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go new file mode 100644 index 0000000000..a40ad85e27 --- /dev/null +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go @@ -0,0 +1,282 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package crypto_test + +import ( + crand "crypto/rand" + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" + "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" + "github.com/scionproto/scion/pkg/snet" +) + +func TestEncryptPolicyID(t *testing.T) { + unixNow := uint32(time.Now().Unix()) + + id := &extension.IdentifierOption{ + Timestamp: time.Unix(int64(unixNow), 10*int64(time.Millisecond)), + PacketID: 0xaa, + BaseTimestamp: unixNow, + } + // test with 64 different randomly chosen keys and policyIDs + for i := 0; i < 64; i++ { + policyID := fabrid.PolicyID(rand.Uint32()) + key := generateRandomBytes(16) + encPolicyID, err := crypto.EncryptPolicyID(policyID, id, key) + assert.NoError(t, err) + meta := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + HopValidationField: [3]byte{}, + } + computedPolicyID, err := crypto.ComputePolicyID(meta, id, key) + assert.NoError(t, err) + assert.Equal(t, policyID, computedPolicyID) + } +} + +func generateRandomBytes(len int) []byte { + b := make([]byte, len) + _, _ = crand.Read(b) + return b +} + +func TestFailedValidation(t *testing.T) { + type test struct { + name string + runTest func(t *testing.T) + } + tests := []test{ + { + name: "manipulated hopfield leads to failed path validator", + runTest: func(t *testing.T) { + unixNow := uint32(time.Now().Unix()) + tmpBuffer := make([]byte, (extension.MaxSupportedFabridHops*3+15)&^15+16) + id := &extension.IdentifierOption{ + Timestamp: time.Unix(int64(unixNow), 10*int64(time.Millisecond)), + PacketID: rand.Uint32(), + BaseTimestamp: unixNow, + } + s := &slayers.SCION{ + RawSrcAddr: generateRandomBytes(4), + SrcIA: addr.MustIAFrom(1, 1), + } + f := &extension.FabridOption{} + f.HopfieldMetadata = append(f.HopfieldMetadata, + &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: uint8(rand.Uint32()), + FabridEnabled: true, + ASLevelKey: rand.Intn(2) == 0, + }) + pathKey := &drkey.FabridKey{ + Key: drkey.Key{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + } + asHostKeys := make(map[addr.IA]*drkey.FabridKey) + asAsKeys := make(map[addr.IA]drkey.FabridKey) + hops := make([]snet.HopInterface, len(f.HopfieldMetadata)) + + for i := 0; i < len(f.HopfieldMetadata); i++ { + hops[i] = snet.HopInterface{ + IgIf: common.IFIDType(rand.Int()), + EgIf: common.IFIDType(rand.Int()), + Policies: nil, + } + if i == 0 { + hops[i].IA = addr.MustIAFrom(1, 1) + } else { + hops[i].IA = addr.IA(rand.Int()) + } + keyBytes := drkey.Key{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1} + if f.HopfieldMetadata[i].ASLevelKey { + asAsKeys[hops[i].IA] = drkey.FabridKey{Key: keyBytes} + } else { + asHostKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} + } + } + + err := crypto.InitValidators(f, id, s, tmpBuffer, pathKey, asHostKeys, + asAsKeys, hops) + assert.NoError(t, err) + + for i, meta := range f.HopfieldMetadata { + if meta.FabridEnabled { + if meta.ASLevelKey { + key := asAsKeys[hops[i].IA] + err = crypto.VerifyAndUpdate(meta, id, s, tmpBuffer, key.Key[:], + uint16(hops[i].IgIf), uint16(hops[i].EgIf)) + } else { + key := asHostKeys[hops[i].IA] + err = crypto.VerifyAndUpdate(meta, id, s, tmpBuffer, key.Key[:], + uint16(hops[i].IgIf), uint16(hops[i].EgIf), + ) + } + + assert.NoError(t, err) + } + } + _, err = crypto.VerifyPathValidator(f, tmpBuffer, pathKey.Key[:]) + assert.NoError(t, err) + // until now we are in the success case. But now we modify a HVF to simulate + // adversarial actions and make sure that the path validator fails + f.HopfieldMetadata[0].HopValidationField = [3]byte{0, 0, 0} + _, err = crypto.VerifyPathValidator(f, tmpBuffer, pathKey.Key[:]) + assert.ErrorContains(t, err, "Path validator is not valid") + }, + }, + { + name: "verify hopfield fails for wrong value", + runTest: func(t *testing.T) { + f := &extension.FabridOption{ + HopfieldMetadata: []*extension.FabridHopfieldMetadata{ + { + FabridEnabled: true, + HopValidationField: [3]byte{1, 2, 3}, + }, + }, + } + id := &extension.IdentifierOption{} + s := &slayers.SCION{} + tmpBuffer := make([]byte, 128) + hfKey := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + err := crypto.VerifyAndUpdate(f.HopfieldMetadata[0], id, s, tmpBuffer, hfKey, 1, 2) + assert.ErrorContains(t, err, "HVF is not valid") + }, + }, + } + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, tc.runTest) + }(tc) + } +} + +func TestSuccessfullValidators(t *testing.T) { + type test struct { + name string + rawSrcAddr []byte + srcIA addr.IA + } + unixNow := uint32(time.Now().Unix()) + + tmpBuffer := make([]byte, (extension.MaxSupportedFabridHops*3+15)&^15+16) + tests := []test{ + { + name: "random 16 byte src addr", + rawSrcAddr: generateRandomBytes(16), + srcIA: addr.IA(rand.Uint64()), + }, + { + name: "random 12 byte src addr", + rawSrcAddr: generateRandomBytes(12), + srcIA: addr.IA(rand.Uint64()), + }, + { + name: "random 8 byte src addr", + rawSrcAddr: generateRandomBytes(8), + srcIA: addr.IA(rand.Uint64()), + }, + { + name: "random 4 byte src addr", + rawSrcAddr: generateRandomBytes(4), + srcIA: addr.IA(rand.Uint64()), + }, + } + + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, func(t *testing.T) { + id := &extension.IdentifierOption{ + Timestamp: time.Unix(int64(unixNow), 10*int64(time.Millisecond)), + PacketID: rand.Uint32(), + BaseTimestamp: unixNow, + } + s := &slayers.SCION{ + RawSrcAddr: tc.rawSrcAddr, + SrcIA: tc.srcIA, + } + f := &extension.FabridOption{} + for j := uint8(1); j <= extension.MaxSupportedFabridHops; j++ { + f.HopfieldMetadata = append(f.HopfieldMetadata, + &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: uint8(rand.Uint32()), + FabridEnabled: rand.Intn(2) == 0, + ASLevelKey: rand.Intn(2) == 0, + }) + keyBytes := drkey.Key{} + copy(keyBytes[:], generateRandomBytes(16)) + pathKey := &drkey.FabridKey{Key: keyBytes} + asHostKeys := make(map[addr.IA]*drkey.FabridKey) + asAsKeys := make(map[addr.IA]drkey.FabridKey) + hops := make([]snet.HopInterface, len(f.HopfieldMetadata)) + //ingresses := []uint16{} + //egresses := []uint16{} + + for i := 0; i < len(f.HopfieldMetadata); i++ { + hops[i] = snet.HopInterface{ + IgIf: common.IFIDType(rand.Int()), + EgIf: common.IFIDType(rand.Int()), + Policies: nil, + } + if i == 0 { + hops[i].IA = tc.srcIA + } else { + hops[i].IA = addr.IA(rand.Int()) + } + keyBytes = drkey.Key{} + copy(keyBytes[:], generateRandomBytes(16)) + if f.HopfieldMetadata[i].ASLevelKey { + asAsKeys[hops[i].IA] = drkey.FabridKey{Key: keyBytes} + } else { + asHostKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} + } + } + + err := crypto.InitValidators(f, id, s, tmpBuffer, pathKey, asHostKeys, + asAsKeys, hops) + assert.NoError(t, err) + + for i, meta := range f.HopfieldMetadata { + if meta.FabridEnabled { + + if meta.ASLevelKey { + key := asAsKeys[hops[i].IA] + err = crypto.VerifyAndUpdate(meta, id, s, tmpBuffer, key.Key[:], + uint16(hops[i].IgIf), uint16(hops[i].EgIf)) + } else { + key := asHostKeys[hops[i].IA] + err = crypto.VerifyAndUpdate(meta, id, s, tmpBuffer, key.Key[:], + uint16(hops[i].IgIf), uint16(hops[i].EgIf), + ) + } + + assert.NoError(t, err) + } + } + _, err = crypto.VerifyPathValidator(f, tmpBuffer, pathKey.Key[:]) + assert.NoError(t, err) + } + }) + }(tc) + } +} diff --git a/pkg/slayers/extension/BUILD.bazel b/pkg/slayers/extension/BUILD.bazel new file mode 100644 index 0000000000..8c0cb605be --- /dev/null +++ b/pkg/slayers/extension/BUILD.bazel @@ -0,0 +1,28 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "fabrid.go", + "identifier.go", + ], + importpath = "github.com/scionproto/scion/pkg/slayers/extension", + visibility = ["//visibility:public"], + deps = [ + "//pkg/private/serrors:go_default_library", + "//pkg/slayers:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "fabrid_test.go", + "identifier_test.go", + ], + deps = [ + ":go_default_library", + "//pkg/slayers:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + ], +) diff --git a/pkg/slayers/extension/fabrid.go b/pkg/slayers/extension/fabrid.go new file mode 100644 index 0000000000..566cc755df --- /dev/null +++ b/pkg/slayers/extension/fabrid.go @@ -0,0 +1,201 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The FABRID option format is as follows: +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NextHdr | ExtLen | OptType = 4 | OptLen | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Enc PolicyID |F|A| Hop Validation Field | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Enc PolicyID |F|A| Hop Validation Field | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | .... | | | .... | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Enc PolicyID |F|A| Hop Validation Field | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Path Validator | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +package extension + +import ( + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" +) + +const baseFabridLen uint8 = 4 +const FabridMetadataLen int = 4 +const MaxSupportedFabridHops = uint8(62) + +// The FABRID option requires the Identifier option to be present in the HBH header +// extension and defined before the FABRID option. +type FabridOption struct { + HopfieldMetadata []*FabridHopfieldMetadata + PathValidator [4]byte +} + +type FabridHopfieldMetadata struct { + EncryptedPolicyID uint8 + FabridEnabled bool + ASLevelKey bool + HopValidationField [3]byte +} + +func (f *FabridHopfieldMetadata) DecodeFabridHopfieldMetadata(b []byte) error { + if len(b) < FabridMetadataLen { + return serrors.New("Buffer too small to decode metadata", + "is", len(b), "expected", FabridMetadataLen) + } + f.decodeFabridHopfieldMetadata(b) + return nil +} + +func (f *FabridHopfieldMetadata) decodeFabridHopfieldMetadata(b []byte) { + f.EncryptedPolicyID = b[0] + copy(f.HopValidationField[:], b[1:4]) + if b[1]&0x80 > 0 { + f.FabridEnabled = true + if b[1]&0x40 > 0 { + f.ASLevelKey = true + } + } + f.HopValidationField[0] &= 0x3f +} + +func (f *FabridHopfieldMetadata) SerializeTo(b []byte) error { + if len(b) < FabridMetadataLen { + return serrors.New("Buffer too small to serialize metadata", + "is", len(b), "expected", FabridMetadataLen) + } + f.serializeTo(b) + return nil +} + +func (f *FabridHopfieldMetadata) serializeTo(b []byte) { + b[0] = f.EncryptedPolicyID + copy(b[1:4], f.HopValidationField[:]) + b[1] &= 0x3f // clear the first two (left) bits of the HVF + if f.FabridEnabled { + b[1] |= 0x80 + if f.ASLevelKey { + b[1] |= 0x40 + } + } +} + +func (f *FabridOption) validate(b []byte, currHf uint8, numHfs uint8) error { + if f == nil { + return serrors.New("Fabrid option must not be nil") + } + if len(b) < int(FabridOptionLen(numHfs)) { + return serrors.New("Raw Fabrid option too short", "is", len(b), + "expected", FabridOptionLen(numHfs)) + } + if numHfs > MaxSupportedFabridHops { + // The size of FABRID is limited to 255 bytes because of the HBH option length field + // 4 bytes + 62 * 4 bytes = 252 bytes + return serrors.New("Fabrid is not supported for paths consisting of more than 62 hopfields") + } + if currHf >= numHfs { + return serrors.New("Current HF is >= the number of HFs", "current HF", + currHf, "num hops", numHfs) + } + return nil +} + +// DecodeForHF decodes only the metadata of the current hop and stores it in f.HopfieldMetadata[0]. +// The PathValidator will not be decoded. +func (f *FabridOption) DecodeForHF(b []byte, currHf uint8, numHfs uint8) error { + if err := f.validate(b, currHf, numHfs); err != nil { + return err + } + byteIndex := int(currHf) * FabridMetadataLen + md := &FabridHopfieldMetadata{} + md.decodeFabridHopfieldMetadata(b[byteIndex : byteIndex+FabridMetadataLen]) + f.HopfieldMetadata = []*FabridHopfieldMetadata{ + md, + } + return nil +} + +func (f *FabridOption) DecodeFull(b []byte, numHfs uint8) error { + if err := f.validate(b, 0, numHfs); err != nil { + return err + } + byteIndex := 0 + f.HopfieldMetadata = make([]*FabridHopfieldMetadata, numHfs) + for i := 0; i < int(numHfs); i++ { + md := &FabridHopfieldMetadata{} + md.decodeFabridHopfieldMetadata(b[byteIndex : byteIndex+FabridMetadataLen]) + f.HopfieldMetadata[i] = md + byteIndex += FabridMetadataLen + } + copy(f.PathValidator[:], b[byteIndex:byteIndex+4]) + return nil +} + +func (f *FabridOption) SerializeTo(b []byte) error { + if f == nil { + return serrors.New("Fabrid option must not be nil") + } + if len(b) < int(FabridOptionLen(uint8(len(f.HopfieldMetadata)))) { + return serrors.New("Buffer too short", "is", len(b), + "expected", FabridOptionLen(uint8(len(f.HopfieldMetadata)))) + } + if len(f.HopfieldMetadata) > int(MaxSupportedFabridHops) { + // The size of FABRID is limited to 255 bytes because of the HBH option length field + // 4 bytes + 62 * 4 bytes = 252 bytes + return serrors.New("Fabrid is not supported for paths consisting of more than 62 hopfields") + } + byteIndex := 0 + for _, md := range f.HopfieldMetadata { + md.serializeTo(b[byteIndex : byteIndex+4]) + byteIndex += 4 + } + copy(b[byteIndex:byteIndex+4], f.PathValidator[:]) + return nil +} + +func FabridOptionLen(numHopfields uint8) uint8 { + return baseFabridLen + numHopfields*uint8(FabridMetadataLen) +} + +func ParseFabridOptionFullExtension(o *slayers.HopByHopOption, numHfs uint8) ( + *FabridOption, error) { + + if o.OptType != slayers.OptTypeFabrid { + return nil, + serrors.New("Wrong option type", "expected", + slayers.OptTypeFabrid, "actual", o.OptType) + } + f := &FabridOption{} + if err := f.DecodeFull(o.OptData, numHfs); err != nil { + return nil, err + } + return f, nil +} + +func ParseFabridOptionCurrentHop(o *slayers.HopByHopOption, currHf uint8, numHfs uint8) ( + *FabridOption, error) { + + if o.OptType != slayers.OptTypeFabrid { + return nil, + serrors.New("Wrong option type", "expected", slayers.OptTypeFabrid, "actual", o.OptType) + } + f := &FabridOption{} + if err := f.DecodeForHF(o.OptData, currHf, numHfs); err != nil { + return nil, err + } + return f, nil +} diff --git a/pkg/slayers/extension/fabrid_test.go b/pkg/slayers/extension/fabrid_test.go new file mode 100644 index 0000000000..736edd170a --- /dev/null +++ b/pkg/slayers/extension/fabrid_test.go @@ -0,0 +1,209 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package extension_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" +) + +func TestFabridDecode(t *testing.T) { + type test struct { + name string + o *slayers.HopByHopOption + currHf uint8 + numHfs uint8 + validate func(*extension.FabridOption, error, *testing.T) + } + tests := []test{ + { + name: "wrong option type", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeIdentifier, + OptData: make([]byte, 8), + }, + currHf: 1, + numHfs: 1, + validate: func(fo *extension.FabridOption, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Raw fabrid too short", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: make([]byte, 11), + }, + currHf: 1, + numHfs: 2, + validate: func(fo *extension.FabridOption, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Raw fabrid parses with 62 HF", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: make([]byte, 252), + }, + currHf: 1, + numHfs: extension.MaxSupportedFabridHops, + validate: func(fo *extension.FabridOption, err error, t *testing.T) { + assert.NoError(t, err) + }, + }, + { + name: "Raw fabrid fails parsing 63 HF", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: make([]byte, 1000), + }, + currHf: 1, + numHfs: extension.MaxSupportedFabridHops + 1, + validate: func(fo *extension.FabridOption, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Parses fabrid correctly", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: []byte{ + 0x66, 0x37, 0x88, 0x99, + 0xaa, 0x8b, 0xcc, 0xdd, + 0xaa, 0xc1, 0x01, 0x01, + 0x22, 0x33, 0x44, 0x55, + }, + }, + currHf: 1, + numHfs: 3, + validate: func(fo *extension.FabridOption, err error, t *testing.T) { + assert.NoError(t, err) + assert.Equal(t, 3, len(fo.HopfieldMetadata)) + assert.Equal(t, uint8(0x66), fo.HopfieldMetadata[0].EncryptedPolicyID) + assert.Equal(t, [3]byte{0x37, 0x88, 0x99}, + fo.HopfieldMetadata[0].HopValidationField) + assert.Equal(t, false, fo.HopfieldMetadata[0].FabridEnabled) + assert.Equal(t, false, fo.HopfieldMetadata[0].ASLevelKey) + assert.Equal(t, uint8(0xaa), fo.HopfieldMetadata[1].EncryptedPolicyID) + assert.Equal(t, [3]byte{0x0b, 0xcc, 0xdd}, + fo.HopfieldMetadata[1].HopValidationField) + assert.Equal(t, true, fo.HopfieldMetadata[1].FabridEnabled) + assert.Equal(t, false, fo.HopfieldMetadata[1].ASLevelKey) + assert.Equal(t, uint8(0xaa), fo.HopfieldMetadata[2].EncryptedPolicyID) + assert.Equal(t, [3]byte{0x01, 0x01, 0x01}, + fo.HopfieldMetadata[2].HopValidationField) + assert.Equal(t, true, fo.HopfieldMetadata[2].FabridEnabled) + assert.Equal(t, true, fo.HopfieldMetadata[2].ASLevelKey) + assert.Equal(t, [4]byte{0x22, 0x33, 0x44, 0x55}, fo.PathValidator) + }, + }, + } + + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + f, err := extension.ParseFabridOptionFullExtension(tc.o, tc.numHfs) + tc.validate(f, err, t) + }) + }(tc) + } +} + +func TestFabridSerialize(t *testing.T) { + type test struct { + name string + fabrid *extension.FabridOption + buffer []byte + validate func([]byte, error, *testing.T) + } + + tests := []test{ + { + name: "Fabrid option is nil", + fabrid: nil, + validate: func(b []byte, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Buffer too small", + fabrid: &extension.FabridOption{ + HopfieldMetadata: make([]*extension.FabridHopfieldMetadata, 1), + }, + buffer: make([]byte, 7), + validate: func(b []byte, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Too many hops", + fabrid: &extension.FabridOption{ + HopfieldMetadata: make([]*extension.FabridHopfieldMetadata, + extension.MaxSupportedFabridHops+1), + }, + buffer: make([]byte, 256), + validate: func(b []byte, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "Fabrid serializes correctly", + fabrid: &extension.FabridOption{ + HopfieldMetadata: []*extension.FabridHopfieldMetadata{ + { + EncryptedPolicyID: 0x11, + HopValidationField: [3]byte{0x22, 0x33, 0x44}, + }, + { + EncryptedPolicyID: 0xaa, + FabridEnabled: true, + HopValidationField: [3]byte{0x0b, 0xcc, 0xdd}, + }, + { + EncryptedPolicyID: 0xaa, + FabridEnabled: true, + ASLevelKey: true, + HopValidationField: [3]byte{0x01, 0x01, 0x01}, + }, + }, + PathValidator: [4]byte{0x11, 0x22, 0x33, 0x44}, + }, + buffer: make([]byte, 16), + validate: func(b []byte, err error, t *testing.T) { + assert.NoError(t, err) + assert.Equal(t, []byte{0x11, 0x22, 0x33, 0x44}, b[0:4]) //HF1 without F or A + assert.Equal(t, []byte{0xaa, 0x8b, 0xcc, 0xdd}, b[4:8]) //HF2 with F without A + assert.Equal(t, []byte{0xaa, 0xc1, 0x01, 0x01}, b[8:12]) //HF3 with F and A + assert.Equal(t, []byte{0x11, 0x22, 0x33, 0x44}, b[12:16]) //Path validator + }, + }, + } + + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := tc.fabrid.SerializeTo(tc.buffer) + tc.validate(tc.buffer, err, t) + }) + }(tc) + } +} diff --git a/pkg/slayers/extension/identifier.go b/pkg/slayers/extension/identifier.go new file mode 100644 index 0000000000..f50026bf35 --- /dev/null +++ b/pkg/slayers/extension/identifier.go @@ -0,0 +1,94 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The Identifier option format is as follows: +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NextHdr | ExtLen | OptType = 3 | OptLen = 8 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | R R R R R | Timestamp | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Packet ID | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +package extension + +import ( + "encoding/binary" + "time" + + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" +) + +const identifierLength int = 8 + +type IdentifierOption struct { + // Timestamp with 1 ms precision + Timestamp time.Time + // The packet ID + PacketID uint32 + // The base timestamp. Usually the timestamp of the first info field. + BaseTimestamp uint32 +} + +func (id *IdentifierOption) GetRelativeTimestamp() uint32 { + return uint32(id.Timestamp.UnixMilli()-int64(id.BaseTimestamp)*1000) & 0x7FFFFFF +} + +func (id *IdentifierOption) decodeTimestampFromBytes(b []byte) { + relativeTimestamp := binary.BigEndian.Uint32(b) & 0x7FFFFFF // take only the right 27bit + ts := uint64(relativeTimestamp) + 1000*uint64(id.BaseTimestamp) + id.Timestamp = time.Unix(0, int64(time.Millisecond)*int64(ts)) +} + +func (id *IdentifierOption) serializeTimestampTo(b []byte) { + binary.BigEndian.PutUint32(b, id.GetRelativeTimestamp()) +} + +func (id *IdentifierOption) decode(b []byte) error { + if len(b) < identifierLength { + return serrors.New("raw data too short", "expected", identifierLength, "actual", len(b)) + } + id.decodeTimestampFromBytes(b[0:4]) + id.PacketID = binary.BigEndian.Uint32(b[4:8]) + return nil +} + +func (id *IdentifierOption) Serialize(b []byte) error { + if id == nil { + return serrors.New("identifier option must not be nil") + } + if len(b) < identifierLength { + return serrors.New("buffer too short", "expected", identifierLength, "actual", len(b)) + } + id.serializeTimestampTo(b[0:4]) + binary.BigEndian.PutUint32(b[4:8], id.PacketID) + return nil +} + +func ParseIdentifierOption(o *slayers.HopByHopOption, baseTimestamp uint32) ( + *IdentifierOption, error) { + if o.OptType != slayers.OptTypeIdentifier { + return nil, + serrors.New("Wrong option type", "expected", slayers.OptTypeIdentifier, + "actual", o.OptType) + } + identifier := &IdentifierOption{ + BaseTimestamp: baseTimestamp, + } + if err := identifier.decode(o.OptData); err != nil { + return nil, err + } + return identifier, nil +} diff --git a/pkg/slayers/extension/identifier_test.go b/pkg/slayers/extension/identifier_test.go new file mode 100644 index 0000000000..ac298a727e --- /dev/null +++ b/pkg/slayers/extension/identifier_test.go @@ -0,0 +1,142 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package extension_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" +) + +func TestIdentifierDecode(t *testing.T) { + type test struct { + name string + o *slayers.HopByHopOption + baseTimestamp uint32 + validate func(*extension.IdentifierOption, error, *testing.T) + } + unixNow := uint32(time.Now().Unix()) + tests := []test{ + { + name: "wrong option type", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: []byte{ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + }, + }, + baseTimestamp: unixNow, + validate: func(id *extension.IdentifierOption, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "raw data too short", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeIdentifier, + OptData: []byte{ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + }, + }, + baseTimestamp: unixNow, + validate: func(id *extension.IdentifierOption, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "correct timestamp", + o: &slayers.HopByHopOption{ + OptType: slayers.OptTypeIdentifier, + OptData: []byte{ + 0xff, 0x00, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x04, + }, + }, + baseTimestamp: unixNow, + validate: func(id *extension.IdentifierOption, err error, t *testing.T) { + assert.NoError(t, err) + expectedTime := int64(unixNow)*1000 + 0x7000001 + assert.Equal(t, expectedTime, id.Timestamp.UnixMilli()) + assert.Equal(t, uint32(0x01020304), id.PacketID) + }, + }, + } + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + id, err := extension.ParseIdentifierOption(tc.o, tc.baseTimestamp) + tc.validate(id, err, t) + }) + }(tc) + } +} + +func TestIdentifierSerialize(t *testing.T) { + type test struct { + name string + identifier *extension.IdentifierOption + buffer []byte + validate func([]byte, error, *testing.T) + } + unixNow := uint32(time.Now().Unix()) + tests := []test{ + { + name: "identifier is nil", + identifier: nil, + buffer: make([]byte, 100), + validate: func(b []byte, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "buffer too small", + identifier: &extension.IdentifierOption{}, + buffer: make([]byte, 7), + validate: func(b []byte, err error, t *testing.T) { + assert.Error(t, err) + }, + }, + { + name: "correct serialization", + identifier: &extension.IdentifierOption{ + Timestamp: time.Unix(int64(unixNow), 0x7000001*int64(time.Millisecond)), + PacketID: 0xaabbccdd, + BaseTimestamp: unixNow, + }, + buffer: make([]byte, 8), + validate: func(b []byte, err error, t *testing.T) { + assert.NoError(t, err) + assert.Equal(t, []byte{0x7, 0x00, 0x00, 0x01}, b[0:4]) //the timestamp + assert.Equal(t, []byte{0xaa, 0xbb, 0xcc, 0xdd}, b[4:8]) + }, + }, + } + for _, tc := range tests { + func(tc test) { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + err := tc.identifier.Serialize(tc.buffer) + tc.validate(tc.buffer, err, t) + }) + }(tc) + } +} diff --git a/pkg/slayers/extn.go b/pkg/slayers/extn.go index 36e21f3406..fded8696a8 100644 --- a/pkg/slayers/extn.go +++ b/pkg/slayers/extn.go @@ -34,6 +34,8 @@ const ( OptTypePad1 OptionType = iota OptTypePadN OptTypeAuthenticator + OptTypeIdentifier + OptTypeFabrid ) type tlvOption struct { diff --git a/pkg/snet/path.go b/pkg/snet/path.go index f55d9c35b1..d055f0a4b6 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -86,6 +86,20 @@ func (iface PathInterface) String() string { return fmt.Sprintf("%s#%d", iface.IA, iface.ID) } +// HopInterface represents a single hop on the path +type HopInterface struct { + // IgIf represents the ingress interface ID for a hop in the path. + IgIf common.IFIDType + // EgIf represents the ingress interface ID for a hop in the path. + EgIf common.IFIDType + // IA is the ISD AS identifier of the hop. + IA addr.IA + // FabridEnabled indicates whether FABRID is enabled on this hop. + FabridEnabled bool + // Policies are the FABRID Policies that are supported by this hop. + Policies []*fabrid.Policy +} + // EpicAuths is a container for the EPIC hop authenticators. type EpicAuths struct { // AuthPHVF is the authenticator for the penultimate hop. From 6c8b559dfafa6f955545271993b44d8d0181b239 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 13:16:52 +0200 Subject: [PATCH 11/26] FABRID dataplane path Passing the WithFabrid option when choosing a path, selects an appropriate path based on the fabrid query and creates a fabrid dataplane path. --- antlr/BUILD.bazel | 7 + antlr/PathPolicyConstraints.g4 | 72 + antlr/generate.sh | 1 + antlr/pathpolicyconstraints/BUILD.bazel | 30 + .../pathpolicyconstraints_base_listener.go | 143 ++ .../pathpolicyconstraints_lexer.go | 148 ++ .../pathpolicyconstraints_listener.go | 129 ++ .../pathpolicyconstraints_parser.go | 2017 +++++++++++++++++ pkg/addr/fmt.go | 2 +- pkg/addr/isdas.go | 4 +- pkg/private/xtest/graph/BUILD.bazel | 1 + pkg/private/xtest/graph/graph.go | 18 + pkg/snet/path.go | 36 + pkg/snet/path/BUILD.bazel | 5 + pkg/snet/path/fabrid.go | 221 ++ pkg/snet/path/path.go | 2 +- private/app/path/BUILD.bazel | 1 + private/app/path/path.go | 155 +- private/path/combinator/fabrid_accumulator.go | 21 + private/path/combinator/graph.go | 16 +- private/path/fabridquery/BUILD.bazel | 40 + private/path/fabridquery/matchlist.go | 74 + private/path/fabridquery/matchlist_test.go | 83 + private/path/fabridquery/parser.go | 266 +++ private/path/fabridquery/query.go | 225 ++ private/path/fabridquery/query_test.go | 173 ++ 26 files changed, 3849 insertions(+), 41 deletions(-) create mode 100644 antlr/PathPolicyConstraints.g4 create mode 100644 antlr/pathpolicyconstraints/BUILD.bazel create mode 100644 antlr/pathpolicyconstraints/pathpolicyconstraints_base_listener.go create mode 100644 antlr/pathpolicyconstraints/pathpolicyconstraints_lexer.go create mode 100644 antlr/pathpolicyconstraints/pathpolicyconstraints_listener.go create mode 100644 antlr/pathpolicyconstraints/pathpolicyconstraints_parser.go create mode 100644 pkg/snet/path/fabrid.go create mode 100644 private/path/fabridquery/BUILD.bazel create mode 100644 private/path/fabridquery/matchlist.go create mode 100644 private/path/fabridquery/matchlist_test.go create mode 100644 private/path/fabridquery/parser.go create mode 100644 private/path/fabridquery/query.go create mode 100644 private/path/fabridquery/query_test.go diff --git a/antlr/BUILD.bazel b/antlr/BUILD.bazel index 1853d69656..dc333f4ceb 100644 --- a/antlr/BUILD.bazel +++ b/antlr/BUILD.bazel @@ -13,3 +13,10 @@ antlr( language = "Go", package = "sequence", ) + +antlr( + name = "pathpolicyconstraints", + srcs = ["PathPolicyConstraints.g4"], + language = "Go", + package = "pathpolicyconstraints", +) diff --git a/antlr/PathPolicyConstraints.g4 b/antlr/PathPolicyConstraints.g4 new file mode 100644 index 0000000000..6d9b2b0a99 --- /dev/null +++ b/antlr/PathPolicyConstraints.g4 @@ -0,0 +1,72 @@ + +grammar PathPolicyConstraints; + +fragment HEXA: [1-9a-fA-F][0-9a-fA-F]* | '0'; + +WHITESPACE: [ \t\r\n]+ -> skip; +ZERO: '0'; +NUM: [1-9][0-9]*; +WILDCARDAS: '-' '0'; +LEGACYAS: '-' NUM; +AS: '-' HEXA '_' HEXA '_' HEXA; +HASH: '#'; + +QUESTIONMARK: '?'; +ELSE: ':'; + +PLUS: '+'; +LPAR: '('; +RPAR: ')'; +LBRACE: '{'; +RBRACE: '}'; + +MONKEYTAIL: '@'; +GLOBALPOLICY: 'G'; +LOCALPOLICY: 'L'; +REJECT: 'REJECT'; + +start + : expression + ; + +query + : LBRACE expression QUESTIONMARK expression ELSE expression RBRACE #IfElse + | LBRACE expression QUESTIONMARK expression RBRACE #If + ; + +expression + : LPAR expression RPAR # Parens + | left=expression PLUS right=expression #ExpressionConcat + | identifier # ExpressionIdentifier + | query #ExpressionQuery + ; + +identifier: isd as HASH iface ',' iface MONKEYTAIL onepolicy; + +isd + : ZERO # WildcardISD + | NUM # ISD + ; + +as + : WILDCARDAS # WildcardAS + | LEGACYAS # LegacyAS + | AS # AS + ; + +iface + : ZERO # WildcardIFace + | NUM # IFace + ; + +onepolicy + : GLOBALPOLICY policyindex # GlobalPolicy + | LOCALPOLICY policyindex # LocalPolicy + | ZERO # WildcardPolicy + | REJECT # Reject + ; + +policyindex + : NUM # PolicyIndex + ; + diff --git a/antlr/generate.sh b/antlr/generate.sh index ad40f8236e..8899f38151 100755 --- a/antlr/generate.sh +++ b/antlr/generate.sh @@ -23,3 +23,4 @@ function generate { generate traffic_class generate sequence +generate pathpolicyconstraints diff --git a/antlr/pathpolicyconstraints/BUILD.bazel b/antlr/pathpolicyconstraints/BUILD.bazel new file mode 100644 index 0000000000..9ba976d431 --- /dev/null +++ b/antlr/pathpolicyconstraints/BUILD.bazel @@ -0,0 +1,30 @@ +load("//tools/lint:go.bzl", "go_library") +load("//tools/lint:go_config.bzl", "go_lint_config") +load("@apple_rules_lint//lint:defs.bzl", "package_lint_config") + +go_lint_config( + name = "go_lint_config", + exclude_filter = [ + "pathpolicyconstraints_parser.go", + ], + visibility = [ + "//visibility:public", + ], +) + +package_lint_config({ + "go": ":go_lint_config", +}) + +go_library( + name = "go_default_library", + srcs = [ + "pathpolicyconstraints_base_listener.go", + "pathpolicyconstraints_lexer.go", + "pathpolicyconstraints_listener.go", + "pathpolicyconstraints_parser.go", + ], + importpath = "github.com/scionproto/scion/antlr/pathpolicyconstraints", + visibility = ["//visibility:public"], + deps = ["@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library"], +) diff --git a/antlr/pathpolicyconstraints/pathpolicyconstraints_base_listener.go b/antlr/pathpolicyconstraints/pathpolicyconstraints_base_listener.go new file mode 100644 index 0000000000..06865b816d --- /dev/null +++ b/antlr/pathpolicyconstraints/pathpolicyconstraints_base_listener.go @@ -0,0 +1,143 @@ +// File generated by ANTLR. DO NOT EDIT. + +package pathpolicyconstraints // PathPolicyConstraints +import "github.com/antlr/antlr4/runtime/Go/antlr" + +// BasePathPolicyConstraintsListener is a complete listener for a parse tree produced by PathPolicyConstraintsParser. +type BasePathPolicyConstraintsListener struct{} + +var _ PathPolicyConstraintsListener = &BasePathPolicyConstraintsListener{} + +// VisitTerminal is called when a terminal node is visited. +func (s *BasePathPolicyConstraintsListener) VisitTerminal(node antlr.TerminalNode) {} + +// VisitErrorNode is called when an error node is visited. +func (s *BasePathPolicyConstraintsListener) VisitErrorNode(node antlr.ErrorNode) {} + +// EnterEveryRule is called when any rule is entered. +func (s *BasePathPolicyConstraintsListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} + +// ExitEveryRule is called when any rule is exited. +func (s *BasePathPolicyConstraintsListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} + +// EnterStart is called when production start is entered. +func (s *BasePathPolicyConstraintsListener) EnterStart(ctx *StartContext) {} + +// ExitStart is called when production start is exited. +func (s *BasePathPolicyConstraintsListener) ExitStart(ctx *StartContext) {} + +// EnterIfElse is called when production IfElse is entered. +func (s *BasePathPolicyConstraintsListener) EnterIfElse(ctx *IfElseContext) {} + +// ExitIfElse is called when production IfElse is exited. +func (s *BasePathPolicyConstraintsListener) ExitIfElse(ctx *IfElseContext) {} + +// EnterIf is called when production If is entered. +func (s *BasePathPolicyConstraintsListener) EnterIf(ctx *IfContext) {} + +// ExitIf is called when production If is exited. +func (s *BasePathPolicyConstraintsListener) ExitIf(ctx *IfContext) {} + +// EnterParens is called when production Parens is entered. +func (s *BasePathPolicyConstraintsListener) EnterParens(ctx *ParensContext) {} + +// ExitParens is called when production Parens is exited. +func (s *BasePathPolicyConstraintsListener) ExitParens(ctx *ParensContext) {} + +// EnterExpressionIdentifier is called when production ExpressionIdentifier is entered. +func (s *BasePathPolicyConstraintsListener) EnterExpressionIdentifier(ctx *ExpressionIdentifierContext) { +} + +// ExitExpressionIdentifier is called when production ExpressionIdentifier is exited. +func (s *BasePathPolicyConstraintsListener) ExitExpressionIdentifier(ctx *ExpressionIdentifierContext) { +} + +// EnterExpressionConcat is called when production ExpressionConcat is entered. +func (s *BasePathPolicyConstraintsListener) EnterExpressionConcat(ctx *ExpressionConcatContext) {} + +// ExitExpressionConcat is called when production ExpressionConcat is exited. +func (s *BasePathPolicyConstraintsListener) ExitExpressionConcat(ctx *ExpressionConcatContext) {} + +// EnterExpressionQuery is called when production ExpressionQuery is entered. +func (s *BasePathPolicyConstraintsListener) EnterExpressionQuery(ctx *ExpressionQueryContext) {} + +// ExitExpressionQuery is called when production ExpressionQuery is exited. +func (s *BasePathPolicyConstraintsListener) ExitExpressionQuery(ctx *ExpressionQueryContext) {} + +// EnterIdentifier is called when production identifier is entered. +func (s *BasePathPolicyConstraintsListener) EnterIdentifier(ctx *IdentifierContext) {} + +// ExitIdentifier is called when production identifier is exited. +func (s *BasePathPolicyConstraintsListener) ExitIdentifier(ctx *IdentifierContext) {} + +// EnterWildcardISD is called when production WildcardISD is entered. +func (s *BasePathPolicyConstraintsListener) EnterWildcardISD(ctx *WildcardISDContext) {} + +// ExitWildcardISD is called when production WildcardISD is exited. +func (s *BasePathPolicyConstraintsListener) ExitWildcardISD(ctx *WildcardISDContext) {} + +// EnterISD is called when production ISD is entered. +func (s *BasePathPolicyConstraintsListener) EnterISD(ctx *ISDContext) {} + +// ExitISD is called when production ISD is exited. +func (s *BasePathPolicyConstraintsListener) ExitISD(ctx *ISDContext) {} + +// EnterWildcardAS is called when production WildcardAS is entered. +func (s *BasePathPolicyConstraintsListener) EnterWildcardAS(ctx *WildcardASContext) {} + +// ExitWildcardAS is called when production WildcardAS is exited. +func (s *BasePathPolicyConstraintsListener) ExitWildcardAS(ctx *WildcardASContext) {} + +// EnterLegacyAS is called when production LegacyAS is entered. +func (s *BasePathPolicyConstraintsListener) EnterLegacyAS(ctx *LegacyASContext) {} + +// ExitLegacyAS is called when production LegacyAS is exited. +func (s *BasePathPolicyConstraintsListener) ExitLegacyAS(ctx *LegacyASContext) {} + +// EnterAS is called when production AS is entered. +func (s *BasePathPolicyConstraintsListener) EnterAS(ctx *ASContext) {} + +// ExitAS is called when production AS is exited. +func (s *BasePathPolicyConstraintsListener) ExitAS(ctx *ASContext) {} + +// EnterWildcardIFace is called when production WildcardIFace is entered. +func (s *BasePathPolicyConstraintsListener) EnterWildcardIFace(ctx *WildcardIFaceContext) {} + +// ExitWildcardIFace is called when production WildcardIFace is exited. +func (s *BasePathPolicyConstraintsListener) ExitWildcardIFace(ctx *WildcardIFaceContext) {} + +// EnterIFace is called when production IFace is entered. +func (s *BasePathPolicyConstraintsListener) EnterIFace(ctx *IFaceContext) {} + +// ExitIFace is called when production IFace is exited. +func (s *BasePathPolicyConstraintsListener) ExitIFace(ctx *IFaceContext) {} + +// EnterGlobalPolicy is called when production GlobalPolicy is entered. +func (s *BasePathPolicyConstraintsListener) EnterGlobalPolicy(ctx *GlobalPolicyContext) {} + +// ExitGlobalPolicy is called when production GlobalPolicy is exited. +func (s *BasePathPolicyConstraintsListener) ExitGlobalPolicy(ctx *GlobalPolicyContext) {} + +// EnterLocalPolicy is called when production LocalPolicy is entered. +func (s *BasePathPolicyConstraintsListener) EnterLocalPolicy(ctx *LocalPolicyContext) {} + +// ExitLocalPolicy is called when production LocalPolicy is exited. +func (s *BasePathPolicyConstraintsListener) ExitLocalPolicy(ctx *LocalPolicyContext) {} + +// EnterWildcardPolicy is called when production WildcardPolicy is entered. +func (s *BasePathPolicyConstraintsListener) EnterWildcardPolicy(ctx *WildcardPolicyContext) {} + +// ExitWildcardPolicy is called when production WildcardPolicy is exited. +func (s *BasePathPolicyConstraintsListener) ExitWildcardPolicy(ctx *WildcardPolicyContext) {} + +// EnterReject is called when production Reject is entered. +func (s *BasePathPolicyConstraintsListener) EnterReject(ctx *RejectContext) {} + +// ExitReject is called when production Reject is exited. +func (s *BasePathPolicyConstraintsListener) ExitReject(ctx *RejectContext) {} + +// EnterPolicyIndex is called when production PolicyIndex is entered. +func (s *BasePathPolicyConstraintsListener) EnterPolicyIndex(ctx *PolicyIndexContext) {} + +// ExitPolicyIndex is called when production PolicyIndex is exited. +func (s *BasePathPolicyConstraintsListener) ExitPolicyIndex(ctx *PolicyIndexContext) {} diff --git a/antlr/pathpolicyconstraints/pathpolicyconstraints_lexer.go b/antlr/pathpolicyconstraints/pathpolicyconstraints_lexer.go new file mode 100644 index 0000000000..8927f64c4a --- /dev/null +++ b/antlr/pathpolicyconstraints/pathpolicyconstraints_lexer.go @@ -0,0 +1,148 @@ +// File generated by ANTLR. DO NOT EDIT. + +package pathpolicyconstraints + +import ( + "fmt" + "unicode" + + "github.com/antlr/antlr4/runtime/Go/antlr" +) + +// Suppress unused import error +var _ = fmt.Printf +var _ = unicode.IsLetter + +var serializedLexerAtn = []uint16{ + 3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 21, 113, + 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, + 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, + 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, + 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 3, 2, 3, 2, 3, 3, + 3, 3, 7, 3, 48, 10, 3, 12, 3, 14, 3, 51, 11, 3, 3, 3, 5, 3, 54, 10, 3, + 3, 4, 6, 4, 57, 10, 4, 13, 4, 14, 4, 58, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, + 3, 6, 7, 6, 67, 10, 6, 12, 6, 14, 6, 70, 11, 6, 3, 7, 3, 7, 3, 7, 3, 8, + 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, + 11, 3, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, + 3, 16, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, + 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 2, 2, 22, 3, 3, 5, 2, 7, 4, 9, 5, + 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, + 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 3, 2, 7, 5, 2, 51, + 59, 67, 72, 99, 104, 5, 2, 50, 59, 67, 72, 99, 104, 5, 2, 11, 12, 15, 15, + 34, 34, 3, 2, 51, 59, 3, 2, 50, 59, 2, 115, 2, 3, 3, 2, 2, 2, 2, 7, 3, + 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, + 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, + 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, + 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, + 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 3, 43, 3, 2, 2, 2, 5, 53, 3, 2, + 2, 2, 7, 56, 3, 2, 2, 2, 9, 62, 3, 2, 2, 2, 11, 64, 3, 2, 2, 2, 13, 71, + 3, 2, 2, 2, 15, 74, 3, 2, 2, 2, 17, 77, 3, 2, 2, 2, 19, 84, 3, 2, 2, 2, + 21, 86, 3, 2, 2, 2, 23, 88, 3, 2, 2, 2, 25, 90, 3, 2, 2, 2, 27, 92, 3, + 2, 2, 2, 29, 94, 3, 2, 2, 2, 31, 96, 3, 2, 2, 2, 33, 98, 3, 2, 2, 2, 35, + 100, 3, 2, 2, 2, 37, 102, 3, 2, 2, 2, 39, 104, 3, 2, 2, 2, 41, 106, 3, + 2, 2, 2, 43, 44, 7, 46, 2, 2, 44, 4, 3, 2, 2, 2, 45, 49, 9, 2, 2, 2, 46, + 48, 9, 3, 2, 2, 47, 46, 3, 2, 2, 2, 48, 51, 3, 2, 2, 2, 49, 47, 3, 2, 2, + 2, 49, 50, 3, 2, 2, 2, 50, 54, 3, 2, 2, 2, 51, 49, 3, 2, 2, 2, 52, 54, + 7, 50, 2, 2, 53, 45, 3, 2, 2, 2, 53, 52, 3, 2, 2, 2, 54, 6, 3, 2, 2, 2, + 55, 57, 9, 4, 2, 2, 56, 55, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 56, 3, + 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 61, 8, 4, 2, 2, 61, + 8, 3, 2, 2, 2, 62, 63, 7, 50, 2, 2, 63, 10, 3, 2, 2, 2, 64, 68, 9, 5, 2, + 2, 65, 67, 9, 6, 2, 2, 66, 65, 3, 2, 2, 2, 67, 70, 3, 2, 2, 2, 68, 66, + 3, 2, 2, 2, 68, 69, 3, 2, 2, 2, 69, 12, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, + 71, 72, 7, 47, 2, 2, 72, 73, 7, 50, 2, 2, 73, 14, 3, 2, 2, 2, 74, 75, 7, + 47, 2, 2, 75, 76, 5, 11, 6, 2, 76, 16, 3, 2, 2, 2, 77, 78, 7, 47, 2, 2, + 78, 79, 5, 5, 3, 2, 79, 80, 7, 97, 2, 2, 80, 81, 5, 5, 3, 2, 81, 82, 7, + 97, 2, 2, 82, 83, 5, 5, 3, 2, 83, 18, 3, 2, 2, 2, 84, 85, 7, 37, 2, 2, + 85, 20, 3, 2, 2, 2, 86, 87, 7, 65, 2, 2, 87, 22, 3, 2, 2, 2, 88, 89, 7, + 60, 2, 2, 89, 24, 3, 2, 2, 2, 90, 91, 7, 45, 2, 2, 91, 26, 3, 2, 2, 2, + 92, 93, 7, 42, 2, 2, 93, 28, 3, 2, 2, 2, 94, 95, 7, 43, 2, 2, 95, 30, 3, + 2, 2, 2, 96, 97, 7, 125, 2, 2, 97, 32, 3, 2, 2, 2, 98, 99, 7, 127, 2, 2, + 99, 34, 3, 2, 2, 2, 100, 101, 7, 66, 2, 2, 101, 36, 3, 2, 2, 2, 102, 103, + 7, 73, 2, 2, 103, 38, 3, 2, 2, 2, 104, 105, 7, 78, 2, 2, 105, 40, 3, 2, + 2, 2, 106, 107, 7, 84, 2, 2, 107, 108, 7, 71, 2, 2, 108, 109, 7, 76, 2, + 2, 109, 110, 7, 71, 2, 2, 110, 111, 7, 69, 2, 2, 111, 112, 7, 86, 2, 2, + 112, 42, 3, 2, 2, 2, 7, 2, 49, 53, 58, 68, 3, 8, 2, 2, +} + +var lexerChannelNames = []string{ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", +} + +var lexerModeNames = []string{ + "DEFAULT_MODE", +} + +var lexerLiteralNames = []string{ + "", "','", "", "'0'", "", "", "", "", "'#'", "'?'", "':'", "'+'", "'('", + "')'", "'{'", "'}'", "'@'", "'G'", "'L'", "'REJECT'", +} + +var lexerSymbolicNames = []string{ + "", "", "WHITESPACE", "ZERO", "NUM", "WILDCARDAS", "LEGACYAS", "AS", "HASH", + "QUESTIONMARK", "ELSE", "PLUS", "LPAR", "RPAR", "LBRACE", "RBRACE", "MONKEYTAIL", + "GLOBALPOLICY", "LOCALPOLICY", "REJECT", +} + +var lexerRuleNames = []string{ + "T__0", "HEXA", "WHITESPACE", "ZERO", "NUM", "WILDCARDAS", "LEGACYAS", + "AS", "HASH", "QUESTIONMARK", "ELSE", "PLUS", "LPAR", "RPAR", "LBRACE", + "RBRACE", "MONKEYTAIL", "GLOBALPOLICY", "LOCALPOLICY", "REJECT", +} + +type PathPolicyConstraintsLexer struct { + *antlr.BaseLexer + channelNames []string + modeNames []string + // TODO: EOF string +} + +// NewPathPolicyConstraintsLexer produces a new lexer instance for the optional input antlr.CharStream. +// +// The *PathPolicyConstraintsLexer instance produced may be reused by calling the SetInputStream method. +// The initial lexer configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. +func NewPathPolicyConstraintsLexer(input antlr.CharStream) *PathPolicyConstraintsLexer { + l := new(PathPolicyConstraintsLexer) + lexerDeserializer := antlr.NewATNDeserializer(nil) + lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn) + lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState)) + for index, ds := range lexerAtn.DecisionToState { + lexerDecisionToDFA[index] = antlr.NewDFA(ds, index) + } + l.BaseLexer = antlr.NewBaseLexer(input) + l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache()) + + l.channelNames = lexerChannelNames + l.modeNames = lexerModeNames + l.RuleNames = lexerRuleNames + l.LiteralNames = lexerLiteralNames + l.SymbolicNames = lexerSymbolicNames + l.GrammarFileName = "PathPolicyConstraints.g4" + // TODO: l.EOF = antlr.TokenEOF + + return l +} + +// PathPolicyConstraintsLexer tokens. +const ( + PathPolicyConstraintsLexerT__0 = 1 + PathPolicyConstraintsLexerWHITESPACE = 2 + PathPolicyConstraintsLexerZERO = 3 + PathPolicyConstraintsLexerNUM = 4 + PathPolicyConstraintsLexerWILDCARDAS = 5 + PathPolicyConstraintsLexerLEGACYAS = 6 + PathPolicyConstraintsLexerAS = 7 + PathPolicyConstraintsLexerHASH = 8 + PathPolicyConstraintsLexerQUESTIONMARK = 9 + PathPolicyConstraintsLexerELSE = 10 + PathPolicyConstraintsLexerPLUS = 11 + PathPolicyConstraintsLexerLPAR = 12 + PathPolicyConstraintsLexerRPAR = 13 + PathPolicyConstraintsLexerLBRACE = 14 + PathPolicyConstraintsLexerRBRACE = 15 + PathPolicyConstraintsLexerMONKEYTAIL = 16 + PathPolicyConstraintsLexerGLOBALPOLICY = 17 + PathPolicyConstraintsLexerLOCALPOLICY = 18 + PathPolicyConstraintsLexerREJECT = 19 +) diff --git a/antlr/pathpolicyconstraints/pathpolicyconstraints_listener.go b/antlr/pathpolicyconstraints/pathpolicyconstraints_listener.go new file mode 100644 index 0000000000..11ae254a3e --- /dev/null +++ b/antlr/pathpolicyconstraints/pathpolicyconstraints_listener.go @@ -0,0 +1,129 @@ +// File generated by ANTLR. DO NOT EDIT. + +package pathpolicyconstraints // PathPolicyConstraints +import "github.com/antlr/antlr4/runtime/Go/antlr" + +// PathPolicyConstraintsListener is a complete listener for a parse tree produced by PathPolicyConstraintsParser. +type PathPolicyConstraintsListener interface { + antlr.ParseTreeListener + + // EnterStart is called when entering the start production. + EnterStart(c *StartContext) + + // EnterIfElse is called when entering the IfElse production. + EnterIfElse(c *IfElseContext) + + // EnterIf is called when entering the If production. + EnterIf(c *IfContext) + + // EnterParens is called when entering the Parens production. + EnterParens(c *ParensContext) + + // EnterExpressionIdentifier is called when entering the ExpressionIdentifier production. + EnterExpressionIdentifier(c *ExpressionIdentifierContext) + + // EnterExpressionConcat is called when entering the ExpressionConcat production. + EnterExpressionConcat(c *ExpressionConcatContext) + + // EnterExpressionQuery is called when entering the ExpressionQuery production. + EnterExpressionQuery(c *ExpressionQueryContext) + + // EnterIdentifier is called when entering the identifier production. + EnterIdentifier(c *IdentifierContext) + + // EnterWildcardISD is called when entering the WildcardISD production. + EnterWildcardISD(c *WildcardISDContext) + + // EnterISD is called when entering the ISD production. + EnterISD(c *ISDContext) + + // EnterWildcardAS is called when entering the WildcardAS production. + EnterWildcardAS(c *WildcardASContext) + + // EnterLegacyAS is called when entering the LegacyAS production. + EnterLegacyAS(c *LegacyASContext) + + // EnterAS is called when entering the AS production. + EnterAS(c *ASContext) + + // EnterWildcardIFace is called when entering the WildcardIFace production. + EnterWildcardIFace(c *WildcardIFaceContext) + + // EnterIFace is called when entering the IFace production. + EnterIFace(c *IFaceContext) + + // EnterGlobalPolicy is called when entering the GlobalPolicy production. + EnterGlobalPolicy(c *GlobalPolicyContext) + + // EnterLocalPolicy is called when entering the LocalPolicy production. + EnterLocalPolicy(c *LocalPolicyContext) + + // EnterWildcardPolicy is called when entering the WildcardPolicy production. + EnterWildcardPolicy(c *WildcardPolicyContext) + + // EnterReject is called when entering the Reject production. + EnterReject(c *RejectContext) + + // EnterPolicyIndex is called when entering the PolicyIndex production. + EnterPolicyIndex(c *PolicyIndexContext) + + // ExitStart is called when exiting the start production. + ExitStart(c *StartContext) + + // ExitIfElse is called when exiting the IfElse production. + ExitIfElse(c *IfElseContext) + + // ExitIf is called when exiting the If production. + ExitIf(c *IfContext) + + // ExitParens is called when exiting the Parens production. + ExitParens(c *ParensContext) + + // ExitExpressionIdentifier is called when exiting the ExpressionIdentifier production. + ExitExpressionIdentifier(c *ExpressionIdentifierContext) + + // ExitExpressionConcat is called when exiting the ExpressionConcat production. + ExitExpressionConcat(c *ExpressionConcatContext) + + // ExitExpressionQuery is called when exiting the ExpressionQuery production. + ExitExpressionQuery(c *ExpressionQueryContext) + + // ExitIdentifier is called when exiting the identifier production. + ExitIdentifier(c *IdentifierContext) + + // ExitWildcardISD is called when exiting the WildcardISD production. + ExitWildcardISD(c *WildcardISDContext) + + // ExitISD is called when exiting the ISD production. + ExitISD(c *ISDContext) + + // ExitWildcardAS is called when exiting the WildcardAS production. + ExitWildcardAS(c *WildcardASContext) + + // ExitLegacyAS is called when exiting the LegacyAS production. + ExitLegacyAS(c *LegacyASContext) + + // ExitAS is called when exiting the AS production. + ExitAS(c *ASContext) + + // ExitWildcardIFace is called when exiting the WildcardIFace production. + ExitWildcardIFace(c *WildcardIFaceContext) + + // ExitIFace is called when exiting the IFace production. + ExitIFace(c *IFaceContext) + + // ExitGlobalPolicy is called when exiting the GlobalPolicy production. + ExitGlobalPolicy(c *GlobalPolicyContext) + + // ExitLocalPolicy is called when exiting the LocalPolicy production. + ExitLocalPolicy(c *LocalPolicyContext) + + // ExitWildcardPolicy is called when exiting the WildcardPolicy production. + ExitWildcardPolicy(c *WildcardPolicyContext) + + // ExitReject is called when exiting the Reject production. + ExitReject(c *RejectContext) + + // ExitPolicyIndex is called when exiting the PolicyIndex production. + ExitPolicyIndex(c *PolicyIndexContext) +} diff --git a/antlr/pathpolicyconstraints/pathpolicyconstraints_parser.go b/antlr/pathpolicyconstraints/pathpolicyconstraints_parser.go new file mode 100644 index 0000000000..6644ae29e9 --- /dev/null +++ b/antlr/pathpolicyconstraints/pathpolicyconstraints_parser.go @@ -0,0 +1,2017 @@ +// File generated by ANTLR. DO NOT EDIT. + +package pathpolicyconstraints // PathPolicyConstraints +import ( + "fmt" + "reflect" + "strconv" + + "github.com/antlr/antlr4/runtime/Go/antlr" +) + +// Suppress unused import errors +var _ = fmt.Printf +var _ = reflect.Copy +var _ = strconv.Itoa + +var parserATN = []uint16{ + 3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 21, 88, 4, + 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, + 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 37, 10, + 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 46, 10, 4, 3, 4, 3, + 4, 3, 4, 7, 4, 51, 10, 4, 12, 4, 14, 4, 54, 11, 4, 3, 5, 3, 5, 3, 5, 3, + 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 5, 6, 67, 10, 6, 3, 7, 3, + 7, 3, 7, 5, 7, 72, 10, 7, 3, 8, 3, 8, 5, 8, 76, 10, 8, 3, 9, 3, 9, 3, 9, + 3, 9, 3, 9, 3, 9, 5, 9, 84, 10, 9, 3, 10, 3, 10, 3, 10, 2, 3, 6, 11, 2, + 4, 6, 8, 10, 12, 14, 16, 18, 2, 2, 2, 89, 2, 20, 3, 2, 2, 2, 4, 36, 3, + 2, 2, 2, 6, 45, 3, 2, 2, 2, 8, 55, 3, 2, 2, 2, 10, 66, 3, 2, 2, 2, 12, + 71, 3, 2, 2, 2, 14, 75, 3, 2, 2, 2, 16, 83, 3, 2, 2, 2, 18, 85, 3, 2, 2, + 2, 20, 21, 5, 6, 4, 2, 21, 3, 3, 2, 2, 2, 22, 23, 7, 16, 2, 2, 23, 24, + 5, 6, 4, 2, 24, 25, 7, 11, 2, 2, 25, 26, 5, 6, 4, 2, 26, 27, 7, 12, 2, + 2, 27, 28, 5, 6, 4, 2, 28, 29, 7, 17, 2, 2, 29, 37, 3, 2, 2, 2, 30, 31, + 7, 16, 2, 2, 31, 32, 5, 6, 4, 2, 32, 33, 7, 11, 2, 2, 33, 34, 5, 6, 4, + 2, 34, 35, 7, 17, 2, 2, 35, 37, 3, 2, 2, 2, 36, 22, 3, 2, 2, 2, 36, 30, + 3, 2, 2, 2, 37, 5, 3, 2, 2, 2, 38, 39, 8, 4, 1, 2, 39, 40, 7, 14, 2, 2, + 40, 41, 5, 6, 4, 2, 41, 42, 7, 15, 2, 2, 42, 46, 3, 2, 2, 2, 43, 46, 5, + 8, 5, 2, 44, 46, 5, 4, 3, 2, 45, 38, 3, 2, 2, 2, 45, 43, 3, 2, 2, 2, 45, + 44, 3, 2, 2, 2, 46, 52, 3, 2, 2, 2, 47, 48, 12, 5, 2, 2, 48, 49, 7, 13, + 2, 2, 49, 51, 5, 6, 4, 6, 50, 47, 3, 2, 2, 2, 51, 54, 3, 2, 2, 2, 52, 50, + 3, 2, 2, 2, 52, 53, 3, 2, 2, 2, 53, 7, 3, 2, 2, 2, 54, 52, 3, 2, 2, 2, + 55, 56, 5, 10, 6, 2, 56, 57, 5, 12, 7, 2, 57, 58, 7, 10, 2, 2, 58, 59, + 5, 14, 8, 2, 59, 60, 7, 3, 2, 2, 60, 61, 5, 14, 8, 2, 61, 62, 7, 18, 2, + 2, 62, 63, 5, 16, 9, 2, 63, 9, 3, 2, 2, 2, 64, 67, 7, 5, 2, 2, 65, 67, + 7, 6, 2, 2, 66, 64, 3, 2, 2, 2, 66, 65, 3, 2, 2, 2, 67, 11, 3, 2, 2, 2, + 68, 72, 7, 7, 2, 2, 69, 72, 7, 8, 2, 2, 70, 72, 7, 9, 2, 2, 71, 68, 3, + 2, 2, 2, 71, 69, 3, 2, 2, 2, 71, 70, 3, 2, 2, 2, 72, 13, 3, 2, 2, 2, 73, + 76, 7, 5, 2, 2, 74, 76, 7, 6, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, + 2, 76, 15, 3, 2, 2, 2, 77, 78, 7, 19, 2, 2, 78, 84, 5, 18, 10, 2, 79, 80, + 7, 20, 2, 2, 80, 84, 5, 18, 10, 2, 81, 84, 7, 5, 2, 2, 82, 84, 7, 21, 2, + 2, 83, 77, 3, 2, 2, 2, 83, 79, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 82, + 3, 2, 2, 2, 84, 17, 3, 2, 2, 2, 85, 86, 7, 6, 2, 2, 86, 19, 3, 2, 2, 2, + 9, 36, 45, 52, 66, 71, 75, 83, +} +var literalNames = []string{ + "", "','", "", "'0'", "", "", "", "", "'#'", "'?'", "':'", "'+'", "'('", + "')'", "'{'", "'}'", "'@'", "'G'", "'L'", "'REJECT'", +} +var symbolicNames = []string{ + "", "", "WHITESPACE", "ZERO", "NUM", "WILDCARDAS", "LEGACYAS", "AS", "HASH", + "QUESTIONMARK", "ELSE", "PLUS", "LPAR", "RPAR", "LBRACE", "RBRACE", "MONKEYTAIL", + "GLOBALPOLICY", "LOCALPOLICY", "REJECT", +} + +var ruleNames = []string{ + "start", "query", "expression", "identifier", "isd", "as", "iface", "onepolicy", + "policyindex", +} + +type PathPolicyConstraintsParser struct { + *antlr.BaseParser +} + +// NewPathPolicyConstraintsParser produces a new parser instance for the optional input antlr.TokenStream. +// +// The *PathPolicyConstraintsParser instance produced may be reused by calling the SetInputStream method. +// The initial parser configuration is expensive to construct, and the object is not thread-safe; +// however, if used within a Golang sync.Pool, the construction cost amortizes well and the +// objects can be used in a thread-safe manner. +func NewPathPolicyConstraintsParser(input antlr.TokenStream) *PathPolicyConstraintsParser { + this := new(PathPolicyConstraintsParser) + deserializer := antlr.NewATNDeserializer(nil) + deserializedATN := deserializer.DeserializeFromUInt16(parserATN) + decisionToDFA := make([]*antlr.DFA, len(deserializedATN.DecisionToState)) + for index, ds := range deserializedATN.DecisionToState { + decisionToDFA[index] = antlr.NewDFA(ds, index) + } + this.BaseParser = antlr.NewBaseParser(input) + + this.Interpreter = antlr.NewParserATNSimulator(this, deserializedATN, decisionToDFA, antlr.NewPredictionContextCache()) + this.RuleNames = ruleNames + this.LiteralNames = literalNames + this.SymbolicNames = symbolicNames + this.GrammarFileName = "PathPolicyConstraints.g4" + + return this +} + +// PathPolicyConstraintsParser tokens. +const ( + PathPolicyConstraintsParserEOF = antlr.TokenEOF + PathPolicyConstraintsParserT__0 = 1 + PathPolicyConstraintsParserWHITESPACE = 2 + PathPolicyConstraintsParserZERO = 3 + PathPolicyConstraintsParserNUM = 4 + PathPolicyConstraintsParserWILDCARDAS = 5 + PathPolicyConstraintsParserLEGACYAS = 6 + PathPolicyConstraintsParserAS = 7 + PathPolicyConstraintsParserHASH = 8 + PathPolicyConstraintsParserQUESTIONMARK = 9 + PathPolicyConstraintsParserELSE = 10 + PathPolicyConstraintsParserPLUS = 11 + PathPolicyConstraintsParserLPAR = 12 + PathPolicyConstraintsParserRPAR = 13 + PathPolicyConstraintsParserLBRACE = 14 + PathPolicyConstraintsParserRBRACE = 15 + PathPolicyConstraintsParserMONKEYTAIL = 16 + PathPolicyConstraintsParserGLOBALPOLICY = 17 + PathPolicyConstraintsParserLOCALPOLICY = 18 + PathPolicyConstraintsParserREJECT = 19 +) + +// PathPolicyConstraintsParser rules. +const ( + PathPolicyConstraintsParserRULE_start = 0 + PathPolicyConstraintsParserRULE_query = 1 + PathPolicyConstraintsParserRULE_expression = 2 + PathPolicyConstraintsParserRULE_identifier = 3 + PathPolicyConstraintsParserRULE_isd = 4 + PathPolicyConstraintsParserRULE_as = 5 + PathPolicyConstraintsParserRULE_iface = 6 + PathPolicyConstraintsParserRULE_onepolicy = 7 + PathPolicyConstraintsParserRULE_policyindex = 8 +) + +// IStartContext is an interface to support dynamic dispatch. +type IStartContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsStartContext differentiates from other interfaces. + IsStartContext() +} + +type StartContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyStartContext() *StartContext { + var p = new(StartContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_start + return p +} + +func (*StartContext) IsStartContext() {} + +func NewStartContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *StartContext { + var p = new(StartContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_start + + return p +} + +func (s *StartContext) GetParser() antlr.Parser { return s.parser } + +func (s *StartContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *StartContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *StartContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *StartContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterStart(s) + } +} + +func (s *StartContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitStart(s) + } +} + +func (p *PathPolicyConstraintsParser) Start() (localctx IStartContext) { + this := p + _ = this + + localctx = NewStartContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 0, PathPolicyConstraintsParserRULE_start) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(18) + p.expression(0) + } + + return localctx +} + +// IQueryContext is an interface to support dynamic dispatch. +type IQueryContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsQueryContext differentiates from other interfaces. + IsQueryContext() +} + +type QueryContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyQueryContext() *QueryContext { + var p = new(QueryContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_query + return p +} + +func (*QueryContext) IsQueryContext() {} + +func NewQueryContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *QueryContext { + var p = new(QueryContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_query + + return p +} + +func (s *QueryContext) GetParser() antlr.Parser { return s.parser } + +func (s *QueryContext) CopyFrom(ctx *QueryContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *QueryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *QueryContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type IfElseContext struct { + *QueryContext +} + +func NewIfElseContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *IfElseContext { + var p = new(IfElseContext) + + p.QueryContext = NewEmptyQueryContext() + p.parser = parser + p.CopyFrom(ctx.(*QueryContext)) + + return p +} + +func (s *IfElseContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IfElseContext) LBRACE() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserLBRACE, 0) +} + +func (s *IfElseContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *IfElseContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *IfElseContext) QUESTIONMARK() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserQUESTIONMARK, 0) +} + +func (s *IfElseContext) ELSE() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserELSE, 0) +} + +func (s *IfElseContext) RBRACE() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserRBRACE, 0) +} + +func (s *IfElseContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterIfElse(s) + } +} + +func (s *IfElseContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitIfElse(s) + } +} + +type IfContext struct { + *QueryContext +} + +func NewIfContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *IfContext { + var p = new(IfContext) + + p.QueryContext = NewEmptyQueryContext() + p.parser = parser + p.CopyFrom(ctx.(*QueryContext)) + + return p +} + +func (s *IfContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IfContext) LBRACE() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserLBRACE, 0) +} + +func (s *IfContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *IfContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *IfContext) QUESTIONMARK() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserQUESTIONMARK, 0) +} + +func (s *IfContext) RBRACE() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserRBRACE, 0) +} + +func (s *IfContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterIf(s) + } +} + +func (s *IfContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitIf(s) + } +} + +func (p *PathPolicyConstraintsParser) Query() (localctx IQueryContext) { + this := p + _ = this + + localctx = NewQueryContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 2, PathPolicyConstraintsParserRULE_query) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.SetState(34) + p.GetErrorHandler().Sync(p) + switch p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 0, p.GetParserRuleContext()) { + case 1: + localctx = NewIfElseContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(20) + p.Match(PathPolicyConstraintsParserLBRACE) + } + { + p.SetState(21) + p.expression(0) + } + { + p.SetState(22) + p.Match(PathPolicyConstraintsParserQUESTIONMARK) + } + { + p.SetState(23) + p.expression(0) + } + { + p.SetState(24) + p.Match(PathPolicyConstraintsParserELSE) + } + { + p.SetState(25) + p.expression(0) + } + { + p.SetState(26) + p.Match(PathPolicyConstraintsParserRBRACE) + } + + case 2: + localctx = NewIfContext(p, localctx) + p.EnterOuterAlt(localctx, 2) + { + p.SetState(28) + p.Match(PathPolicyConstraintsParserLBRACE) + } + { + p.SetState(29) + p.expression(0) + } + { + p.SetState(30) + p.Match(PathPolicyConstraintsParserQUESTIONMARK) + } + { + p.SetState(31) + p.expression(0) + } + { + p.SetState(32) + p.Match(PathPolicyConstraintsParserRBRACE) + } + + } + + return localctx +} + +// IExpressionContext is an interface to support dynamic dispatch. +type IExpressionContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsExpressionContext differentiates from other interfaces. + IsExpressionContext() +} + +type ExpressionContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyExpressionContext() *ExpressionContext { + var p = new(ExpressionContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_expression + return p +} + +func (*ExpressionContext) IsExpressionContext() {} + +func NewExpressionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ExpressionContext { + var p = new(ExpressionContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_expression + + return p +} + +func (s *ExpressionContext) GetParser() antlr.Parser { return s.parser } + +func (s *ExpressionContext) CopyFrom(ctx *ExpressionContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *ExpressionContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type ParensContext struct { + *ExpressionContext +} + +func NewParensContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ParensContext { + var p = new(ParensContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *ParensContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ParensContext) LPAR() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserLPAR, 0) +} + +func (s *ParensContext) Expression() IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *ParensContext) RPAR() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserRPAR, 0) +} + +func (s *ParensContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterParens(s) + } +} + +func (s *ParensContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitParens(s) + } +} + +type ExpressionIdentifierContext struct { + *ExpressionContext +} + +func NewExpressionIdentifierContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ExpressionIdentifierContext { + var p = new(ExpressionIdentifierContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *ExpressionIdentifierContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionIdentifierContext) Identifier() IIdentifierContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IIdentifierContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IIdentifierContext) +} + +func (s *ExpressionIdentifierContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterExpressionIdentifier(s) + } +} + +func (s *ExpressionIdentifierContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitExpressionIdentifier(s) + } +} + +type ExpressionConcatContext struct { + *ExpressionContext + left IExpressionContext + right IExpressionContext +} + +func NewExpressionConcatContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ExpressionConcatContext { + var p = new(ExpressionConcatContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *ExpressionConcatContext) GetLeft() IExpressionContext { return s.left } + +func (s *ExpressionConcatContext) GetRight() IExpressionContext { return s.right } + +func (s *ExpressionConcatContext) SetLeft(v IExpressionContext) { s.left = v } + +func (s *ExpressionConcatContext) SetRight(v IExpressionContext) { s.right = v } + +func (s *ExpressionConcatContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionConcatContext) PLUS() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserPLUS, 0) +} + +func (s *ExpressionConcatContext) AllExpression() []IExpressionContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IExpressionContext)(nil)).Elem()) + var tst = make([]IExpressionContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IExpressionContext) + } + } + + return tst +} + +func (s *ExpressionConcatContext) Expression(i int) IExpressionContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IExpressionContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IExpressionContext) +} + +func (s *ExpressionConcatContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterExpressionConcat(s) + } +} + +func (s *ExpressionConcatContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitExpressionConcat(s) + } +} + +type ExpressionQueryContext struct { + *ExpressionContext +} + +func NewExpressionQueryContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ExpressionQueryContext { + var p = new(ExpressionQueryContext) + + p.ExpressionContext = NewEmptyExpressionContext() + p.parser = parser + p.CopyFrom(ctx.(*ExpressionContext)) + + return p +} + +func (s *ExpressionQueryContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ExpressionQueryContext) Query() IQueryContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IQueryContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IQueryContext) +} + +func (s *ExpressionQueryContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterExpressionQuery(s) + } +} + +func (s *ExpressionQueryContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitExpressionQuery(s) + } +} + +func (p *PathPolicyConstraintsParser) Expression() (localctx IExpressionContext) { + return p.expression(0) +} + +func (p *PathPolicyConstraintsParser) expression(_p int) (localctx IExpressionContext) { + this := p + _ = this + + var _parentctx antlr.ParserRuleContext = p.GetParserRuleContext() + _parentState := p.GetState() + localctx = NewExpressionContext(p, p.GetParserRuleContext(), _parentState) + var _prevctx IExpressionContext = localctx + var _ antlr.ParserRuleContext = _prevctx // TODO: To prevent unused variable warning. + _startState := 4 + p.EnterRecursionRule(localctx, 4, PathPolicyConstraintsParserRULE_expression, _p) + + defer func() { + p.UnrollRecursionContexts(_parentctx) + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + var _alt int + + p.EnterOuterAlt(localctx, 1) + p.SetState(43) + p.GetErrorHandler().Sync(p) + + switch p.GetTokenStream().LA(1) { + case PathPolicyConstraintsParserLPAR: + localctx = NewParensContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + + { + p.SetState(37) + p.Match(PathPolicyConstraintsParserLPAR) + } + { + p.SetState(38) + p.expression(0) + } + { + p.SetState(39) + p.Match(PathPolicyConstraintsParserRPAR) + } + + case PathPolicyConstraintsParserZERO, PathPolicyConstraintsParserNUM: + localctx = NewExpressionIdentifierContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(41) + p.Identifier() + } + + case PathPolicyConstraintsParserLBRACE: + localctx = NewExpressionQueryContext(p, localctx) + p.SetParserRuleContext(localctx) + _prevctx = localctx + { + p.SetState(42) + p.Query() + } + + default: + panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + } + p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) + p.SetState(50) + p.GetErrorHandler().Sync(p) + _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 2, p.GetParserRuleContext()) + + for _alt != 2 && _alt != antlr.ATNInvalidAltNumber { + if _alt == 1 { + if p.GetParseListeners() != nil { + p.TriggerExitRuleEvent() + } + _prevctx = localctx + localctx = NewExpressionConcatContext(p, NewExpressionContext(p, _parentctx, _parentState)) + localctx.(*ExpressionConcatContext).left = _prevctx + + p.PushNewRecursionContext(localctx, _startState, PathPolicyConstraintsParserRULE_expression) + p.SetState(45) + + if !(p.Precpred(p.GetParserRuleContext(), 3)) { + panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 3)", "")) + } + { + p.SetState(46) + p.Match(PathPolicyConstraintsParserPLUS) + } + { + p.SetState(47) + + var _x = p.expression(4) + + localctx.(*ExpressionConcatContext).right = _x + } + + } + p.SetState(52) + p.GetErrorHandler().Sync(p) + _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 2, p.GetParserRuleContext()) + } + + return localctx +} + +// IIdentifierContext is an interface to support dynamic dispatch. +type IIdentifierContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsIdentifierContext differentiates from other interfaces. + IsIdentifierContext() +} + +type IdentifierContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyIdentifierContext() *IdentifierContext { + var p = new(IdentifierContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_identifier + return p +} + +func (*IdentifierContext) IsIdentifierContext() {} + +func NewIdentifierContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *IdentifierContext { + var p = new(IdentifierContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_identifier + + return p +} + +func (s *IdentifierContext) GetParser() antlr.Parser { return s.parser } + +func (s *IdentifierContext) Isd() IIsdContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IIsdContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IIsdContext) +} + +func (s *IdentifierContext) As() IAsContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IAsContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IAsContext) +} + +func (s *IdentifierContext) HASH() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserHASH, 0) +} + +func (s *IdentifierContext) AllIface() []IIfaceContext { + var ts = s.GetTypedRuleContexts(reflect.TypeOf((*IIfaceContext)(nil)).Elem()) + var tst = make([]IIfaceContext, len(ts)) + + for i, t := range ts { + if t != nil { + tst[i] = t.(IIfaceContext) + } + } + + return tst +} + +func (s *IdentifierContext) Iface(i int) IIfaceContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IIfaceContext)(nil)).Elem(), i) + + if t == nil { + return nil + } + + return t.(IIfaceContext) +} + +func (s *IdentifierContext) MONKEYTAIL() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserMONKEYTAIL, 0) +} + +func (s *IdentifierContext) Onepolicy() IOnepolicyContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IOnepolicyContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IOnepolicyContext) +} + +func (s *IdentifierContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IdentifierContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +func (s *IdentifierContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterIdentifier(s) + } +} + +func (s *IdentifierContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitIdentifier(s) + } +} + +func (p *PathPolicyConstraintsParser) Identifier() (localctx IIdentifierContext) { + this := p + _ = this + + localctx = NewIdentifierContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 6, PathPolicyConstraintsParserRULE_identifier) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.EnterOuterAlt(localctx, 1) + { + p.SetState(53) + p.Isd() + } + { + p.SetState(54) + p.As() + } + { + p.SetState(55) + p.Match(PathPolicyConstraintsParserHASH) + } + { + p.SetState(56) + p.Iface() + } + { + p.SetState(57) + p.Match(PathPolicyConstraintsParserT__0) + } + { + p.SetState(58) + p.Iface() + } + { + p.SetState(59) + p.Match(PathPolicyConstraintsParserMONKEYTAIL) + } + { + p.SetState(60) + p.Onepolicy() + } + + return localctx +} + +// IIsdContext is an interface to support dynamic dispatch. +type IIsdContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsIsdContext differentiates from other interfaces. + IsIsdContext() +} + +type IsdContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyIsdContext() *IsdContext { + var p = new(IsdContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_isd + return p +} + +func (*IsdContext) IsIsdContext() {} + +func NewIsdContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *IsdContext { + var p = new(IsdContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_isd + + return p +} + +func (s *IsdContext) GetParser() antlr.Parser { return s.parser } + +func (s *IsdContext) CopyFrom(ctx *IsdContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *IsdContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IsdContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type WildcardISDContext struct { + *IsdContext +} + +func NewWildcardISDContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *WildcardISDContext { + var p = new(WildcardISDContext) + + p.IsdContext = NewEmptyIsdContext() + p.parser = parser + p.CopyFrom(ctx.(*IsdContext)) + + return p +} + +func (s *WildcardISDContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *WildcardISDContext) ZERO() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserZERO, 0) +} + +func (s *WildcardISDContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterWildcardISD(s) + } +} + +func (s *WildcardISDContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitWildcardISD(s) + } +} + +type ISDContext struct { + *IsdContext +} + +func NewISDContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ISDContext { + var p = new(ISDContext) + + p.IsdContext = NewEmptyIsdContext() + p.parser = parser + p.CopyFrom(ctx.(*IsdContext)) + + return p +} + +func (s *ISDContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ISDContext) NUM() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserNUM, 0) +} + +func (s *ISDContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterISD(s) + } +} + +func (s *ISDContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitISD(s) + } +} + +func (p *PathPolicyConstraintsParser) Isd() (localctx IIsdContext) { + this := p + _ = this + + localctx = NewIsdContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 8, PathPolicyConstraintsParserRULE_isd) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.SetState(64) + p.GetErrorHandler().Sync(p) + + switch p.GetTokenStream().LA(1) { + case PathPolicyConstraintsParserZERO: + localctx = NewWildcardISDContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(62) + p.Match(PathPolicyConstraintsParserZERO) + } + + case PathPolicyConstraintsParserNUM: + localctx = NewISDContext(p, localctx) + p.EnterOuterAlt(localctx, 2) + { + p.SetState(63) + p.Match(PathPolicyConstraintsParserNUM) + } + + default: + panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + } + + return localctx +} + +// IAsContext is an interface to support dynamic dispatch. +type IAsContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsAsContext differentiates from other interfaces. + IsAsContext() +} + +type AsContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyAsContext() *AsContext { + var p = new(AsContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_as + return p +} + +func (*AsContext) IsAsContext() {} + +func NewAsContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AsContext { + var p = new(AsContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_as + + return p +} + +func (s *AsContext) GetParser() antlr.Parser { return s.parser } + +func (s *AsContext) CopyFrom(ctx *AsContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *AsContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *AsContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type ASContext struct { + *AsContext +} + +func NewASContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *ASContext { + var p = new(ASContext) + + p.AsContext = NewEmptyAsContext() + p.parser = parser + p.CopyFrom(ctx.(*AsContext)) + + return p +} + +func (s *ASContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *ASContext) AS() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserAS, 0) +} + +func (s *ASContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterAS(s) + } +} + +func (s *ASContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitAS(s) + } +} + +type LegacyASContext struct { + *AsContext +} + +func NewLegacyASContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *LegacyASContext { + var p = new(LegacyASContext) + + p.AsContext = NewEmptyAsContext() + p.parser = parser + p.CopyFrom(ctx.(*AsContext)) + + return p +} + +func (s *LegacyASContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *LegacyASContext) LEGACYAS() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserLEGACYAS, 0) +} + +func (s *LegacyASContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterLegacyAS(s) + } +} + +func (s *LegacyASContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitLegacyAS(s) + } +} + +type WildcardASContext struct { + *AsContext +} + +func NewWildcardASContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *WildcardASContext { + var p = new(WildcardASContext) + + p.AsContext = NewEmptyAsContext() + p.parser = parser + p.CopyFrom(ctx.(*AsContext)) + + return p +} + +func (s *WildcardASContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *WildcardASContext) WILDCARDAS() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserWILDCARDAS, 0) +} + +func (s *WildcardASContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterWildcardAS(s) + } +} + +func (s *WildcardASContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitWildcardAS(s) + } +} + +func (p *PathPolicyConstraintsParser) As() (localctx IAsContext) { + this := p + _ = this + + localctx = NewAsContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 10, PathPolicyConstraintsParserRULE_as) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.SetState(69) + p.GetErrorHandler().Sync(p) + + switch p.GetTokenStream().LA(1) { + case PathPolicyConstraintsParserWILDCARDAS: + localctx = NewWildcardASContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(66) + p.Match(PathPolicyConstraintsParserWILDCARDAS) + } + + case PathPolicyConstraintsParserLEGACYAS: + localctx = NewLegacyASContext(p, localctx) + p.EnterOuterAlt(localctx, 2) + { + p.SetState(67) + p.Match(PathPolicyConstraintsParserLEGACYAS) + } + + case PathPolicyConstraintsParserAS: + localctx = NewASContext(p, localctx) + p.EnterOuterAlt(localctx, 3) + { + p.SetState(68) + p.Match(PathPolicyConstraintsParserAS) + } + + default: + panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + } + + return localctx +} + +// IIfaceContext is an interface to support dynamic dispatch. +type IIfaceContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsIfaceContext differentiates from other interfaces. + IsIfaceContext() +} + +type IfaceContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyIfaceContext() *IfaceContext { + var p = new(IfaceContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_iface + return p +} + +func (*IfaceContext) IsIfaceContext() {} + +func NewIfaceContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *IfaceContext { + var p = new(IfaceContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_iface + + return p +} + +func (s *IfaceContext) GetParser() antlr.Parser { return s.parser } + +func (s *IfaceContext) CopyFrom(ctx *IfaceContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *IfaceContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IfaceContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type IFaceContext struct { + *IfaceContext +} + +func NewIFaceContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *IFaceContext { + var p = new(IFaceContext) + + p.IfaceContext = NewEmptyIfaceContext() + p.parser = parser + p.CopyFrom(ctx.(*IfaceContext)) + + return p +} + +func (s *IFaceContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *IFaceContext) NUM() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserNUM, 0) +} + +func (s *IFaceContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterIFace(s) + } +} + +func (s *IFaceContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitIFace(s) + } +} + +type WildcardIFaceContext struct { + *IfaceContext +} + +func NewWildcardIFaceContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *WildcardIFaceContext { + var p = new(WildcardIFaceContext) + + p.IfaceContext = NewEmptyIfaceContext() + p.parser = parser + p.CopyFrom(ctx.(*IfaceContext)) + + return p +} + +func (s *WildcardIFaceContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *WildcardIFaceContext) ZERO() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserZERO, 0) +} + +func (s *WildcardIFaceContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterWildcardIFace(s) + } +} + +func (s *WildcardIFaceContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitWildcardIFace(s) + } +} + +func (p *PathPolicyConstraintsParser) Iface() (localctx IIfaceContext) { + this := p + _ = this + + localctx = NewIfaceContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 12, PathPolicyConstraintsParserRULE_iface) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.SetState(73) + p.GetErrorHandler().Sync(p) + + switch p.GetTokenStream().LA(1) { + case PathPolicyConstraintsParserZERO: + localctx = NewWildcardIFaceContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(71) + p.Match(PathPolicyConstraintsParserZERO) + } + + case PathPolicyConstraintsParserNUM: + localctx = NewIFaceContext(p, localctx) + p.EnterOuterAlt(localctx, 2) + { + p.SetState(72) + p.Match(PathPolicyConstraintsParserNUM) + } + + default: + panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + } + + return localctx +} + +// IOnepolicyContext is an interface to support dynamic dispatch. +type IOnepolicyContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsOnepolicyContext differentiates from other interfaces. + IsOnepolicyContext() +} + +type OnepolicyContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyOnepolicyContext() *OnepolicyContext { + var p = new(OnepolicyContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_onepolicy + return p +} + +func (*OnepolicyContext) IsOnepolicyContext() {} + +func NewOnepolicyContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *OnepolicyContext { + var p = new(OnepolicyContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_onepolicy + + return p +} + +func (s *OnepolicyContext) GetParser() antlr.Parser { return s.parser } + +func (s *OnepolicyContext) CopyFrom(ctx *OnepolicyContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *OnepolicyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *OnepolicyContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type RejectContext struct { + *OnepolicyContext +} + +func NewRejectContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *RejectContext { + var p = new(RejectContext) + + p.OnepolicyContext = NewEmptyOnepolicyContext() + p.parser = parser + p.CopyFrom(ctx.(*OnepolicyContext)) + + return p +} + +func (s *RejectContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *RejectContext) REJECT() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserREJECT, 0) +} + +func (s *RejectContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterReject(s) + } +} + +func (s *RejectContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitReject(s) + } +} + +type LocalPolicyContext struct { + *OnepolicyContext +} + +func NewLocalPolicyContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *LocalPolicyContext { + var p = new(LocalPolicyContext) + + p.OnepolicyContext = NewEmptyOnepolicyContext() + p.parser = parser + p.CopyFrom(ctx.(*OnepolicyContext)) + + return p +} + +func (s *LocalPolicyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *LocalPolicyContext) LOCALPOLICY() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserLOCALPOLICY, 0) +} + +func (s *LocalPolicyContext) Policyindex() IPolicyindexContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IPolicyindexContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IPolicyindexContext) +} + +func (s *LocalPolicyContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterLocalPolicy(s) + } +} + +func (s *LocalPolicyContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitLocalPolicy(s) + } +} + +type GlobalPolicyContext struct { + *OnepolicyContext +} + +func NewGlobalPolicyContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *GlobalPolicyContext { + var p = new(GlobalPolicyContext) + + p.OnepolicyContext = NewEmptyOnepolicyContext() + p.parser = parser + p.CopyFrom(ctx.(*OnepolicyContext)) + + return p +} + +func (s *GlobalPolicyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *GlobalPolicyContext) GLOBALPOLICY() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserGLOBALPOLICY, 0) +} + +func (s *GlobalPolicyContext) Policyindex() IPolicyindexContext { + var t = s.GetTypedRuleContext(reflect.TypeOf((*IPolicyindexContext)(nil)).Elem(), 0) + + if t == nil { + return nil + } + + return t.(IPolicyindexContext) +} + +func (s *GlobalPolicyContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterGlobalPolicy(s) + } +} + +func (s *GlobalPolicyContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitGlobalPolicy(s) + } +} + +type WildcardPolicyContext struct { + *OnepolicyContext +} + +func NewWildcardPolicyContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *WildcardPolicyContext { + var p = new(WildcardPolicyContext) + + p.OnepolicyContext = NewEmptyOnepolicyContext() + p.parser = parser + p.CopyFrom(ctx.(*OnepolicyContext)) + + return p +} + +func (s *WildcardPolicyContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *WildcardPolicyContext) ZERO() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserZERO, 0) +} + +func (s *WildcardPolicyContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterWildcardPolicy(s) + } +} + +func (s *WildcardPolicyContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitWildcardPolicy(s) + } +} + +func (p *PathPolicyConstraintsParser) Onepolicy() (localctx IOnepolicyContext) { + this := p + _ = this + + localctx = NewOnepolicyContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 14, PathPolicyConstraintsParserRULE_onepolicy) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + p.SetState(81) + p.GetErrorHandler().Sync(p) + + switch p.GetTokenStream().LA(1) { + case PathPolicyConstraintsParserGLOBALPOLICY: + localctx = NewGlobalPolicyContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(75) + p.Match(PathPolicyConstraintsParserGLOBALPOLICY) + } + { + p.SetState(76) + p.Policyindex() + } + + case PathPolicyConstraintsParserLOCALPOLICY: + localctx = NewLocalPolicyContext(p, localctx) + p.EnterOuterAlt(localctx, 2) + { + p.SetState(77) + p.Match(PathPolicyConstraintsParserLOCALPOLICY) + } + { + p.SetState(78) + p.Policyindex() + } + + case PathPolicyConstraintsParserZERO: + localctx = NewWildcardPolicyContext(p, localctx) + p.EnterOuterAlt(localctx, 3) + { + p.SetState(79) + p.Match(PathPolicyConstraintsParserZERO) + } + + case PathPolicyConstraintsParserREJECT: + localctx = NewRejectContext(p, localctx) + p.EnterOuterAlt(localctx, 4) + { + p.SetState(80) + p.Match(PathPolicyConstraintsParserREJECT) + } + + default: + panic(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) + } + + return localctx +} + +// IPolicyindexContext is an interface to support dynamic dispatch. +type IPolicyindexContext interface { + antlr.ParserRuleContext + + // GetParser returns the parser. + GetParser() antlr.Parser + + // IsPolicyindexContext differentiates from other interfaces. + IsPolicyindexContext() +} + +type PolicyindexContext struct { + *antlr.BaseParserRuleContext + parser antlr.Parser +} + +func NewEmptyPolicyindexContext() *PolicyindexContext { + var p = new(PolicyindexContext) + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(nil, -1) + p.RuleIndex = PathPolicyConstraintsParserRULE_policyindex + return p +} + +func (*PolicyindexContext) IsPolicyindexContext() {} + +func NewPolicyindexContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PolicyindexContext { + var p = new(PolicyindexContext) + + p.BaseParserRuleContext = antlr.NewBaseParserRuleContext(parent, invokingState) + + p.parser = parser + p.RuleIndex = PathPolicyConstraintsParserRULE_policyindex + + return p +} + +func (s *PolicyindexContext) GetParser() antlr.Parser { return s.parser } + +func (s *PolicyindexContext) CopyFrom(ctx *PolicyindexContext) { + s.BaseParserRuleContext.CopyFrom(ctx.BaseParserRuleContext) +} + +func (s *PolicyindexContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PolicyindexContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { + return antlr.TreesStringTree(s, ruleNames, recog) +} + +type PolicyIndexContext struct { + *PolicyindexContext +} + +func NewPolicyIndexContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *PolicyIndexContext { + var p = new(PolicyIndexContext) + + p.PolicyindexContext = NewEmptyPolicyindexContext() + p.parser = parser + p.CopyFrom(ctx.(*PolicyindexContext)) + + return p +} + +func (s *PolicyIndexContext) GetRuleContext() antlr.RuleContext { + return s +} + +func (s *PolicyIndexContext) NUM() antlr.TerminalNode { + return s.GetToken(PathPolicyConstraintsParserNUM, 0) +} + +func (s *PolicyIndexContext) EnterRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.EnterPolicyIndex(s) + } +} + +func (s *PolicyIndexContext) ExitRule(listener antlr.ParseTreeListener) { + if listenerT, ok := listener.(PathPolicyConstraintsListener); ok { + listenerT.ExitPolicyIndex(s) + } +} + +func (p *PathPolicyConstraintsParser) Policyindex() (localctx IPolicyindexContext) { + this := p + _ = this + + localctx = NewPolicyindexContext(p, p.GetParserRuleContext(), p.GetState()) + p.EnterRule(localctx, 16, PathPolicyConstraintsParserRULE_policyindex) + + defer func() { + p.ExitRule() + }() + + defer func() { + if err := recover(); err != nil { + if v, ok := err.(antlr.RecognitionException); ok { + localctx.SetException(v) + p.GetErrorHandler().ReportError(p, v) + p.GetErrorHandler().Recover(p, v) + } else { + panic(err) + } + } + }() + + localctx = NewPolicyIndexContext(p, localctx) + p.EnterOuterAlt(localctx, 1) + { + p.SetState(83) + p.Match(PathPolicyConstraintsParserNUM) + } + + return localctx +} + +func (p *PathPolicyConstraintsParser) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex int) bool { + switch ruleIndex { + case 2: + var t *ExpressionContext = nil + if localctx != nil { + t = localctx.(*ExpressionContext) + } + return p.Expression_Sempred(t, predIndex) + + default: + panic("No predicate with index: " + fmt.Sprint(ruleIndex)) + } +} + +func (p *PathPolicyConstraintsParser) Expression_Sempred(localctx antlr.RuleContext, predIndex int) bool { + this := p + _ = this + + switch predIndex { + case 0: + return p.Precpred(p.GetParserRuleContext(), 3) + + default: + panic("No predicate with index: " + fmt.Sprint(predIndex)) + } +} diff --git a/pkg/addr/fmt.go b/pkg/addr/fmt.go index ed9b2d9de1..12b094d23f 100644 --- a/pkg/addr/fmt.go +++ b/pkg/addr/fmt.go @@ -65,7 +65,7 @@ func ParseFormattedAS(as string, opts ...FormatOption) (AS, error) { } as = trimmed } - return parseAS(as, o.separator) + return ParseASSep(as, o.separator) } // FormatIA formats the ISD-AS. diff --git a/pkg/addr/isdas.go b/pkg/addr/isdas.go index 64e9c50a8b..3391c259df 100644 --- a/pkg/addr/isdas.go +++ b/pkg/addr/isdas.go @@ -67,10 +67,10 @@ type AS uint64 // ParseAS parses an AS from a decimal (in the case of the 32bit BGP AS number // space) or ipv6-style hex (in the case of SCION-only AS numbers) string. func ParseAS(as string) (AS, error) { - return parseAS(as, ":") + return ParseASSep(as, ":") } -func parseAS(as string, sep string) (AS, error) { +func ParseASSep(as string, sep string) (AS, error) { parts := strings.Split(as, sep) if len(parts) == 1 { // Must be a BGP AS, parse as 32-bit decimal number diff --git a/pkg/private/xtest/graph/BUILD.bazel b/pkg/private/xtest/graph/BUILD.bazel index d5907cf9e5..6ddcb1a1ab 100644 --- a/pkg/private/xtest/graph/BUILD.bazel +++ b/pkg/private/xtest/graph/BUILD.bazel @@ -10,6 +10,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/proto/control_plane:go_default_library", diff --git a/pkg/private/xtest/graph/graph.go b/pkg/private/xtest/graph/graph.go index bc34543665..690a58ecb6 100644 --- a/pkg/private/xtest/graph/graph.go +++ b/pkg/private/xtest/graph/graph.go @@ -37,6 +37,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" @@ -416,6 +417,23 @@ func (g *Graph) InternalHops(a, b uint16) uint32 { return uint32(a * b % 10) } +// FabridPolicy returns an arbitrary set of policies between between two interfaces of an AS. +func (g *Graph) FabridPolicy(a, b uint16) []*fabrid.Policy { + if g.parents[a] != g.parents[b] && a != 0 && b != 0 { + panic("interfaces must be in the same AS") + } + amtOfPols := int(a*b%10 + 3) + policies := make([]*fabrid.Policy, amtOfPols) + for i := 0; i < amtOfPols; i++ { + policies[i] = &fabrid.Policy{ + IsLocal: false, + Identifier: (uint32(a)*uint32(b)*uint32(i)*39 + uint32(i) + 1) % 20000, + Index: fabrid.PolicyID(a * b), + } + } + return policies +} + // SignerOption allows customizing the generated Signer. type SignerOption func(o *Signer) diff --git a/pkg/snet/path.go b/pkg/snet/path.go index d055f0a4b6..f0a54797d4 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -187,6 +187,42 @@ type PathMetadata struct { FabridInfo []FabridInfo } +func (pm *PathMetadata) Hops() []HopInterface { + ifaces := pm.Interfaces + fabrid := pm.FabridInfo + switch { + case len(ifaces)%2 != 0 || (len(fabrid) != len(ifaces)/2+1): + return []HopInterface{} + case len(ifaces) == 0 || len(fabrid) == 0: + return []HopInterface{} + default: + hops := make([]HopInterface, 0, len(ifaces)/2+1) + hops = append(hops, HopInterface{ + IA: ifaces[0].IA, + IgIf: 0, + EgIf: ifaces[0].ID, + FabridEnabled: fabrid[0].Enabled, + Policies: fabrid[0].Policies}) + for i := 1; i < len(ifaces)-1; i += 2 { + hops = append(hops, HopInterface{ + IA: ifaces[i].IA, + IgIf: ifaces[i].ID, + EgIf: ifaces[i+1].ID, + FabridEnabled: fabrid[(i+1)/2].Enabled, + Policies: fabrid[(i+1)/2].Policies, + }) + } + hops = append(hops, HopInterface{ + IA: ifaces[len(ifaces)-1].IA, + IgIf: ifaces[len(ifaces)-1].ID, + EgIf: 0, + FabridEnabled: fabrid[len(ifaces)/2].Enabled, + Policies: fabrid[len(ifaces)/2].Policies, + }) + return hops + } +} + func (pm *PathMetadata) Copy() *PathMetadata { if pm == nil { return nil diff --git a/pkg/snet/path/BUILD.bazel b/pkg/snet/path/BUILD.bazel index 351e08c2e3..4f9c63b3a6 100644 --- a/pkg/snet/path/BUILD.bazel +++ b/pkg/snet/path/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "empty.go", "epic.go", + "fabrid.go", "onehop.go", "path.go", "scion.go", @@ -13,10 +14,14 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", "//pkg/experimental/epic:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/experimental/fabrid/crypto:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/epic:go_default_library", diff --git a/pkg/snet/path/fabrid.go b/pkg/snet/path/fabrid.go new file mode 100644 index 0000000000..b6dd13aa40 --- /dev/null +++ b/pkg/snet/path/fabrid.go @@ -0,0 +1,221 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package path + +import ( + "context" + "time" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" + "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/snet" +) + +type FabridConfig struct { + LocalIA addr.IA + LocalAddr string + DestinationIA addr.IA + DestinationAddr string +} + +type FABRID struct { + Raw []byte + keys map[addr.IA]*drkey.FabridKey + pathKey *drkey.FabridKey + getFabridKeys func(context.Context, drkey.FabridKeysMeta) (drkey.FabridKeysResponse, error) + conf *FabridConfig + counter uint32 + baseTimestamp uint32 + tmpBuffer []byte + identifierBuffer []byte + fabridBuffer []byte + policyIDs []*fabrid.PolicyID + numHops int + hops []snet.HopInterface +} + +func NewFABRIDDataplanePath(p SCION, hops []snet.HopInterface, policyIDs []*fabrid.PolicyID, + conf *FabridConfig) (*FABRID, error) { + numHops := len(hops) + var decoded scion.Decoded + if err := decoded.DecodeFromBytes(p.Raw); err != nil { + return nil, serrors.WrapStr("decoding path", err) + } + keys := make(map[addr.IA]*drkey.FabridKey) + if len(policyIDs) == 0 { // If no policies are provided, use empty policy for all hops + policyIDs = make([]*fabrid.PolicyID, numHops) + } else if len(policyIDs) != numHops { + return nil, serrors.New("Amount of policy ids does not match the amount of hops in " + + "the path.") + } + var pathKey *drkey.FabridKey + if hops[numHops-1].FabridEnabled { + pathKey = &drkey.FabridKey{} + } + f := &FABRID{ + hops: hops, + numHops: numHops, + conf: conf, + keys: keys, + pathKey: pathKey, + tmpBuffer: make([]byte, 64), + identifierBuffer: make([]byte, 8), + fabridBuffer: make([]byte, 8+4*numHops), + Raw: append([]byte(nil), p.Raw...), + policyIDs: policyIDs, + } + + // Get ingress/egress IFs and IAs from path interfaces + for i, hop := range hops { + if policyIDs[i] != nil { + f.keys[hop.IA] = &drkey.FabridKey{} + } + } + f.baseTimestamp = decoded.InfoFields[0].Timestamp + return f, nil +} + +func (f *FABRID) RegisterDRKeyFetcher( + getFabridKeys func(context.Context, drkey.FabridKeysMeta) (drkey.FabridKeysResponse, error)) { + + f.getFabridKeys = getFabridKeys +} + +func (f *FABRID) SetPath(s *slayers.SCION) error { + var sp scion.Raw + if err := sp.DecodeFromBytes(f.Raw); err != nil { + return err + } + s.Path, s.PathType = &sp, sp.Type() + return nil +} +func (f *FABRID) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { + if s == nil { + return serrors.New("scion layer is nil") + } + if p == nil { + return serrors.New("packet info is nil") + } + if f.getFabridKeys == nil { + return serrors.New("drkey not correctly configured") + } + if p.HbhExtension == nil { + p.HbhExtension = &slayers.HopByHopExtn{} + } + now := time.Now().Truncate(time.Millisecond) + err := f.renewExpiredKeys(now) + if err != nil { + return serrors.WrapStr("While obtaining fabrid keys", err) + } + identifierOption := &extension.IdentifierOption{ + Timestamp: now, + BaseTimestamp: f.baseTimestamp, + PacketID: f.counter, + } + fabridOption := &extension.FabridOption{ + HopfieldMetadata: make([]*extension.FabridHopfieldMetadata, f.numHops), + } + for i := 0; i < f.numHops; i++ { + meta := &extension.FabridHopfieldMetadata{} + if f.policyIDs[i] != nil && f.keys[f.hops[i].IA] != nil { + meta.FabridEnabled = true + key := f.keys[f.hops[i].IA].Key + encPolicyID, err := crypto.EncryptPolicyID(*f.policyIDs[i], identifierOption, key[:]) + if err != nil { + return serrors.WrapStr("encrypting policy ID", err) + } + meta.EncryptedPolicyID = encPolicyID + } + fabridOption.HopfieldMetadata[i] = meta + } + err = crypto.InitValidators(fabridOption, identifierOption, s, f.tmpBuffer, f.pathKey, + f.keys, nil, f.hops) + if err != nil { + return serrors.WrapStr("initializing validators failed", err) + } + err = identifierOption.Serialize(f.identifierBuffer) + if err != nil { + return serrors.WrapStr("serializing identifier", err) + } + err = fabridOption.SerializeTo(f.fabridBuffer) + if err != nil { + return serrors.WrapStr("serializing fabrid option", err) + } + fabridLength := 4 + 4*f.numHops + p.HbhExtension.Options = append(p.HbhExtension.Options, + &slayers.HopByHopOption{ + OptType: slayers.OptTypeIdentifier, + OptData: f.identifierBuffer, + OptDataLen: 8, + ActualLength: 8, + }, + &slayers.HopByHopOption{ + OptType: slayers.OptTypeFabrid, + OptData: f.fabridBuffer[:fabridLength], + OptDataLen: uint8(fabridLength), + ActualLength: fabridLength, + }) + f.counter++ + return nil +} + +// This function iterates over all on-path ASes and checks whether the keys are still valid. +// If it finds expired keys it marks them as expired and renews all expired keys at once. +func (f *FABRID) renewExpiredKeys(t time.Time) error { + var expiredAses []addr.IA = nil + for ia, key := range f.keys { + if key.Epoch.NotAfter.Before(t) { + // key is expired, mark as expired + if expiredAses == nil { + expiredAses = make([]addr.IA, 0, len(f.keys)) + } + expiredAses = append(expiredAses, ia) + } + } + isPathKeyExpired := false + if f.pathKey != nil { + isPathKeyExpired = f.pathKey.Epoch.NotAfter.Before(t) + } + if expiredAses != nil || isPathKeyExpired { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + meta := drkey.FabridKeysMeta{ + SrcAS: f.conf.LocalIA, + SrcHost: f.conf.LocalAddr, + PathASes: expiredAses, + DstAS: f.conf.DestinationIA, + } + if isPathKeyExpired { + meta.DstHost = &f.conf.DestinationAddr + } + keys, err := f.getFabridKeys(ctx, meta) + if err != nil { + return err + } + if isPathKeyExpired { + f.pathKey = &keys.PathKey + } + for i := range keys.ASHostKeys { + f.keys[keys.ASHostKeys[i].AS] = &keys.ASHostKeys[i] + } + } + return nil +} diff --git a/pkg/snet/path/path.go b/pkg/snet/path/path.go index 08748964d9..1013366a4e 100644 --- a/pkg/snet/path/path.go +++ b/pkg/snet/path/path.go @@ -62,7 +62,7 @@ func (p Path) Destination() addr.IA { } func (p Path) Metadata() *snet.PathMetadata { - return p.Meta.Copy() + return &p.Meta } func (p Path) String() string { diff --git a/private/app/path/BUILD.bazel b/private/app/path/BUILD.bazel index d6df278e2a..856852af91 100644 --- a/private/app/path/BUILD.bazel +++ b/private/app/path/BUILD.bazel @@ -12,6 +12,7 @@ go_library( "//pkg/snet:go_default_library", "//pkg/snet/path:go_default_library", "//private/app/path/pathprobe:go_default_library", + "//private/path/fabridquery:go_default_library", "//private/path/pathpol:go_default_library", "@com_github_fatih_color//:go_default_library", ], diff --git a/private/app/path/path.go b/private/app/path/path.go index 96666805e3..dd897c46dd 100644 --- a/private/app/path/path.go +++ b/private/app/path/path.go @@ -34,6 +34,7 @@ import ( "github.com/scionproto/scion/pkg/snet" snetpath "github.com/scionproto/scion/pkg/snet/path" "github.com/scionproto/scion/private/app/path/pathprobe" + "github.com/scionproto/scion/private/path/fabridquery" "github.com/scionproto/scion/private/path/pathpol" ) @@ -79,7 +80,7 @@ func Choose( ) (snet.Path, error) { o := applyOption(opts) - paths, err := fetchPaths(ctx, conn, remote, o.refresh, o.seq) + paths, err := fetchPaths(ctx, conn, remote, o.refresh, o.seq, o.fetchDetachedFabridMaps) if err != nil { return nil, serrors.WrapStr("fetching paths", err) } @@ -101,6 +102,38 @@ func Choose( } paths = epicPaths } + if o.fabrid != nil { + query, err := fabridquery.ParseFabridQuery(o.fabrid.Query) + if err != nil { + return nil, serrors.WrapStr("parsing fabrid query", err) + } + + for _, p := range paths { + scionPath, isSCIONPath := p.Dataplane().(snetpath.SCION) + if !isSCIONPath { + continue + } + hopIntfs := p.Metadata().Hops() + ml := fabridquery.MatchList{ + SelectedPolicies: make([]*fabridquery.Policy, len(hopIntfs)), + } + _, pols := query.Evaluate(hopIntfs, &ml) + + if !pols.Accepted() { + continue + } + fabridPath, err := snetpath.NewFABRIDDataplanePath(scionPath, p.Metadata().Hops(), + pols.Policies(), &o.fabrid.FabridConfig) + if err != nil { + return nil, serrors.WrapStr("creating fabrid path from scion path", err) + } + return snetpath.Path{Src: p.Source(), Dst: p.Destination(), DataplanePath: fabridPath, + NextHop: p.UnderlayNextHop(), Meta: *p.Metadata()}, nil + } + return nil, serrors.New( + fmt.Sprintf("no fabrid paths available satisfying query '%s'", + o.fabrid.Query)) + } if o.probeCfg != nil { paths, err = filterUnhealthy(ctx, paths, remote, conn, o.probeCfg, o.epic) if err != nil { @@ -110,11 +143,16 @@ func Choose( return nil, serrors.New("no healthy paths available") } } + var selectedPath snet.Path if o.interactive { - return printAndChoose(paths, remote, o.colorScheme) + selectedPath, err = printAndChoose(paths, remote, o.colorScheme) + if err != nil { + return selectedPath, err + } + } else { + selectedPath = paths[rand.Intn(len(paths))] } - - return paths[rand.Intn(len(paths))], nil + return selectedPath, nil } func filterUnhealthy( @@ -170,9 +208,11 @@ func fetchPaths( remote addr.IA, refresh bool, seq string, + fetchFabridDetachedMaps bool, ) ([]snet.Path, error) { - allPaths, err := conn.Paths(ctx, remote, 0, daemon.PathReqFlags{Refresh: refresh}) + allPaths, err := conn.Paths(ctx, remote, 0, daemon.PathReqFlags{Refresh: refresh, + FetchFabridDetachedMaps: fetchFabridDetachedMaps}) if err != nil { return nil, serrors.WrapStr("retrieving paths", err) } @@ -224,36 +264,42 @@ func printAndChoose(paths []snet.Path, remote addr.IA, cs ColorScheme) (snet.Pat // ColorScheme allows customizing the path coloring. type ColorScheme struct { - Header *color.Color - Keys *color.Color - Values *color.Color - Link *color.Color - Intf *color.Color - Good *color.Color - Bad *color.Color + Header *color.Color + Keys *color.Color + Values *color.Color + Link *color.Color + GlobalPolicy *color.Color + LocalPolicy *color.Color + Intf *color.Color + Good *color.Color + Bad *color.Color } func DefaultColorScheme(disable bool) ColorScheme { if disable { noColor := color.New() return ColorScheme{ - Header: noColor, - Keys: noColor, - Values: noColor, - Link: noColor, - Intf: noColor, - Good: noColor, - Bad: noColor, + Header: noColor, + Keys: noColor, + Values: noColor, + GlobalPolicy: noColor, + LocalPolicy: noColor, + Link: noColor, + Intf: noColor, + Good: noColor, + Bad: noColor, } } return ColorScheme{ - Header: color.New(color.FgHiBlack), - Keys: color.New(color.FgHiCyan), - Values: color.New(), - Link: color.New(color.FgHiMagenta), - Intf: color.New(color.FgYellow), - Good: color.New(color.FgGreen), - Bad: color.New(color.FgRed), + Header: color.New(color.FgHiBlack), + Keys: color.New(color.FgHiCyan), + Values: color.New(), + Link: color.New(color.FgHiMagenta), + Intf: color.New(color.FgYellow), + Good: color.New(color.FgGreen), + Bad: color.New(color.FgRed), + GlobalPolicy: color.New(color.FgHiBlue), + LocalPolicy: color.New(color.FgHiGreen), } } @@ -271,34 +317,56 @@ func (cs ColorScheme) KeyValues(kv ...string) []string { } return entries } +func (cs ColorScheme) Policies(policies []snet.FabridInfo, idx int) string { + if len(policies) < idx { + return "" + } + if policies[idx].Enabled && len(policies[idx].Policies) == 0 { + return cs.GlobalPolicy.Sprintf("~ZERO~") + } + policyStr := make([]string, len(policies[idx].Policies)) + for i, v := range policies[idx].Policies { + if v.IsLocal { + policyStr[i] = cs.LocalPolicy.Sprintf(v.String()) + } else { + policyStr[i] = cs.GlobalPolicy.Sprintf(v.String()) + } + } + return fmt.Sprintf("~%s~", strings.Join(policyStr, ",")) + +} func (cs ColorScheme) Path(path snet.Path) string { if path == nil { return "" } intfs := path.Metadata().Interfaces + policies := path.Metadata().FabridInfo if len(intfs) == 0 { return "" } var hops []string intf := intfs[0] - hops = append(hops, cs.Values.Sprintf("%s %s", + hops = append(hops, cs.Values.Sprintf("%s %s %s", cs.Values.Sprint(intf.IA), + cs.Policies(policies, 0), cs.Intf.Sprint(intf.ID), )) for i := 1; i < len(intfs)-1; i += 2 { inIntf := intfs[i] outIntf := intfs[i+1] - hops = append(hops, cs.Values.Sprintf("%s %s %s", + hops = append(hops, cs.Values.Sprintf("%s %s %s %s", cs.Intf.Sprint(inIntf.ID), cs.Values.Sprint(inIntf.IA), + cs.Policies(policies, (i+1)/2), cs.Intf.Sprint(outIntf.ID), )) } intf = intfs[len(intfs)-1] - hops = append(hops, cs.Values.Sprintf("%s %s", + hops = append(hops, cs.Values.Sprintf("%s %s %s", cs.Intf.Sprint(intf.ID), cs.Values.Sprint(intf.IA), + cs.Policies(policies, len(intfs)/2), )) return fmt.Sprintf("[%s]", strings.Join(hops, cs.Link.Sprintf(">"))) } @@ -311,13 +379,19 @@ type ProbeConfig struct { SCIONPacketConnMetrics snet.SCIONPacketConnMetrics } +type FABRIDQuery struct { + Query string + FabridConfig snetpath.FabridConfig +} type options struct { - interactive bool - refresh bool - seq string - colorScheme ColorScheme - probeCfg *ProbeConfig - epic bool + interactive bool + refresh bool + seq string + colorScheme ColorScheme + probeCfg *ProbeConfig + epic bool + fetchDetachedFabridMaps bool + fabrid *FABRIDQuery } type Option func(o *options) @@ -365,3 +439,14 @@ func WithEPIC(epic bool) Option { o.epic = epic } } + +func WithFABRID(f *FABRIDQuery) Option { + return func(o *options) { + o.fabrid = f + } +} +func WithFetchDetachedFabridMaps(value bool) Option { + return func(o *options) { + o.fetchDetachedFabridMaps = value + } +} diff --git a/private/path/combinator/fabrid_accumulator.go b/private/path/combinator/fabrid_accumulator.go index b9ac57884c..1040b3b65d 100644 --- a/private/path/combinator/fabrid_accumulator.go +++ b/private/path/combinator/fabrid_accumulator.go @@ -34,6 +34,27 @@ type FabridMapEntry struct { Digest []byte } +func collectFabridPolicies(ifaces []snet.PathInterface, + maps map[addr.IA]FabridMapEntry) []snet.FabridInfo { + + switch { + case len(ifaces)%2 != 0: + return []snet.FabridInfo{} + case len(ifaces) == 0: + return []snet.FabridInfo{} + default: + fabridInfo := make([]snet.FabridInfo, len(ifaces)/2+1) + fabridInfo[0] = *GetFabridInfoForIntfs(ifaces[0].IA, 0, uint16(ifaces[0].ID), maps, false) + for i := 1; i < len(ifaces)-1; i += 2 { + fabridInfo[(i+1)/2] = *GetFabridInfoForIntfs(ifaces[i].IA, uint16(ifaces[i].ID), + uint16(ifaces[i+1].ID), maps, false) + } + fabridInfo[len(ifaces)/2] = *GetFabridInfoForIntfs(ifaces[len(ifaces)-1].IA, + uint16(ifaces[len(ifaces)-1].ID), 0, maps, true) + return fabridInfo + } +} + func GetFabridInfoForIntfs(ia addr.IA, ig, eg uint16, maps map[addr.IA]FabridMapEntry, allowIpPolicies bool) *snet.FabridInfo { policies := make([]*fabrid.Policy, 0) diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index e3ed0cd808..253d8e5576 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -310,9 +310,11 @@ type pathSolution struct { // Path builds the forwarding path with metadata by extracting it from a path // between source and destination in the DMG. + func (solution *pathSolution) Path() Path { mtu := ^uint16(0) var segments segmentList + fabridMaps := make(map[addr.IA]FabridMapEntry) var epicPathAuths [][]byte for _, solEdge := range solution.edges { var hops []path.HopField @@ -379,6 +381,16 @@ func (solution *pathSolution) Path() Path { pathASEntries = append(pathASEntries, asEntry) epicSegAuths = append(epicSegAuths, epicAuth) + fabridMap, exists := fabridMaps[asEntry.Local] + if (!exists || fabridMap.Ts.Before(solEdge.segment.Info.Timestamp)) && asEntry. + Extensions.Digests != nil { + fabridMaps[asEntry.Local] = FabridMapEntry{ + Map: asEntry.UnsignedExtensions.FabridDetached, + Digest: asEntry.Extensions.Digests.Fabrid.Digest, + Ts: solEdge.segment.Info.Timestamp, + } + } + mtu = minUint16(mtu, uint16(asEntry.MTU)) if forwardingLinkMtu != 0 { // The first HE in a segment has MTU 0, so we ignore those @@ -413,7 +425,7 @@ func (solution *pathSolution) Path() Path { interfaces := segments.Interfaces() asEntries := segments.ASEntries() staticInfo := collectMetadata(interfaces, asEntries) - + fabridInfo := collectFabridPolicies(interfaces, fabridMaps) path := Path{ SCIONPath: segments.ScionPath(), Metadata: snet.PathMetadata{ @@ -427,6 +439,7 @@ func (solution *pathSolution) Path() Path { LinkType: staticInfo.LinkType, InternalHops: staticInfo.InternalHops, Notes: staticInfo.Notes, + FabridInfo: fabridInfo, }, Weight: solution.cost, } @@ -462,7 +475,6 @@ func getAuthPeer(a *seg.ASEntry, i int) []byte { copy(auth[6:16], a.UnsignedExtensions.EpicDetached.AuthPeerEntries[i]) return auth } - func isEpicAvailable(epicPathAuths [][]byte) ([]byte, []byte, bool) { l := len(epicPathAuths) if l < 2 { diff --git a/private/path/fabridquery/BUILD.bazel b/private/path/fabridquery/BUILD.bazel new file mode 100644 index 0000000000..176d36b7a7 --- /dev/null +++ b/private/path/fabridquery/BUILD.bazel @@ -0,0 +1,40 @@ +load("//tools/lint:go.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "matchlist.go", + "parser.go", + "query.go", + ], + importpath = "github.com/scionproto/scion/private/path/fabridquery", + visibility = ["//visibility:public"], + deps = [ + "//antlr/pathpolicyconstraints:go_default_library", + "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/private/common:go_default_library", + "//pkg/private/serrors:go_default_library", + "//pkg/snet:go_default_library", + "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "matchlist_test.go", + "query_test.go", + ], + deps = [ + ":go_default_library", + "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/private/common:go_default_library", + "//pkg/private/xtest:go_default_library", + "//pkg/private/xtest/graph:go_default_library", + "//pkg/snet:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], +) diff --git a/private/path/fabridquery/matchlist.go b/private/path/fabridquery/matchlist.go new file mode 100644 index 0000000000..5d73e4a0bd --- /dev/null +++ b/private/path/fabridquery/matchlist.go @@ -0,0 +1,74 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabridquery + +import ( + "fmt" + + "github.com/scionproto/scion/pkg/experimental/fabrid" +) + +type MatchList struct { + SelectedPolicies []*Policy +} + +// Copy creates a copy of the MatchList object, including the list of selected policies. +func (ml MatchList) Copy() *MatchList { + duplicate := make([]*Policy, len(ml.SelectedPolicies)) + copy(duplicate, ml.SelectedPolicies) + return &MatchList{duplicate} +} + +// StorePolicy only stores a policy if there has not been one already set for the hop. +func (ml MatchList) StorePolicy(hop int, policy *Policy) { + if ml.SelectedPolicies[hop] == nil { + ml.SelectedPolicies[hop] = policy + } +} + +// Accepted checks if all hops have at least a policy assigned, which is not the rejection policy +func (ml MatchList) Accepted() bool { + for _, policy := range ml.SelectedPolicies { + if policy != nil && policy.Type == REJECT_POLICY_TYPE { + return false + } + } + return true +} + +// Policies returns a slice of PolicyIDs representing the policies used in each hop of +// the MatchList object. A zero PolicyID is used for a nil selected policy, and a zero +// or reject PolicyID is used when a wildcard or reject policy is selected. +// For other policies, the PolicyID is obtained from the selected policy's Policy.Index field. +// It also prints the index and policy details of each hop to console. +// The returned slice has the same length as the MatchList.SelectedPolicies slice. +// func (ml MatchList) Policies() (pols []*fabrid.PolicyID) {} +func (ml MatchList) Policies() (pols []*fabrid.PolicyID) { + pols = make([]*fabrid.PolicyID, len(ml.SelectedPolicies)) + for i, selected := range ml.SelectedPolicies { + if selected == nil { + pols[i] = nil + fmt.Println(i, " is not using a policy") + } else if selected.Type == WILDCARD_POLICY_TYPE || selected.Type == REJECT_POLICY_TYPE { + zeroPol := fabrid.PolicyID(0) + pols[i] = &zeroPol + fmt.Println(i, " is using zero policy") + } else { + pols[i] = &selected.Policy.Index + fmt.Println(i, " is using policy ", selected.String(), " idx: ", selected.Policy.Index) + } + } + return pols +} diff --git a/private/path/fabridquery/matchlist_test.go b/private/path/fabridquery/matchlist_test.go new file mode 100644 index 0000000000..1518d40c40 --- /dev/null +++ b/private/path/fabridquery/matchlist_test.go @@ -0,0 +1,83 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabridquery_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/private/path/fabridquery" +) + +func TestAddExistingHop(t *testing.T) { + ml := fabridquery.MatchList{SelectedPolicies: make([]*fabridquery.Policy, 5)} + polIdx := 1 + ml.StorePolicy(1, &fabridquery.Policy{ + Type: fabridquery.STANDARD_POLICY_TYPE, + Policy: &fabrid.Policy{ + IsLocal: false, + Identifier: 100, + Index: fabrid.PolicyID(polIdx), + }, + }) + + ml.StorePolicy(1, &fabridquery.Policy{ + Type: fabridquery.REJECT_POLICY_TYPE, + }) + require.Equal(t, fabrid.PolicyID(polIdx), *ml.Policies()[1]) +} + +func TestRejectedHop(t *testing.T) { + ml := fabridquery.MatchList{SelectedPolicies: make([]*fabridquery.Policy, 5)} + polIdx := 1 + + ml.StorePolicy(1, &fabridquery.Policy{ + Type: fabridquery.REJECT_POLICY_TYPE, + }) + ml.StorePolicy(1, &fabridquery.Policy{ + Type: fabridquery.STANDARD_POLICY_TYPE, + Policy: &fabrid.Policy{ + IsLocal: false, + Identifier: 100, + Index: fabrid.PolicyID(polIdx), + }, + }) + require.NotEqual(t, fabrid.PolicyID(polIdx), *ml.Policies()[1]) + require.False(t, ml.Accepted()) +} + +func TestAcceptedHop(t *testing.T) { + ml := fabridquery.MatchList{SelectedPolicies: make([]*fabridquery.Policy, 6)} + for i := 0; i < 6; i++ { + ml.StorePolicy(i, &fabridquery.Policy{ + Type: fabridquery.STANDARD_POLICY_TYPE, + Policy: &fabrid.Policy{ + IsLocal: false, + Identifier: uint32(100 + i), + Index: fabrid.PolicyID(200 + i), + }, + }) + } + require.True(t, ml.Accepted()) + for i, pol := range ml.Policies() { + require.Equal(t, fabrid.PolicyID(200+i), *pol) + } +} + +func TestPolicies(t *testing.T) { + +} diff --git a/private/path/fabridquery/parser.go b/private/path/fabridquery/parser.go new file mode 100644 index 0000000000..1f2f501227 --- /dev/null +++ b/private/path/fabridquery/parser.go @@ -0,0 +1,266 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabridquery + +import ( + "fmt" + "strconv" + + "github.com/antlr/antlr4/runtime/Go/antlr" + + "github.com/scionproto/scion/antlr/pathpolicyconstraints" + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" +) + +type errorListener struct { + *antlr.DefaultErrorListener + msg string +} + +func (l *errorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, + column int, msg string, e antlr.RecognitionException) { + + l.msg += fmt.Sprintf("%d:%d %s\n", line, column, msg) +} + +type pathpolicyConstraintsListener struct { + *pathpolicyconstraints.BasePathPolicyConstraintsListener + stack []interface{} +} + +func (l *pathpolicyConstraintsListener) push(s interface{}) { + l.stack = append(l.stack, s) +} + +func (l *pathpolicyConstraintsListener) pop() interface{} { + var result interface{} + if len(l.stack) == 0 { + result = "X" + } else { + result = l.stack[len(l.stack)-1] + l.stack = l.stack[:len(l.stack)-1] + } + return result +} + +func (l *pathpolicyConstraintsListener) ExitIf(c *pathpolicyconstraints.IfContext) { + t, ok := l.pop().(Expressions) + if !ok { + return + } + q, ok := l.pop().(Expressions) + if !ok { + return + } + l.push(Query{q, t, Nop{}}) + +} + +func (l *pathpolicyConstraintsListener) ExitIfElse(c *pathpolicyconstraints.IfElseContext) { + f, ok := l.pop().(Expressions) + if !ok { + return + } + t, ok := l.pop().(Expressions) + if !ok { + return + } + q, ok := l.pop().(Expressions) + if !ok { + return + } + l.push(Query{q, t, f}) + +} + +func (l *pathpolicyConstraintsListener) ExitExpressionQuery(c *pathpolicyconstraints. + ExpressionQueryContext) { + + id, ok := l.pop().(Query) + if !ok { + return + } + l.push(Expression{id}) +} + +func (l *pathpolicyConstraintsListener) ExitExpressionIdentifier(c *pathpolicyconstraints. + ExpressionIdentifierContext) { + + id, ok := l.pop().(Identifier) + if !ok { + return + } + l.push(Expression{id}) +} + +func (l *pathpolicyConstraintsListener) ExitExpressionConcat(c *pathpolicyconstraints. + ExpressionConcatContext) { + + right := l.pop().(Expressions) + left := l.pop().(Expressions) + l.push(ConcatExpression{left, right}) +} + +func (l *pathpolicyConstraintsListener) ExitParens(c *pathpolicyconstraints.ParensContext) { +} + +// ExitIdentifier is called when exiting the identifier production. +func (l *pathpolicyConstraintsListener) ExitIdentifier(c *pathpolicyconstraints. + IdentifierContext) { + + policy, ok := l.pop().(Policy) + if !ok { + return + } + egIface, ok := l.pop().(Interface) + if !ok { + return + } + igIface, ok := l.pop().(Interface) + if !ok { + return + } + as, ok := l.pop().(AS) + if !ok { + return + } + isd, ok := l.pop().(ISD) + if !ok { + return + } + l.push(Identifier{ + Isd: isd, + As: as, + IgIntf: igIface, + EgIntf: egIface, + Policy: policy, + }) +} + +// ExitWildcardISD is called when exiting the WildcardISD production. +func (l *pathpolicyConstraintsListener) ExitWildcardISD(c *pathpolicyconstraints. + WildcardISDContext) { + + l.push(ISD{Wildcard: true}) +} + +// ExitISD is called when exiting the ISD production. +func (l *pathpolicyConstraintsListener) ExitISD(c *pathpolicyconstraints.ISDContext) { + n, err := strconv.Atoi(c.GetText()) + if err != nil { + l.push(ISD{Wildcard: true}) + return + } + l.push(ISD{Wildcard: false, Number: n}) +} + +// ExitWildcardAS is called when exiting the WildcardAS production. +func (l *pathpolicyConstraintsListener) ExitWildcardAS(c *pathpolicyconstraints. + WildcardASContext) { + l.push(AS{Wildcard: true}) + +} + +// ExitLegacyAS is called when exiting the LegacyAS production. +func (l *pathpolicyConstraintsListener) ExitLegacyAS(c *pathpolicyconstraints.LegacyASContext) { + as, err := addr.ParseASSep(c.GetText()[1:], "_") + if err != nil { + c.SetException(antlr.NewFailedPredicateException(c.GetParser(), c.GetText(), err.Error())) + } + l.push(AS{ASN: as}) + +} + +// ExitAS is called when exiting the AS production. +func (l *pathpolicyConstraintsListener) ExitAS(c *pathpolicyconstraints.ASContext) { + as, err := addr.ParseASSep(c.GetText()[1:], "_") + if err != nil { + c.SetException(antlr.NewFailedPredicateException(c.GetParser(), c.GetText(), err.Error())) + } + l.push(AS{ASN: as}) +} + +// ExitWildcardIFace is called when exiting the WildcardIFace production. +func (l *pathpolicyConstraintsListener) ExitWildcardIFace(c *pathpolicyconstraints. + WildcardIFaceContext) { + + l.push(Interface{Wildcard: true}) +} + +// ExitIFace is called when exiting the IFace production. +func (l *pathpolicyConstraintsListener) ExitIFace(c *pathpolicyconstraints.IFaceContext) { + n, err := strconv.Atoi(c.GetText()) + if err != nil { + l.push(Interface{Wildcard: true}) + return + } + l.push(Interface{Wildcard: false, Number: n}) +} + +// ExitGlobalPolicy is called when exiting the GlobalPolicy production. +func (l *pathpolicyConstraintsListener) ExitGlobalPolicy(c *pathpolicyconstraints. + GlobalPolicyContext) { + + n, err := strconv.Atoi(c.GetText()[1:]) + if err != nil { + l.push(Policy{Type: WILDCARD_POLICY_TYPE}) + return + } + l.push(Policy{ + Type: STANDARD_POLICY_TYPE, + Policy: &fabrid.Policy{ + IsLocal: false, + Identifier: uint32(n), + }, + }) +} + +// ExitLocalPolicy is called when exiting the LocalPolicy production. +func (l *pathpolicyConstraintsListener) ExitLocalPolicy(c *pathpolicyconstraints. + LocalPolicyContext) { + + n, err := strconv.Atoi(c.GetText()[1:]) + if err != nil { + l.push(Policy{Type: WILDCARD_POLICY_TYPE}) + return + } + l.push(Policy{ + Type: STANDARD_POLICY_TYPE, + Policy: &fabrid.Policy{ + IsLocal: true, + Identifier: uint32(n), + }, + }) +} + +// ExitWildcardPolicy is called when exiting the WildcardPolicy production. +func (l *pathpolicyConstraintsListener) ExitWildcardPolicy(c *pathpolicyconstraints. + WildcardPolicyContext) { + + l.push(Policy{Type: WILDCARD_POLICY_TYPE}) +} + +// ExitWildcardPolicy is called when exiting the WildcardPolicy production. +func (l *pathpolicyConstraintsListener) ExitReject(c *pathpolicyconstraints.RejectContext) { + + l.push(Policy{Type: REJECT_POLICY_TYPE}) +} + +// ExitPolicyIndex is called when exiting the PolicyIndex production. +func (l *pathpolicyConstraintsListener) ExitPolicyIndex(c *pathpolicyconstraints. + PolicyIndexContext) { + // UNUSED +} diff --git a/private/path/fabridquery/query.go b/private/path/fabridquery/query.go new file mode 100644 index 0000000000..adb5920ea9 --- /dev/null +++ b/private/path/fabridquery/query.go @@ -0,0 +1,225 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabridquery + +import ( + "fmt" + + "github.com/antlr/antlr4/runtime/Go/antlr" + + "github.com/scionproto/scion/antlr/pathpolicyconstraints" + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/snet" +) + +type TypedNumber struct { + Wildcard bool + Number int +} + +type ISD TypedNumber + +func (i ISD) Matches(ia addr.ISD) bool { + return i.Wildcard || ia == addr.ISD(i.Number) +} + +func (i ISD) String() string { + if i.Wildcard { + return "*" + } + return fmt.Sprintf("%d", i.Number) + +} + +type AS struct { + Wildcard bool + ASN addr.AS +} + +func (a AS) Matches(iaas addr.AS) bool { + return a.Wildcard || iaas == a.ASN +} + +func (a AS) String() string { + if a.Wildcard { + return "*" + } + return a.ASN.String() +} + +type Interface TypedNumber + +func (i Interface) Matches(intf common.IFIDType) bool { + return i.Wildcard || intf == common.IFIDType(i.Number) +} + +func (i Interface) String() string { + if i.Wildcard { + return "*" + } + return fmt.Sprintf("%d", i.Number) +} + +const ( + WILDCARD_POLICY_TYPE = iota + REJECT_POLICY_TYPE + STANDARD_POLICY_TYPE +) + +type Policy struct { + Type uint8 + *fabrid.Policy +} + +func (p Policy) String() string { + if p.Type == WILDCARD_POLICY_TYPE { + return "*" + } else if p.Type == REJECT_POLICY_TYPE { + return "reject" + } else if p.Type == STANDARD_POLICY_TYPE { + return p.Policy.String() + } + return "unknown" +} + +type Expressions interface { + Evaluate([]snet.HopInterface, *MatchList) (bool, *MatchList) + String() string +} + +type Identifier struct { + Isd ISD + As AS + IgIntf Interface + EgIntf Interface + Policy Policy +} + +func (i Identifier) String() string { + return fmt.Sprintf("{ Isd %s, As %s, IgIntf %s, EgIntf %s, Policy %s }", i.Isd, i.As, i.IgIntf, + i.EgIntf, i.Policy) +} + +func (i Identifier) Evaluate(pi []snet.HopInterface, ml *MatchList) (bool, *MatchList) { + matched := false + for idx, p := range pi { + // Check if ISD, AS and interfaces match between the query and a hop in the path. + if !(i.Isd.Matches(p.IA.ISD()) && i.As.Matches(p.IA.AS()) && i.IgIntf.Matches(p.IgIf) && + i.EgIntf.Matches(p.EgIf)) { + continue + } + // If so and the query sets a wildcard or reject policy, assign this and continue evaluating + // the query + if (i.Policy.Type == WILDCARD_POLICY_TYPE && p.FabridEnabled) || i.Policy. + Type == REJECT_POLICY_TYPE { + ml.StorePolicy(idx, &i.Policy) + } + + if i.Policy.Type == WILDCARD_POLICY_TYPE || i.Policy.Type == REJECT_POLICY_TYPE { + matched = true + continue + } + // Check if the query's policy matches a policy that is available for this hop. + for _, pol := range p.Policies { + if pol.Identifier == i.Policy.Identifier && i.Policy.Policy.IsLocal == pol.IsLocal { + + ml.StorePolicy(idx, &Policy{ + Type: STANDARD_POLICY_TYPE, + Policy: pol, + }) + matched = true + } + } + + } + return matched, ml +} + +type Expression struct { + Expressions +} + +func (e Expression) Evaluate(pi []snet.HopInterface, ml *MatchList) (bool, *MatchList) { + return e.Expressions.Evaluate(pi, ml) +} + +type Query struct { + Q Expressions + T Expressions + F Expressions +} + +func (q Query) String() string { + return fmt.Sprintf(" Query { Query %s, True %s, False %s } ", q.Q, q.T, q.F) +} + +func (q Query) Evaluate(pi []snet.HopInterface, ml *MatchList) (bool, *MatchList) { + mlOriginal := ml.Copy() + qRes, _ := q.Q.Evaluate(pi, mlOriginal) + if qRes { + return q.T.Evaluate(pi, ml) + } + return q.F.Evaluate(pi, ml) +} + +type ConcatExpression struct { + Left Expressions + Right Expressions +} + +func (e ConcatExpression) String() string { + return fmt.Sprintf(" Concat { Left %s, Right %s } ", e.Left, e.Right) +} + +func (e ConcatExpression) Evaluate(pi []snet.HopInterface, ml *MatchList) (bool, *MatchList) { + left, mlLeft := e.Left.Evaluate(pi, ml) + right, mlRight := e.Right.Evaluate(pi, mlLeft) + return left && right, mlRight +} + +type Nop struct{} + +func (n Nop) String() string { + return "Nop" +} + +func (n Nop) Evaluate(_ []snet.HopInterface, list *MatchList) (bool, *MatchList) { + return true, list +} + +func ParseFabridQuery(input string) (Expressions, error) { + istream := antlr.NewInputStream(input) + lexer := pathpolicyconstraints.NewPathPolicyConstraintsLexer(istream) + lexer.RemoveErrorListeners() + errListener := &errorListener{} + lexer.AddErrorListener(errListener) + tstream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) + parser := pathpolicyconstraints.NewPathPolicyConstraintsParser(tstream) + parser.RemoveErrorListeners() + parser.AddErrorListener(errListener) + listener := pathpolicyConstraintsListener{} + antlr.ParseTreeWalkerDefault.Walk(&listener, parser.Start()) + if errListener.msg != "" || (len(listener.stack) != 1) { + return nil, serrors.New(errListener.msg) + } + expr, ok := listener.stack[0].(Expressions) + if !ok { + return nil, serrors.New("Not a valid query") + } + return expr, nil +} diff --git a/private/path/fabridquery/query_test.go b/private/path/fabridquery/query_test.go new file mode 100644 index 0000000000..badf28d379 --- /dev/null +++ b/private/path/fabridquery/query_test.go @@ -0,0 +1,173 @@ +// Copyright 2023 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fabridquery_test + +import ( + "fmt" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/pkg/private/xtest/graph" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/private/path/fabridquery" +) + +type PathProvider struct { + g *graph.Graph +} + +func NewPathProvider(ctrl *gomock.Controller) PathProvider { + return PathProvider{ + g: graph.NewDefaultGraph(ctrl), + } +} + +func (p PathProvider) GetHops(src, dst addr.IA) [][]snet.HopInterface { + result := [][]snet.HopInterface{} + paths := p.g.GetPaths(src.String(), dst.String()) + for _, ifids := range paths { + pathIntfs := make([]snet.PathInterface, 0, len(ifids)) + for _, ifid := range ifids { + ia := p.g.GetParent(ifid) + pathIntfs = append(pathIntfs, snet.PathInterface{ + IA: ia, + ID: common.IFIDType(ifid), + }) + } + fabridInfo := make([]snet.FabridInfo, 0, len(pathIntfs)/2) + fabridInfo = append(fabridInfo, snet.FabridInfo{ + Enabled: true, + Detached: false, + Digest: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16}, + Policies: []*fabrid.Policy{}, + }) + for i := 1; i < len(pathIntfs)-1; i += 2 { + fabridInfo = append(fabridInfo, snet.FabridInfo{ + Enabled: true, + Detached: false, + Digest: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16}, + Policies: p.g.FabridPolicy(uint16(pathIntfs[i].ID), + uint16(pathIntfs[i+1].ID)), + }) + } + fabridInfo = append(fabridInfo, snet.FabridInfo{ + Enabled: true, + Detached: false, + Digest: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16}, + Policies: p.g.FabridPolicy(uint16(pathIntfs[len( + pathIntfs)-1].ID), 0), + }) + metadata := snet.PathMetadata{ + Interfaces: pathIntfs, + FabridInfo: fabridInfo, + } + result = append(result, metadata.Hops()) + } + return result +} + +func TestParseFabridQuery(t *testing.T) { + tests := map[string]struct { + Input string + ExpPolicies []fabrid.PolicyID + Src addr.IA + Dst addr.IA + ExpectError bool + Accept bool + NilPolicies []bool + }{ + "Wildcard": { + Input: "0-0#0,0@0", + Src: xtest.MustParseIA("1-ff00:0:133"), + Dst: xtest.MustParseIA("1-ff00:0:131"), + ExpPolicies: []fabrid.PolicyID{ + fabrid.PolicyID(0), + fabrid.PolicyID(0), + fabrid.PolicyID(0), + }, + NilPolicies: []bool{false, false, false}, + Accept: true, + ExpectError: false, + }, + "Reject All": { + Input: "0-0#0,0@REJECT", + Src: xtest.MustParseIA("1-ff00:0:133"), + Dst: xtest.MustParseIA("1-ff00:0:131"), + ExpPolicies: []fabrid.PolicyID{ + fabrid.PolicyID(0), + fabrid.PolicyID(0), + fabrid.PolicyID(0), + }, + NilPolicies: []bool{false, false, false}, + Accept: false, + ExpectError: false, + }, + "Global policy": { + Input: "0-0#0,0@G1", + Src: xtest.MustParseIA("1-ff00:0:133"), + Dst: xtest.MustParseIA("1-ff00:0:131"), + ExpPolicies: []fabrid.PolicyID{ + fabrid.PolicyID(0x28), + fabrid.PolicyID(0x28), + fabrid.PolicyID(0x0), + }, + NilPolicies: []bool{true, false, false}, + Accept: true, + ExpectError: false, + }, + //TODO(jvanbommel): extend + } + ctrl := gomock.NewController(t) + defer ctrl.Finish() + pp := NewPathProvider(ctrl) + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + hops := pp.GetHops(tc.Src, tc.Dst)[0] + expr, err := fabridquery.ParseFabridQuery(tc.Input) + if tc.ExpectError { + require.Error(t, err) + return + } else { + require.NoError(t, err) + } + ml := fabridquery.MatchList{ + SelectedPolicies: make([]*fabridquery.Policy, len(hops)), + } + _, resMl := expr.Evaluate(hops, &ml) + fmt.Println(resMl.SelectedPolicies) + require.Equal(t, tc.Accept, resMl.Accepted()) + if !tc.Accept { + return + } + pols := resMl.Policies() + for i, pol := range tc.ExpPolicies { + if tc.NilPolicies[i] { + require.True(t, pols[i] == nil) + continue + } + require.Equal(t, pol, *pols[i]) + } + }) + } +} From dd1292c8ccff1d8bcb7569c239cff3a28e626f62 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 13:42:34 +0200 Subject: [PATCH 12/26] FABRID dataplane router - BR fetches DRKey secret values and fabrid config on startup - BR validates and updates FABRID HVFs --- .../router_benchmark/conf/topology.json | 5 + router/BUILD.bazel | 6 + router/cmd/router/BUILD.bazel | 1 + router/cmd/router/main.go | 28 + router/config/config.go | 27 +- router/connector.go | 13 + router/control/BUILD.bazel | 9 + router/control/conf.go | 3 + router/control/drkey.go | 123 ++++ router/control/fetcher.go | 214 ++++++ router/dataplane.go | 292 +++++++- router/dataplane_internal_test.go | 145 +++- router/dataplane_test.go | 696 +++++++++++++++++- router/export_test.go | 6 + router/mock_router/mock.go | 14 + tools/topology/go.py | 23 +- 16 files changed, 1559 insertions(+), 46 deletions(-) create mode 100644 router/control/drkey.go create mode 100644 router/control/fetcher.go diff --git a/acceptance/router_benchmark/conf/topology.json b/acceptance/router_benchmark/conf/topology.json index 6e48ac2cf4..1a09d0857e 100644 --- a/acceptance/router_benchmark/conf/topology.json +++ b/acceptance/router_benchmark/conf/topology.json @@ -5,6 +5,11 @@ "isd_as": "1-ff00:0:1", "mtu": 1400, "dispatched_ports": "1024-65535", + "control_service": { + "cs1": { + "addr": "10.123.10.3:30252" + } + }, "border_routers": { "br1a": { "internal_addr": "10.123.10.1:30042", diff --git a/router/BUILD.bazel b/router/BUILD.bazel index f60cbb7b19..13da7a1347 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/experimental/epic:go_default_library", + "//pkg/experimental/fabrid/crypto:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/processmetrics:go_default_library", @@ -22,6 +23,7 @@ go_library( "//pkg/private/util:go_default_library", "//pkg/scrypto:go_default_library", "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/epic:go_default_library", @@ -53,13 +55,17 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", "//pkg/experimental/epic:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/experimental/fabrid/crypto:go_default_library", "//pkg/private/ptr:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", "//pkg/private/xtest:go_default_library", "//pkg/scrypto:go_default_library", "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/empty:go_default_library", "//pkg/slayers/path/epic:go_default_library", diff --git a/router/cmd/router/BUILD.bazel b/router/cmd/router/BUILD.bazel index f1014ba346..53c1a82475 100644 --- a/router/cmd/router/BUILD.bazel +++ b/router/cmd/router/BUILD.bazel @@ -7,6 +7,7 @@ go_library( importpath = "github.com/scionproto/scion/router/cmd/router", visibility = ["//visibility:private"], deps = [ + "//pkg/addr:go_default_library", "//pkg/log:go_default_library", "//pkg/private/serrors:go_default_library", "//private/app:go_default_library", diff --git a/router/cmd/router/main.go b/router/cmd/router/main.go index 6a43e58796..3976edb3b7 100644 --- a/router/cmd/router/main.go +++ b/router/cmd/router/main.go @@ -26,6 +26,7 @@ import ( "github.com/go-chi/cors" "golang.org/x/sync/errgroup" + "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/private/app" @@ -61,6 +62,7 @@ func realMain(ctx context.Context) error { DataPlane: router.DataPlane{ Metrics: metrics, ExperimentalSCMPAuthentication: globalCfg.Features.ExperimentalSCMPAuthentication, + DRKeyProvider: &control.DRKeyProvider{}, }, ReceiveBufferSize: globalCfg.Router.ReceiveBufferSize, SendBufferSize: globalCfg.Router.SendBufferSize, @@ -126,6 +128,32 @@ func realMain(ctx context.Context) error { defer log.HandlePanic() return globalCfg.Metrics.ServePrometheus(errCtx) }) + dp.DataPlane.DRKeyProvider.Init() + controlServiceAddr, err := controlConfig.Topo.Anycast(addr.SvcCS) + if err != nil { + return err + } + fetcher, err := control.NewFetcher(controlConfig.BR.InternalAddr.Addr().String(), + controlServiceAddr.String(), dp) + if err != nil { + return err + } + if len(globalCfg.Router.DRKey) != 0 { + go func() { + defer log.HandlePanic() + fetcher.StartSecretUpdater(globalCfg.Router.DRKey) + }() + } + if globalCfg.Router.Fabrid { + go func() { + defer log.HandlePanic() + interfaces := make([]uint16, len(controlConfig.BR.IFIDs)) + for i, iface := range controlConfig.BR.IFIDs { + interfaces[i] = uint16(iface) + } + fetcher.StartFabridPolicyFetcher() + }() + } g.Go(func() error { defer log.HandlePanic() runConfig := &router.RunConfig{ diff --git a/router/config/config.go b/router/config/config.go index eeb0308fa1..629f5b3bf7 100644 --- a/router/config/config.go +++ b/router/config/config.go @@ -42,12 +42,14 @@ type Config struct { } type RouterConfig struct { - ReceiveBufferSize int `toml:"receive_buffer_size,omitempty"` - SendBufferSize int `toml:"send_buffer_size,omitempty"` - NumProcessors int `toml:"num_processors,omitempty"` - NumSlowPathProcessors int `toml:"num_slow_processors,omitempty"` - BatchSize int `toml:"batch_size,omitempty"` - BFD BFD `toml:"bfd,omitempty"` + ReceiveBufferSize int `toml:"receive_buffer_size,omitempty"` + SendBufferSize int `toml:"send_buffer_size,omitempty"` + NumProcessors int `toml:"num_processors,omitempty"` + NumSlowPathProcessors int `toml:"num_slow_processors,omitempty"` + BatchSize int `toml:"batch_size,omitempty"` + DRKey []string `toml:"drkey,omitempty"` + Fabrid bool `toml:"fabrid,omitempty"` + BFD BFD `toml:"bfd,omitempty"` // TODO: These two values were introduced to override the port range for // configured router in the context of acceptance tests. However, this // introduces two sources for the port configuration. We should remove this @@ -85,6 +87,19 @@ func (cfg *RouterConfig) Validate() error { if cfg.NumSlowPathProcessors < 1 { return serrors.New("Provided router config is invalid. NumSlowPathProcessors < 1") } + if cfg.Fabrid { + fabrid_drkey := false + for _, protocol := range cfg.DRKey { + if protocol == "FABRID" { + fabrid_drkey = true + break + } + } + if !fabrid_drkey { + return serrors.New("Provided router config is invalid." + + "Enabling FABRID requires adding it to the DRKey protocols.") + } + } if cfg.DispatchedPortStart != nil { if cfg.DispatchedPortEnd == nil { return serrors.New("provided router config is invalid. " + diff --git a/router/connector.go b/router/connector.go index e3d205287f..5476848cfe 100644 --- a/router/connector.go +++ b/router/connector.go @@ -163,6 +163,19 @@ func (c *Connector) DelSvc(ia addr.IA, svc addr.SVC, a *net.UDPAddr) error { return c.DataPlane.DelSvc(svc, a) } +func (c *Connector) AddDRKeySecret(protocolID int32, sv control.SecretValue) error { + c.mtx.Lock() + defer c.mtx.Unlock() + return c.DataPlane.DRKeyProvider.AddSecret(protocolID, sv) +} + +func (c *Connector) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, + interfacePolicies map[uint64]uint32) error { + c.mtx.Lock() + defer c.mtx.Unlock() + return c.DataPlane.UpdateFabridPolicies(ipRangePolicies, interfacePolicies) +} + // SetKey sets the key for the given ISD-AS at the given index. func (c *Connector) SetKey(ia addr.IA, index int, key []byte) error { c.mtx.Lock() diff --git a/router/control/BUILD.bazel b/router/control/BUILD.bazel index 5cd4a3bee5..9a692fec8c 100644 --- a/router/control/BUILD.bazel +++ b/router/control/BUILD.bazel @@ -4,17 +4,26 @@ go_library( name = "go_default_library", srcs = [ "conf.go", + "drkey.go", + "fetcher.go", "iactx.go", ], importpath = "github.com/scionproto/scion/router/control", visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/drkey/specific:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", + "//pkg/proto/control_plane:go_default_library", + "//pkg/proto/control_plane/experimental:go_default_library", + "//pkg/proto/drkey:go_default_library", "//private/keyconf:go_default_library", "//private/topology:go_default_library", + "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", "@org_golang_x_crypto//pbkdf2:go_default_library", ], ) diff --git a/router/control/conf.go b/router/control/conf.go index 7c4ecd8bc3..afff63dff1 100644 --- a/router/control/conf.go +++ b/router/control/conf.go @@ -38,6 +38,9 @@ type Dataplane interface { DelSvc(ia addr.IA, svc addr.SVC, a *net.UDPAddr) error SetKey(ia addr.IA, index int, key []byte) error SetPortRange(start, end uint16) + AddDRKeySecret(protocolID int32, sv SecretValue) error + UpdateFabridPolicies(ipRangePolicies map[uint32][]*PolicyIPRange, + interfacePolicies map[uint64]uint32) error } // BFD is the configuration for the BFD sessions. diff --git a/router/control/drkey.go b/router/control/drkey.go new file mode 100644 index 0000000000..23db229259 --- /dev/null +++ b/router/control/drkey.go @@ -0,0 +1,123 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package control + +import ( + "errors" + "sync" + "time" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey/specific" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" + pb "github.com/scionproto/scion/pkg/proto/drkey" +) + +const pastValidity time.Duration = time.Second * 5 + +var errDRKeySecretInvalid = errors.New("no valid drkey secret for provided time period") +var errDRKeyNotInitialized = errors.New("drkey not initialized") + +var nullByte = [16]byte{} + +type DRKeyProvider struct { + drKeySecrets [][2]*SecretValue + // determines whether index 0 or index 1 should be overwritten next + drKeySecretNextOverwrite []uint8 + mtx sync.Mutex +} + +func (d *DRKeyProvider) Init() { + d.mtx.Lock() + defer d.mtx.Unlock() + log.Debug("Initialize DRKey provider") + numDRKeyProtocols := len(pb.Protocol_value) + d.drKeySecrets = make([][2]*SecretValue, numDRKeyProtocols) + for i := 0; i < numDRKeyProtocols; i++ { + d.drKeySecrets[i] = [2]*SecretValue{ + {}, + {}, + } + } + d.drKeySecretNextOverwrite = make([]uint8, numDRKeyProtocols) +} + +func (d *DRKeyProvider) AddSecret(protocolID int32, sv SecretValue) error { + if d == nil { + return serrors.New("Error while adding new drkey. DRKeyProvider not initialized.") + } + d.mtx.Lock() + defer d.mtx.Unlock() + if d.drKeySecrets == nil { + return errDRKeyNotInitialized + } + if int(protocolID) > len(d.drKeySecrets) { + return serrors.New("Error while adding a new drkey. ProtocolID too large", + "protocolID", protocolID) + } + nextOverwrite := d.drKeySecretNextOverwrite[protocolID] + d.drKeySecrets[protocolID][nextOverwrite] = &sv + log.Debug("Registered new DRKey", "protocol", protocolID, "from", sv.EpochBegin, + "to", sv.EpochEnd) + // switch nextOverwrite from 0 to 1 or from 1 to 0 + d.drKeySecretNextOverwrite[protocolID] = 1 - nextOverwrite + return nil +} + +func (d *DRKeyProvider) getSecret(protocolID int32, t time.Time) (*SecretValue, error) { + secrets := d.drKeySecrets[protocolID] + since := time.Since(t) + if since > pastValidity { + return nil, serrors.New("time after validity window", "t", t, "since", since, + "validityPeriod", pastValidity) + } + for _, sv := range secrets { + if t.After(sv.EpochBegin) && sv.EpochEnd.After(t) { + return sv, nil + } + } + return nil, errDRKeySecretInvalid +} + +func (d *DRKeyProvider) DeriveASASKey(protocolID int32, t time.Time, srcAS addr.IA) ([16]byte, + error) { + drv := specific.Deriver{} + secret, err := d.getSecret(protocolID, t) + if err != nil { + return nullByte, err + } + asToAsKey, err := drv.DeriveLevel1(srcAS, secret.Key) + if err != nil { + return nullByte, err + } + return asToAsKey, nil +} + +func (d *DRKeyProvider) DeriveASHostKey(protocolID int32, t time.Time, srcAS addr.IA, src string) ( + [16]byte, error) { + + drv := specific.Deriver{} + asToAsKey, err := d.DeriveASASKey(protocolID, t, srcAS) + if err != nil { + return nullByte, err + } + asToHostKey, err := drv.DeriveASHost(src, asToAsKey) + if err != nil { + return nullByte, err + } + + return asToHostKey, nil +} diff --git a/router/control/fetcher.go b/router/control/fetcher.go new file mode 100644 index 0000000000..1ad73203b0 --- /dev/null +++ b/router/control/fetcher.go @@ -0,0 +1,214 @@ +// Copyright 2023 ETH Zürich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package control + +import ( + "context" + "net" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" + cppb "github.com/scionproto/scion/pkg/proto/control_plane" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + drpb "github.com/scionproto/scion/pkg/proto/drkey" +) + +type SecretValue struct { + EpochBegin time.Time + EpochEnd time.Time + Key [16]byte +} + +type PolicyIPRange struct { + MPLSLabel uint32 + IPPrefix *net.IPNet +} + +type Fetcher struct { + localAddr *net.TCPAddr + remoteAddr *net.TCPAddr + dp Dataplane +} + +func NewFetcher(localIP string, csAddr string, dp Dataplane) (*Fetcher, error) { + localAddr := &net.TCPAddr{ + IP: net.ParseIP(localIP), + Port: 0, + } + remoteTcpAddr, err := net.ResolveTCPAddr("tcp", csAddr) + if err != nil { + return nil, err + } + f := &Fetcher{ + localAddr: localAddr, + remoteAddr: remoteTcpAddr, + dp: dp, + } + return f, nil +} + +func (f *Fetcher) StartFabridPolicyFetcher() { + retryAfterErrorDuration := 10 * time.Second + for { + mplsPolicyResp, err := f.queryFabridPolicies() + + if err != nil { + log.Debug("Error while querying the FABRID policies from local control service", + "err", err) + time.Sleep(retryAfterErrorDuration) + continue + } + if !mplsPolicyResp.Update { + time.Sleep(30 * time.Minute) + continue + } + + log.Debug("Updated FABRID policies") + err = f.dp.UpdateFabridPolicies(ipPoliciesMapFromPB(mplsPolicyResp.MplsIpMap), + mplsPolicyResp.MplsInterfacePoliciesMap) + if err != nil { + log.Debug("Error while adding FABRID policies", "err", err) + time.Sleep(retryAfterErrorDuration) + continue + } + + time.Sleep(30 * time.Minute) + } +} + +func ipPoliciesMapFromPB(mplsPolicyResp map[uint32]*experimental. + MPLSIPArray) map[uint32][]*PolicyIPRange { + res := make(map[uint32][]*PolicyIPRange) + for key, ipArray := range mplsPolicyResp { + + for _, ipRange := range ipArray.Entry { + var m net.IPMask + if len(ipRange.Ip) == 4 { //TODO(jvanbommel): test this + m = net.CIDRMask(int(ipRange.Prefix), 8*net.IPv4len) + } else { + m = net.CIDRMask(int(ipRange.Prefix), 8*net.IPv6len) + } + res[key] = append(res[key], &PolicyIPRange{ + IPPrefix: &net.IPNet{IP: ipRange.Ip, Mask: m}, + MPLSLabel: ipRange.MplsLabel, + }) + } + } + return res +} + +func (f *Fetcher) queryFabridPolicies() (*experimental.MPLSMapResponse, error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + dialer := func(ctx context.Context, addr string) (net.Conn, error) { + return net.DialTCP("tcp", f.localAddr, f.remoteAddr) + } + grpcconn, err := grpc.DialContext(ctx, f.remoteAddr.String(), + grpc.WithInsecure(), grpc.WithContextDialer(dialer)) + if err != nil { + return nil, err + } + defer grpcconn.Close() + client := experimental.NewFABRIDIntraServiceClient(grpcconn) + rep, err := client.MPLSMap(ctx, + &experimental.MPLSMapRequest{ + Hash: nil, + }) + if err != nil { + return nil, serrors.WrapStr("requesting policy", err) + } + return rep, err +} + +func (f *Fetcher) StartSecretUpdater(protocols []string) { + retryAfterErrorDuration := 5 * time.Second + prefetchTime := time.Minute * 3 + runProtocol := func(protocolID drkey.Protocol) { + // First we make sure that we have a secret that is valid now. + // After that we start prefetching. In case we initially receive a secret value + // that expires before the prefetch time, we prefetch the new secret value immediately. + isPrefetching := false + for { + t := time.Now() + if isPrefetching { + t = t.Add(prefetchTime) + } + sv, err := f.queryASSecret(protocolID, t) + if err != nil { + log.Debug("Error while querying secret value from local control service", + "protocol", protocolID, "err", err) + time.Sleep(retryAfterErrorDuration) + continue + } + err = f.dp.AddDRKeySecret(int32(protocolID), sv) + if err != nil { + log.Debug("Error while adding drkey", "protocol", protocolID, "err", err) + time.Sleep(retryAfterErrorDuration) + continue + } + sleepTime := max(time.Until(sv.EpochEnd)-prefetchTime, 0) + time.Sleep(sleepTime) + isPrefetching = true + } + } + for _, p := range protocols { + pID, ok := drkey.ProtocolStringToId("PROTOCOL_" + p) + if ok { + log.Debug("Register DRKey secret fetcher for", "protocol", p) + go func(protocol drkey.Protocol) { + defer log.HandlePanic() + runProtocol(protocol) + }(pID) + } + } +} + +func (f *Fetcher) queryASSecret( + protocolID drkey.Protocol, minValStart time.Time) (SecretValue, error) { + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + dialer := func(ctx context.Context, addr string) (net.Conn, error) { + return net.DialTCP("tcp", f.localAddr, f.remoteAddr) + } + grpcconn, err := grpc.DialContext(ctx, f.remoteAddr.String(), + grpc.WithInsecure(), grpc.WithContextDialer(dialer)) + if err != nil { + return SecretValue{}, err + } + defer grpcconn.Close() + client := cppb.NewDRKeyIntraServiceClient(grpcconn) + req := &cppb.DRKeySecretValueRequest{ + ProtocolId: drpb.Protocol(protocolID), + ValTime: timestamppb.New(minValStart), + } + res, err := client.DRKeySecretValue(ctx, req) + if err != nil { + return SecretValue{}, err + } + newKey := [16]byte{} + copy(newKey[:16], res.Key[:16]) + sv := SecretValue{ + EpochBegin: res.EpochBegin.AsTime(), + EpochEnd: res.EpochEnd.AsTime(), + Key: newKey, + } + return sv, nil +} diff --git a/router/dataplane.go b/router/dataplane.go index 02324114d5..ca60d185db 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -38,12 +38,14 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" libepic "github.com/scionproto/scion/pkg/experimental/epic" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/processmetrics" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/empty" "github.com/scionproto/scion/pkg/slayers/path/epic" @@ -91,24 +93,27 @@ type BatchConn interface { // from multiple sockets, performs routing, and sends them to their destinations // (after updating the path, if that is needed). type DataPlane struct { - interfaces map[uint16]BatchConn - external map[uint16]BatchConn - linkTypes map[uint16]topology.LinkType - neighborIAs map[uint16]addr.IA - peerInterfaces map[uint16]uint16 - internal BatchConn - internalIP netip.Addr - internalNextHops map[uint16]*net.UDPAddr - svc *services - macFactory func() hash.Hash - bfdSessions map[uint16]bfdSession - localIA addr.IA - mtx sync.Mutex - running bool - Metrics *Metrics - forwardingMetrics map[uint16]interfaceMetrics - dispatchedPortStart uint16 - dispatchedPortEnd uint16 + interfaces map[uint16]BatchConn + external map[uint16]BatchConn + linkTypes map[uint16]topology.LinkType + neighborIAs map[uint16]addr.IA + peerInterfaces map[uint16]uint16 + internal BatchConn + internalIP netip.Addr + internalNextHops map[uint16]*net.UDPAddr + svc *services + macFactory func() hash.Hash + bfdSessions map[uint16]bfdSession + localIA addr.IA + mtx sync.Mutex + running bool + Metrics *Metrics + DRKeyProvider *control.DRKeyProvider + fabridPolicyIPRangeMap map[uint32][]*control.PolicyIPRange + fabridPolicyInterfaceMap map[uint64]uint32 + forwardingMetrics map[uint16]interfaceMetrics + dispatchedPortStart uint16 + dispatchedPortEnd uint16 ExperimentalSCMPAuthentication bool @@ -485,6 +490,17 @@ func (d *DataPlane) addNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro return d.addBFDController(ifID, s, cfg, m) } +func (d *DataPlane) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, + interfacePolicies map[uint64]uint32) error { + d.mtx.Lock() + defer d.mtx.Unlock() + // TODO(rohrerj): check for concurrency issues + // when an update happens during reading + d.fabridPolicyIPRangeMap = ipRangePolicies + d.fabridPolicyInterfaceMap = interfacePolicies + return nil +} + func max(a int, b int) int { if a > b { return a @@ -595,6 +611,7 @@ type packet struct { trafficType trafficType // The goods rawPacket []byte + mplsLabel uint8 } type slowPacket struct { @@ -747,6 +764,7 @@ func (d *DataPlane) runProcessor(id int, q <-chan packet, } p.rawPacket = result.OutPkt p.dstAddr = result.OutAddr + p.mplsLabel = uint8(processor.mplsLabel) p.trafficType = result.TrafficType select { case fwCh <- p: @@ -1023,10 +1041,11 @@ func readUpTo(c <-chan packet, n int, needsBlocking bool, pkts []packet) int { func newPacketProcessor(d *DataPlane) *scionPacketProcessor { p := &scionPacketProcessor{ - d: d, - buffer: gopacket.NewSerializeBuffer(), - mac: d.macFactory(), - macInputBuffer: make([]byte, max(path.MACBufferSize, libepic.MACBufferSize)), + d: d, + buffer: gopacket.NewSerializeBuffer(), + mac: d.macFactory(), + macInputBuffer: make([]byte, max(path.MACBufferSize, libepic.MACBufferSize)), + fabridInputBuffer: make([]byte, crypto.FabridMacInputSize), } p.scionLayer.RecyclePaths() return p @@ -1048,12 +1067,185 @@ func (p *scionPacketProcessor) reset() error { p.mac.Reset() p.cachedMac = nil // Reset hbh layer - p.hbhLayer = slayers.HopByHopExtnSkipper{} + p.hbhLayer = slayers.HopByHopExtn{} // Reset e2e layer p.e2eLayer = slayers.EndToEndExtnSkipper{} + p.identifier = nil + p.fabrid = nil + p.mplsLabel = 0 + p.nextHop = nil return nil } +func (p *scionPacketProcessor) processFabrid(egressIF uint16) error { + meta := p.fabrid.HopfieldMetadata[0] + src, err := p.scionLayer.SrcAddr() + if err != nil { + return err + } + var key [16]byte + if p.fabrid.HopfieldMetadata[0].ASLevelKey { + key, err = p.d.DRKeyProvider.DeriveASASKey(int32(drkey.FABRID), p.identifier.Timestamp, + p.scionLayer.SrcIA) + } else { + key, err = p.d.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), p.identifier.Timestamp, + p.scionLayer.SrcIA, src.String()) + } + if err != nil { + return err + } + policyID, err := crypto.ComputePolicyID(meta, p.identifier, key[:]) + if err != nil { + return err + } + err = crypto.VerifyAndUpdate(meta, p.identifier, &p.scionLayer, p.fabridInputBuffer, key[:], + p.ingressID, egressIF) + if err != nil { + return err + } + // Check / set MPLS label only if policy ID != 0 + // and only if the packet will be sent within the AS or to another router of the local AS + if policyID != 0 { + var mplsLabel uint32 + switch p.transitType { + case ingressEgressDifferentRouter: + mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), + uint32(policyID), uint32(egressIF)) + case internalTraffic: + mplsLabel, err = p.d.getFabridMplsLabel(uint32(p.ingressID), uint32(policyID), + p.nextHop.IP) + if err != nil { + mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), + uint32(policyID), 0) + } + case ingressEgressSameRouter: + return nil + } + if err != nil { + return err + } + p.mplsLabel = mplsLabel + } + return nil +} + +func (d *DataPlane) getFabridMplsLabelForInterface(ingressID uint32, policyIndex uint32, + egressID uint32) (uint32, error) { + + policyMapKey := uint64(ingressID)<<24 + uint64(egressID)<<8 + uint64(policyIndex) + mplsLabel, found := d.fabridPolicyInterfaceMap[policyMapKey] + if !found { + //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): + policyMapKey = 1<<63 + uint64(egressID)<<8 + uint64(policyIndex) + mplsLabel, found = d.fabridPolicyInterfaceMap[policyMapKey] + if !found { + return 0, serrors.New("Provided policyID is invalid", + "ingress", ingressID, "index", policyIndex, "egress", egressID) + } + } + return mplsLabel, nil +} + +func (d *DataPlane) getFabridMplsLabel(ingressID uint32, policyIndex uint32, + nextHopIP net.IP) (uint32, error) { + + policyMapKey := ingressID<<8 + policyIndex + ipRanges, found := d.fabridPolicyIPRangeMap[policyMapKey] + if !found { + //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): + policyMapKey = 1<<31 + policyIndex + ipRanges, found = d.fabridPolicyIPRangeMap[policyMapKey] + if !found { + return 0, serrors.New("Provided policyID is invalid", + "ingress", ingressID, "index", policyIndex) + } + } + var bestRange *control.PolicyIPRange + for _, r := range ipRanges { + if r.IPPrefix.Contains(nextHopIP) { + if bestRange == nil { + bestRange = r + } else { + bestPrefixLength, _ := bestRange.IPPrefix.Mask.Size() + currentPrefixLength, _ := r.IPPrefix.Mask.Size() + if currentPrefixLength > bestPrefixLength { + bestRange = r + } + } + } + } + if bestRange == nil { + return 0, serrors.New("Provided policy index is not valid for nexthop.", + "index", policyIndex, "next hop IP", nextHopIP) + } + return bestRange.MPLSLabel, nil +} + +func (p *scionPacketProcessor) processHbhOptions(egressIF uint16) error { + var err error + for _, opt := range p.hbhLayer.Options { + switch opt.OptType { + case slayers.OptTypeIdentifier: + if p.identifier != nil { + return serrors.New("Identifier HBH option provided multiple times") + } + // TODO(marcodermatt): Find cleaner solution for getting timestamp of first InfoField + baseTimestamp := p.infoField.Timestamp + if p.path.PathMeta.CurrINF > 0 { + firstInfoField, err := p.path.GetInfoField(0) + if err != nil { + return serrors.New("Failed to parse first InfoField") + } + baseTimestamp = firstInfoField.Timestamp + } + p.identifier, err = extension.ParseIdentifierOption(opt, baseTimestamp) + if err != nil { + return err + } + case slayers.OptTypeFabrid: + if p.fabrid != nil { + return serrors.New("FABRID HBH option provided multiple times") + } + if p.identifier == nil { + return serrors.New("Identifier HBH option must be present when using FABRID") + } + + // Calculate FABRID hop index + currHop := p.path.PathMeta.CurrHF + if !p.infoField.Peer { + currHop -= p.path.PathMeta.CurrINF + } + + // Skip if this is an intermediary egress router + if p.ingressID == 0 && currHop != 0 { + return nil + } + + // Calculate number of FABRID hops + numHFs := p.path.NumHops - p.path.NumINF + 1 + if p.infoField.Peer { + numHFs++ + } + fabrid, err := extension.ParseFabridOptionCurrentHop(opt, currHop, uint8(numHFs)) + if err != nil { + return err + } + if fabrid.HopfieldMetadata[0].FabridEnabled { + p.fabrid = fabrid + if err = p.processFabrid(egressIF); err != nil { + return err + } + if err = fabrid.HopfieldMetadata[0].SerializeTo(opt. + OptData[currHop*4:]); err != nil { + return err + } + } + default: + } + } + return err +} + func (p *scionPacketProcessor) processPkt(rawPkt []byte, srcAddr *net.UDPAddr, ingressID uint16) (processResult, error) { @@ -1222,7 +1414,7 @@ type scionPacketProcessor struct { // scionLayer is the SCION gopacket layer. scionLayer slayers.SCION - hbhLayer slayers.HopByHopExtnSkipper + hbhLayer slayers.HopByHopExtn e2eLayer slayers.EndToEndExtnSkipper // last is the last parsed layer, i.e. either &scionLayer, &hbhLayer or &e2eLayer lastLayer gopacket.DecodingLayer @@ -1246,8 +1438,24 @@ type scionPacketProcessor struct { // bfdLayer is reusable buffer for parsing BFD messages bfdLayer layers.BFD + + identifier *extension.IdentifierOption + fabrid *extension.FabridOption + fabridInputBuffer []byte + mplsLabel uint32 + // IP of the next hop. Only valid for the inbound or AS transit cases + nextHop *net.UDPAddr + transitType transitType } +type transitType int + +const ( + ingressEgressSameRouter transitType = iota + ingressEgressDifferentRouter + internalTraffic +) + type slowPathType int const ( @@ -1835,6 +2043,12 @@ func (p *scionPacketProcessor) process() (processResult, error) { if err != nil { return r, err } + + p.transitType = internalTraffic + p.nextHop = a + if err := p.processHbhOptions(0); err != nil { + return processResult{}, err + } return processResult{OutAddr: a, OutPkt: p.rawPkt, TrafficType: ttIn}, nil } @@ -1873,6 +2087,10 @@ func (p *scionPacketProcessor) process() (processResult, error) { } egressID := p.egressInterface() if _, ok := p.d.external[egressID]; ok { + p.transitType = ingressEgressSameRouter + if err := p.processHbhOptions(egressID); err != nil { + return processResult{}, err + } // Not ASTransit in if err := p.processEgress(); err != nil { return processResult{}, err @@ -1893,6 +2111,11 @@ func (p *scionPacketProcessor) process() (processResult, error) { } // ASTransit in: pkt leaving this AS through another BR. if a, ok := p.d.internalNextHops[egressID]; ok { + p.transitType = ingressEgressDifferentRouter + p.nextHop = a + if err := p.processHbhOptions(egressID); err != nil { + return processResult{}, err + } return processResult{OutAddr: a, OutPkt: p.rawPkt, TrafficType: ttInTransit}, nil } errCode := slayers.SCMPCodeUnknownHopFieldEgress @@ -2370,17 +2593,14 @@ func (p *slowPathPacketProcessor) prepareSCMP( scmpH := slayers.SCMP{TypeCode: typeCode} scmpH.SetNetworkLayerForChecksum(&scionL) - needsAuth := false - if p.d.ExperimentalSCMPAuthentication { - // Error messages must be authenticated. - // Traceroute are OPTIONALLY authenticated ONLY IF the request - // was authenticated. - // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth - // if SCMPTypeTracerouteReply to create the response. - needsAuth = cause != nil || - (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && - p.hasValidAuth(time.Now())) - } + // Error messages must be authenticated. + // Traceroute are OPTIONALLY authenticated ONLY IF the request + // was authenticated. + // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth + // if SCMPTypeTracerouteReply to create the response. + needsAuth := cause != nil || + (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && + p.hasValidAuth(time.Now())) var quote []byte if cause != nil { @@ -2573,6 +2793,8 @@ func nextHdr(layer gopacket.DecodingLayer) slayers.L4ProtocolType { return v.NextHdr case *slayers.EndToEndExtnSkipper: return v.NextHdr + case *slayers.HopByHopExtn: + return v.NextHdr case *slayers.HopByHopExtnSkipper: return v.NextHdr default: diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go index 393e289ab7..5636831135 100644 --- a/router/dataplane_internal_test.go +++ b/router/dataplane_internal_test.go @@ -39,6 +39,7 @@ import ( "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/scion" underlayconn "github.com/scionproto/scion/private/underlay/conn" + "github.com/scionproto/scion/router/control" "github.com/scionproto/scion/router/mock_router" ) @@ -214,6 +215,147 @@ func TestForwarder(t *testing.T) { } } +func TestFabridPolicies(t *testing.T) { + type testcase struct { + name string + ipRangePolicies map[uint32][]*control.PolicyIPRange + interfacePolicies map[uint64]uint32 + packetIngress uint32 + packetEgress uint32 + useIPRange bool + packetPolicyIndex uint32 + nextHopIP net.IP + expectedMplsLabel uint32 + expectsError bool + } + testcases := []testcase{ + { + name: "ingress and policyindex tuple exists with single ip range", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 0xa<<8 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + }, + }, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "ingress and policyindex tuple doesn't exist", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{}, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + expectsError: true, + useIPRange: true, + }, + { + name: "ingress and policyindex tuple exists with multiple ip ranges", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 0xa<<8 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + &control.PolicyIPRange{ + MPLSLabel: 2, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/31"), + }, + &control.PolicyIPRange{ + MPLSLabel: 3, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/30"), + }, + &control.PolicyIPRange{ + MPLSLabel: 4, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.2/32"), + }, + }, + }, + expectedMplsLabel: 2, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "ip range only exists for default value", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 1<<31 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + }, + }, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "mpls label exists for interface map", + interfacePolicies: map[uint64]uint32{ + 1<<24 + 2<<8 + 0xf: 7, + 1<<63 + 2<<8 + 0xf: 5, // default value + }, + expectedMplsLabel: 7, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + useIPRange: false, + }, + { + name: "mpls label exists for interface map with default value", + interfacePolicies: map[uint64]uint32{ + 1<<63 + 2<<8 + 0xf: 5, // default value + }, + expectedMplsLabel: 5, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + useIPRange: false, + }, + { + name: "mpls label doesnt exist for interface map", + interfacePolicies: map[uint64]uint32{}, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + expectsError: true, + useIPRange: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + dp := &DataPlane{Metrics: metrics} + err := dp.UpdateFabridPolicies(tc.ipRangePolicies, tc.interfacePolicies) + assert.NoError(t, err) + var mplsLabel uint32 + if tc.useIPRange { + mplsLabel, err = dp.getFabridMplsLabel(tc.packetIngress, tc.packetPolicyIndex, + tc.nextHopIP) + } else { + mplsLabel, err = dp.getFabridMplsLabelForInterface(tc.packetIngress, + tc.packetPolicyIndex, tc.packetEgress) + } + if tc.expectsError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedMplsLabel, mplsLabel) + } + }) + } + +} + func TestComputeProcId(t *testing.T) { randomValueBytes := []byte{1, 2, 3, 4} numProcs := 10000 @@ -446,7 +588,8 @@ func TestSlowPathProcessing(t *testing.T) { nil, mock_router.NewMockBatchConn(ctrl), fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), nil, testKey) + xtest.MustParseIA("1-ff00:0:110"), + nil, testKey) }, mockMsg: func() []byte { spkt := prepBaseMsg(t, payload, 0) diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 7750bb1861..1f99c754d2 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -33,13 +33,17 @@ import ( "golang.org/x/net/ipv4" "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" libepic "github.com/scionproto/scion/pkg/experimental/epic" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" "github.com/scionproto/scion/pkg/private/ptr" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" "github.com/scionproto/scion/pkg/private/xtest" "github.com/scionproto/scion/pkg/scrypto" "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/empty" "github.com/scionproto/scion/pkg/slayers/path/epic" @@ -237,6 +241,689 @@ func TestDataPlaneRun(t *testing.T) { testCases := map[string]struct { prepareDP func(*gomock.Controller, chan<- struct{}) *router.DataPlane }{ + "fabrid basic": { + prepareDP: func(ctrl *gomock.Controller, done chan<- struct{}) *router.DataPlane { + ret := &router.DataPlane{Metrics: metrics, DRKeyProvider: &control.DRKeyProvider{}} + ret.DRKeyProvider.Init() + key := []byte("testkey_xxxxxxxx") + dstIA := xtest.MustParseIA("4-ff00:0:411") + dstAddr := addr.MustParseHost("2.2.2.2") + srcIA := xtest.MustParseIA("2-ff00:0:222") + srcAddr := addr.MustParseHost("1.1.1.1") + + asDRKey := [16]byte{ + 0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff, + } + err := ret.DRKeyProvider.AddSecret(int32(drkey.FABRID), + control.SecretValue{ + Key: asDRKey, + EpochBegin: time.Now().Add(-time.Second), + EpochEnd: time.Now().AddDate(1, 0, 0), + }) + assert.NoError(t, err) + local := xtest.MustParseIA("1-ff00:0:110") + now := time.Now().Truncate(time.Millisecond) + identifier := extension.IdentifierOption{ + Timestamp: now, + PacketID: 0xabcd, + BaseTimestamp: uint32(now.Unix()), + } + + policyID := fabrid.PolicyID(0x0f) + _, ipPrefix, _ := net.ParseCIDR("0.0.0.0/0") + err = ret.UpdateFabridPolicies(map[uint32][]*control.PolicyIPRange{ + // ingress 3 with policy index 0x0f + (3<<8 + 0x0f): { + { + MPLSLabel: 1, + IPPrefix: ipPrefix, + }, + }, + }, nil) + assert.NoError(t, err) + + asToHostKey, err := ret.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), now, + srcIA, srcAddr.String()) + assert.NoError(t, err) + encPolicyID, err := crypto.EncryptPolicyID(policyID, &identifier, asToHostKey[:]) + assert.NoError(t, err) + + mExternal := mock_router.NewMockBatchConn(ctrl) + infoField := path.InfoField{SegID: 0x111, ConsDir: true, + Timestamp: util.TimeToSecs(now)} + + mExternal.EXPECT().ReadBatch(gomock.Any()).DoAndReturn( + func(m underlayconn.Messages) (int, error) { + buf := gopacket.NewSerializeBuffer() + p := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + infoField, + }, + HopFields: []path.HopField{ + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 3, ConsEgress: 4}, + {ConsIngress: 5, ConsEgress: 6}, + }, + } + p.HopFields[1].Mac = computeMAC(t, key, p.InfoFields[0], + p.HopFields[1]) + rawDstAddr := dstAddr.IP().As4() + rawSrcAddr := srcAddr.IP().As4() + s := slayers.SCION{ + NextHdr: slayers.HopByHopClass, + PathType: scion.PathType, + DstIA: dstIA, + SrcIA: srcIA, + SrcAddrType: slayers.T4Ip, + DstAddrType: slayers.T4Ip, + RawSrcAddr: rawSrcAddr[:], + RawDstAddr: rawDstAddr[:], + Path: p, + } + + identifierData := make([]byte, 8) + err = identifier.Serialize(identifierData) + assert.NoError(t, err) + + meta := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + tmp := make([]byte, 100) + err = crypto.ComputeBaseHVF(meta, &identifier, &s, tmp, asToHostKey[:], + 3, 4) + assert.NoError(t, err) + + fopt := extension.FabridOption{ + HopfieldMetadata: []*extension.FabridHopfieldMetadata{ + {}, + meta, + {}, + }, + } + fabridData := make([]byte, 16) + err = fopt.SerializeTo(fabridData) + assert.NoError(t, err) + + hbh := slayers.HopByHopExtn{ + Options: []*slayers.HopByHopOption{ + { + OptType: slayers.OptTypeIdentifier, + OptData: identifierData, + OptDataLen: uint8(len(identifierData)), + }, + { + OptType: slayers.OptTypeFabrid, + OptData: fabridData, + OptDataLen: uint8(len(fabridData)), + }, + }, + } + err = gopacket.SerializeLayers(buf, + gopacket.SerializeOptions{FixLengths: true}, &s, &hbh) + assert.NoError(t, err) + raw := buf.Bytes() + copy(m[0].Buffers[0], raw) + m[0].N = len(raw) + m[0].Addr = &net.UDPAddr{IP: net.IP{10, 0, 200, 200}} + + return 1, nil + }, + ).Times(1) + mExternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), + gomock.Any()).Return(0, nil).AnyTimes() + + mExternal2 := mock_router.NewMockBatchConn(ctrl) + mExternal2.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mExternal2.EXPECT().WriteBatch(gomock.Any(), 0).DoAndReturn( + func(ms underlayconn.Messages, flags int) (int, error) { + if len(ms) != 1 { + assert.Fail(t, "len(ms)!=1", len(ms)) + return 0, nil + } + s := slayers.SCION{} + hbh := slayers.HopByHopExtn{} + _, err := router.DecodeLayers(ms[0].Buffers[0], &s, &hbh) + assert.NoError(t, err) + + containsFabrid := false + containsIdentifier := false + var foundIdentifier *extension.IdentifierOption + var foundFabrid *extension.FabridOption + + baseTs := infoField.Timestamp + for _, hbhOption := range hbh.Options { + switch hbhOption.OptType { + case slayers.OptTypeIdentifier: + containsIdentifier = true + foundIdentifier, err = extension.ParseIdentifierOption(hbhOption, + baseTs) + assert.NoError(t, err) + assert.Equal(t, identifier.Timestamp, foundIdentifier.Timestamp) + assert.Equal(t, identifier.PacketID, foundIdentifier.PacketID) + case slayers.OptTypeFabrid: + containsFabrid = true + if containsIdentifier { + foundFabrid, err = extension.ParseFabridOptionFullExtension( + hbhOption, 3) + assert.NoError(t, err) + meta := foundFabrid.HopfieldMetadata[1] + tmp := make([]byte, 100) + recomputedVerifiedHVF := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + err = crypto.ComputeVerifiedHVF(recomputedVerifiedHVF, + foundIdentifier, &s, tmp, asToHostKey[:], 3, + 4) + assert.NoError(t, err) + assert.Equal(t, encPolicyID, meta.EncryptedPolicyID) + assert.Equal(t, recomputedVerifiedHVF.HopValidationField, + meta.HopValidationField) + } else { + assert.Fail(t, "identifier not present before "+ + "fabrid") + } + default: + + } + + } + assert.True(t, containsIdentifier) + assert.True(t, containsFabrid) + + done <- struct{}{} + return 1, nil + }).Times(1) + mExternal2.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + + l := control.LinkEnd{ + IA: local, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.100")}, + } + r1 := control.LinkEnd{ + IA: srcIA, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.200")}, + } + r2 := control.LinkEnd{ + IA: dstIA, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.300")}, + } + nobfd := control.BFD{Disable: ptr.To(true)} + + _ = ret.AddExternalInterface(3, mExternal, l, r1, nobfd) + _ = ret.AddLinkType(3, topology.Core) + _ = ret.AddExternalInterface(4, mExternal2, l, r2, nobfd) + _ = ret.AddLinkType(4, topology.Core) + + _ = ret.SetIA(local) + _ = ret.SetKey(key) + return ret + }, + }, + "fabrid mpls ingress egress different router": { + prepareDP: func(c1 *gomock.Controller, done chan<- struct{}) *router.DataPlane { + ret := &router.DataPlane{Metrics: metrics, DRKeyProvider: &control.DRKeyProvider{}} + ret.DRKeyProvider.Init() + key := []byte("testkey_xxxxxxxx") + dstIA := xtest.MustParseIA("4-ff00:0:411") + dstAddr := addr.MustParseHost("2.2.2.2") + srcIA := xtest.MustParseIA("2-ff00:0:222") + srcAddr := addr.MustParseHost("1.1.1.1") + + asDRKey := [16]byte{ + 0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff, + } + _ = ret.DRKeyProvider.AddSecret(int32(drkey.FABRID), + control.SecretValue{ + Key: asDRKey, + EpochBegin: time.Now().Add(-time.Second), + EpochEnd: time.Now().AddDate(1, 0, 0), + }) + local := xtest.MustParseIA("1-ff00:0:110") + now := time.Now().Truncate(time.Millisecond) + identifier := extension.IdentifierOption{ + Timestamp: now, + PacketID: 0xabcd, + BaseTimestamp: uint32(now.Unix()), + } + + policyID := fabrid.PolicyID(0x0f) + err := ret.UpdateFabridPolicies(nil, + map[uint64]uint32{ + 3<<24 + 2<<8 + 0x0f: 7, + }) + assert.NoError(t, err) + + asToHostKey, err := ret.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), now, + srcIA, srcAddr.String()) + assert.NoError(t, err) + encPolicyID, err := crypto.EncryptPolicyID(policyID, &identifier, asToHostKey[:]) + assert.NoError(t, err) + + mExternal := mock_router.NewMockBatchConn(ctrl) + infoField := path.InfoField{SegID: 0x111, ConsDir: true, + Timestamp: util.TimeToSecs(now)} + + mExternal.EXPECT().ReadBatch(gomock.Any()).DoAndReturn( + func(m underlayconn.Messages) (int, error) { + buf := gopacket.NewSerializeBuffer() + p := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 1, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + infoField, + }, + HopFields: []path.HopField{ + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 3, ConsEgress: 2}, + {ConsIngress: 5, ConsEgress: 6}, + }, + } + p.HopFields[1].Mac = computeMAC(t, key, p.InfoFields[0], + p.HopFields[1]) + rawDstAddr := dstAddr.IP().As4() + rawSrcAddr := srcAddr.IP().As4() + s := slayers.SCION{ + NextHdr: slayers.HopByHopClass, + PathType: scion.PathType, + DstIA: dstIA, + SrcIA: srcIA, + SrcAddrType: slayers.T4Ip, + DstAddrType: slayers.T4Ip, + RawSrcAddr: rawSrcAddr[:], + RawDstAddr: rawDstAddr[:], + Path: p, + } + + identifierData := make([]byte, 8) + err = identifier.Serialize(identifierData) + assert.NoError(t, err) + + meta := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + tmp := make([]byte, 100) + err = crypto.ComputeBaseHVF(meta, &identifier, &s, tmp, asToHostKey[:], + 3, 2) + assert.NoError(t, err) + + fopt := extension.FabridOption{ + HopfieldMetadata: []*extension.FabridHopfieldMetadata{ + {}, + meta, + {}, + }, + } + fabridData := make([]byte, 16) + err = fopt.SerializeTo(fabridData) + assert.NoError(t, err) + hbh := slayers.HopByHopExtn{ + Options: []*slayers.HopByHopOption{ + { + OptType: slayers.OptTypeIdentifier, + OptData: identifierData, + OptDataLen: uint8(len(identifierData)), + }, + { + OptType: slayers.OptTypeFabrid, + OptData: fabridData, + OptDataLen: uint8(len(fabridData)), + }, + }, + } + err = gopacket.SerializeLayers(buf, + gopacket.SerializeOptions{FixLengths: true}, &s, &hbh) + assert.NoError(t, err) + raw := buf.Bytes() + copy(m[0].Buffers[0], raw) + m[0].N = len(raw) + m[0].Addr = &net.UDPAddr{IP: net.IP{10, 0, 200, 200}} + + return 1, nil + }, + ).Times(1) + mExternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), + gomock.Any()).Return(0, nil).AnyTimes() + + mInternal := mock_router.NewMockBatchConn(ctrl) + mInternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mInternal.EXPECT().WriteBatch(gomock.Any(), 0).DoAndReturn( + func(ms underlayconn.Messages, flags int) (int, error) { + if len(ms) != 1 { + assert.Fail(t, "len(ms)!=1", len(ms)) + return 0, nil + } + s := slayers.SCION{} + hbh := slayers.HopByHopExtn{} + _, err := router.DecodeLayers(ms[0].Buffers[0], &s, &hbh) + assert.NoError(t, err) + + containsFabrid := false + containsIdentifier := false + var foundIdentifier *extension.IdentifierOption + var foundFabrid *extension.FabridOption + + baseTs := infoField.Timestamp + for _, hbhOption := range hbh.Options { + switch hbhOption.OptType { + case slayers.OptTypeIdentifier: + containsIdentifier = true + foundIdentifier, err = extension.ParseIdentifierOption( + hbhOption, baseTs) + assert.NoError(t, err) + assert.Equal(t, identifier.Timestamp, foundIdentifier.Timestamp) + assert.Equal(t, identifier.PacketID, foundIdentifier.PacketID) + case slayers.OptTypeFabrid: + containsFabrid = true + if containsIdentifier { + foundFabrid, err = extension.ParseFabridOptionFullExtension( + hbhOption, 3) + assert.NoError(t, err) + meta := foundFabrid.HopfieldMetadata[1] + tmp := make([]byte, 100) + recomputedVerifiedHVF := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + err = crypto.ComputeVerifiedHVF(recomputedVerifiedHVF, + foundIdentifier, &s, tmp, asToHostKey[:], 3, + 2) + assert.NoError(t, err) + assert.Equal(t, encPolicyID, meta.EncryptedPolicyID) + assert.Equal(t, recomputedVerifiedHVF.HopValidationField, + meta.HopValidationField) + } else { + assert.Fail(t, "identifier not present "+ + "before fabrid") + } + default: + } + } + assert.True(t, containsIdentifier) + assert.True(t, containsFabrid) + + done <- struct{}{} + return 1, nil + }).Times(1) + _ = ret.AddInternalInterface(mInternal, netip.Addr{}) + + l := control.LinkEnd{ + IA: local, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.100")}, + } + r1 := control.LinkEnd{ + IA: srcIA, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.200")}, + } + nobfd := control.BFD{Disable: ptr.To(true)} + + _ = ret.AddExternalInterface(3, mExternal, l, r1, nobfd) + _ = ret.AddLinkType(3, topology.Core) + + _ = ret.SetIA(local) + _ = ret.SetKey(key) + + nextHopAddr := xtest.MustParseUDPAddr(t, "127.0.0.2:8888") + err = ret.AddNextHop(2, l.Addr, nextHopAddr, nobfd, "") + assert.NoError(t, err) + err = ret.AddLinkType(2, topology.Core) + assert.NoError(t, err) + return ret + }, + }, + "fabrid mpls internal traffic": { + prepareDP: func(c1 *gomock.Controller, done chan<- struct{}) *router.DataPlane { + ret := &router.DataPlane{Metrics: metrics, DRKeyProvider: &control.DRKeyProvider{}} + ret.DRKeyProvider.Init() + key := []byte("testkey_xxxxxxxx") + dstIA := xtest.MustParseIA("4-ff00:0:411") + dstAddr := addr.MustParseHost("2.2.2.2") + srcIA := xtest.MustParseIA("2-ff00:0:222") + srcAddr := addr.MustParseHost("1.1.1.1") + + asDRKey := [16]byte{ + 0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff, + } + _ = ret.DRKeyProvider.AddSecret(int32(drkey.FABRID), + control.SecretValue{ + Key: asDRKey, + EpochBegin: time.Now().Add(-time.Second), + EpochEnd: time.Now().AddDate(1, 0, 0), + }) + local := dstIA + now := time.Now().Truncate(time.Millisecond) + identifier := extension.IdentifierOption{ + Timestamp: now, + PacketID: 0xabcd, + BaseTimestamp: uint32(now.Unix()), + } + + policyID := fabrid.PolicyID(0x0f) + _, ipPrefix, _ := net.ParseCIDR("2.2.2.0/24") + err := ret.UpdateFabridPolicies(map[uint32][]*control.PolicyIPRange{ + // ingress 3 with policy index 0x0f + (3<<8 + 0x0f): { + { + MPLSLabel: 7, + IPPrefix: ipPrefix, + }, + }, + }, nil) + + assert.NoError(t, err) + + asToHostKey, err := ret.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), now, + srcIA, srcAddr.String()) + assert.NoError(t, err) + encPolicyID, err := crypto.EncryptPolicyID(policyID, &identifier, asToHostKey[:]) + assert.NoError(t, err) + + mExternal := mock_router.NewMockBatchConn(ctrl) + infoField := path.InfoField{SegID: 0x111, ConsDir: true, + Timestamp: util.TimeToSecs(now)} + + mExternal.EXPECT().ReadBatch(gomock.Any()).DoAndReturn( + func(m underlayconn.Messages) (int, error) { + buf := gopacket.NewSerializeBuffer() + p := &scion.Decoded{ + Base: scion.Base{ + PathMeta: scion.MetaHdr{ + CurrHF: 2, + SegLen: [3]uint8{3, 0, 0}, + }, + NumINF: 1, + NumHops: 3, + }, + InfoFields: []path.InfoField{ + infoField, + }, + HopFields: []path.HopField{ + {ConsIngress: 1, ConsEgress: 2}, + {ConsIngress: 3, ConsEgress: 4}, + {ConsIngress: 3, ConsEgress: 0}, + }, + } + p.HopFields[2].Mac = computeMAC(t, key, p.InfoFields[0], + p.HopFields[2]) + rawDstAddr := dstAddr.IP().As4() + rawSrcAddr := srcAddr.IP().As4() + s := slayers.SCION{ + NextHdr: slayers.HopByHopClass, + PathType: scion.PathType, + DstIA: dstIA, + SrcIA: srcIA, + SrcAddrType: slayers.T4Ip, + DstAddrType: slayers.T4Ip, + RawSrcAddr: rawSrcAddr[:], + RawDstAddr: rawDstAddr[:], + Path: p, + } + + identifierData := make([]byte, 8) + err = identifier.Serialize(identifierData) + assert.NoError(t, err) + + meta := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + tmp := make([]byte, 100) + err = crypto.ComputeBaseHVF(meta, &identifier, &s, tmp, asToHostKey[:], + 3, 0) + assert.NoError(t, err) + + fopt := extension.FabridOption{ + HopfieldMetadata: []*extension.FabridHopfieldMetadata{ + {}, + {}, + meta, + }, + } + fabridData := make([]byte, 16) + err = fopt.SerializeTo(fabridData) + assert.NoError(t, err) + hbh := slayers.HopByHopExtn{ + Options: []*slayers.HopByHopOption{ + { + OptType: slayers.OptTypeIdentifier, + OptData: identifierData, + OptDataLen: uint8(len(identifierData)), + }, + { + OptType: slayers.OptTypeFabrid, + OptData: fabridData, + OptDataLen: uint8(len(fabridData)), + }, + }, + } + err = gopacket.SerializeLayers(buf, + gopacket.SerializeOptions{FixLengths: true}, &s, &hbh) + assert.NoError(t, err) + raw := buf.Bytes() + copy(m[0].Buffers[0], raw) + m[0].N = len(raw) + m[0].Addr = &net.UDPAddr{IP: net.IP{10, 0, 200, 200}} + + return 1, nil + }, + ).Times(1) + mExternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). + AnyTimes() + + mInternal := mock_router.NewMockBatchConn(ctrl) + mInternal.EXPECT().ReadBatch(gomock.Any()).Return(0, nil).AnyTimes() + mInternal.EXPECT().WriteBatch(gomock.Any(), 0).DoAndReturn( + func(ms underlayconn.Messages, flags int) (int, error) { + if len(ms) != 1 { + assert.Fail(t, "len(ms)!=1", len(ms)) + return 0, nil + } + s := slayers.SCION{} + hbh := slayers.HopByHopExtn{} + _, err := router.DecodeLayers(ms[0].Buffers[0], &s, &hbh) + assert.NoError(t, err) + + containsFabrid := false + containsIdentifier := false + var foundIdentifier *extension.IdentifierOption + var foundFabrid *extension.FabridOption + + baseTs := infoField.Timestamp + for _, hbhOption := range hbh.Options { + switch hbhOption.OptType { + case slayers.OptTypeIdentifier: + containsIdentifier = true + foundIdentifier, err = extension.ParseIdentifierOption(hbhOption, + baseTs) + assert.NoError(t, err) + assert.Equal(t, identifier.Timestamp, foundIdentifier.Timestamp) + assert.Equal(t, identifier.PacketID, foundIdentifier.PacketID) + case slayers.OptTypeFabrid: + containsFabrid = true + if containsIdentifier { + foundFabrid, err = extension.ParseFabridOptionFullExtension( + hbhOption, 3) + assert.NoError(t, err) + meta := foundFabrid.HopfieldMetadata[2] + tmp := make([]byte, 100) + recomputedVerifiedHVF := &extension.FabridHopfieldMetadata{ + EncryptedPolicyID: encPolicyID, + FabridEnabled: true, + } + err = crypto.ComputeVerifiedHVF(recomputedVerifiedHVF, + foundIdentifier, &s, tmp, asToHostKey[:], + 3, 0) + assert.NoError(t, err) + assert.Equal(t, encPolicyID, meta.EncryptedPolicyID) + assert.Equal(t, recomputedVerifiedHVF.HopValidationField, + meta.HopValidationField) + } else { + assert.Fail(t, + "identifier not present before fabrid") + } + default: + } + } + assert.True(t, containsIdentifier) + assert.True(t, containsFabrid) + + done <- struct{}{} + return 1, nil + }).Times(1) + _ = ret.AddInternalInterface(mInternal, netip.Addr{}) + + l := control.LinkEnd{ + IA: local, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.100")}, + } + r1 := control.LinkEnd{ + IA: srcIA, + Addr: &net.UDPAddr{IP: net.ParseIP("10.0.0.200")}, + } + nobfd := control.BFD{Disable: ptr.To(true)} + + _ = ret.AddExternalInterface(3, mExternal, l, r1, nobfd) + _ = ret.AddLinkType(3, topology.Core) + + _ = ret.SetIA(local) + _ = ret.SetKey(key) + + nextHopAddr := xtest.MustParseUDPAddr(t, "127.0.0.2:8888") + err = ret.AddNextHop(2, l.Addr, nextHopAddr, nobfd, "") + assert.NoError(t, err) + err = ret.AddLinkType(2, topology.Core) + assert.NoError(t, err) + return ret + }, + }, "route 10 msg from external to internal": { prepareDP: func(ctrl *gomock.Controller, done chan<- struct{}) *router.DataPlane { ret := &router.DataPlane{Metrics: metrics} @@ -384,7 +1071,8 @@ func TestDataPlaneRun(t *testing.T) { return 0, fmt.Errorf("no valid BFD message") }).MinTimes(1) - mInternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() + mInternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). + AnyTimes() local := &net.UDPAddr{IP: net.ParseIP("10.0.200.100").To4()} _ = ret.SetKey([]byte("randomkeyformacs")) @@ -484,7 +1172,8 @@ func TestDataPlaneRun(t *testing.T) { done <- struct{}{} return 1, nil }).MinTimes(1) - mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). + AnyTimes() local := control.LinkEnd{ IA: xtest.MustParseIA("1-ff00:0:1"), @@ -562,7 +1251,8 @@ func TestDataPlaneRun(t *testing.T) { } return 0, fmt.Errorf("no valid BFD message") }).MinTimes(1) - mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). + AnyTimes() local := control.LinkEnd{ IA: xtest.MustParseIA("1-ff00:0:1"), diff --git a/router/export_test.go b/router/export_test.go index 96faeed914..646192ec3d 100644 --- a/router/export_test.go +++ b/router/export_test.go @@ -19,6 +19,7 @@ import ( "net" "net/netip" + "github.com/google/gopacket" "golang.org/x/net/ipv4" "github.com/scionproto/scion/pkg/addr" @@ -94,3 +95,8 @@ func (d *DataPlane) ProcessPkt(ifID uint16, m *ipv4.Message) (ProcessResult, err func ExtractServices(s *services) map[addr.SVC][]*net.UDPAddr { return s.m } + +func DecodeLayers(data []byte, base gopacket.DecodingLayer, + opts ...gopacket.DecodingLayer) (gopacket.DecodingLayer, error) { + return decodeLayers(data, base, opts...) +} diff --git a/router/mock_router/mock.go b/router/mock_router/mock.go index 06993e27c8..923505da3c 100644 --- a/router/mock_router/mock.go +++ b/router/mock_router/mock.go @@ -64,6 +64,20 @@ func (mr *MockBatchConnMockRecorder) ReadBatch(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadBatch", reflect.TypeOf((*MockBatchConn)(nil).ReadBatch), arg0) } +// SetToS mocks base method. +func (m *MockBatchConn) SetToS(arg0 byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetToS", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetToS indicates an expected call of SetToS. +func (mr *MockBatchConnMockRecorder) SetToS(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetToS", reflect.TypeOf((*MockBatchConn)(nil).SetToS), arg0) +} + // WriteBatch mocks base method. func (m *MockBatchConn) WriteBatch(arg0 conn.Messages, arg1 int) (int, error) { m.ctrl.T.Helper() diff --git a/tools/topology/go.py b/tools/topology/go.py index 266c7bd0ca..10cf6e63b9 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -91,8 +91,13 @@ def _build_br_conf(self, topo_id, ia, base, name, v): 'features': translate_features(self.args.features), 'api': { 'addr': prom_addr(v['internal_addr'], DEFAULT_BR_PROM_PORT+700) - } + }, } + if self.args.fabrid: + raw_entry['router'] = { + 'drkey': ["FABRID"], + 'fabrid': True, + } return raw_entry def generate_control_service(self): @@ -135,6 +140,22 @@ def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): 'enabled': True, 'path': fabrid_path, } + + borderRouterInternalIPs = [] + for _, v in self.args.topo_dicts[topo_id].get("border_routers", {}).items(): + borderRouterInternalIPs.append(v['internal_addr'].rsplit(':', 1)[0].strip('[]')) + raw_entry['drkey'] = { + 'level1_db': { + 'connection': os.path.join(self.db_dir, '%s.drkey-level1.db' % name), + }, + 'secret_value_db': { + 'connection': os.path.join(self.db_dir, '%s.drkey-secret.db' % name), + }, + 'delegation': { + 'FABRID': borderRouterInternalIPs, + } + } + if ca: raw_entry['ca'] = {'mode': 'in-process'} return raw_entry From 174bc03349c06bebcc386adc9ff0d84107c8f6d1 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Thu, 25 Jul 2024 13:58:49 +0200 Subject: [PATCH 13/26] FABRID ping and end2end - ping: select fabrid policies with --fabridquery flag - end2end: run integration test with --fabrid to test path validation --- doc/command/scion/scion_ping.rst | 2 + docker/BUILD.bazel | 4 + docker/endhost.bzl | 79 +++++++++ docker/files/endhost.sh | 18 ++ scion/cmd/scion/ping.go | 98 ++++++++--- tools/end2end/BUILD.bazel | 6 + tools/end2end/main.go | 269 ++++++++++++++++++++++++++++-- tools/end2end_integration/main.go | 28 +++- tools/integration/binary.go | 18 ++ tools/integration/docker.go | 46 +++++ tools/integration/integration.go | 37 +++- tools/topogen.py | 3 + tools/topology/common.py | 16 +- tools/topology/config.py | 20 ++- tools/topology/docker_utils.py | 36 ++++ tools/topology/go.py | 41 +++++ tools/topology/topo.py | 6 + tools/wireshark/scion.lua | 58 +++++++ 18 files changed, 728 insertions(+), 57 deletions(-) create mode 100644 docker/endhost.bzl create mode 100644 docker/files/endhost.sh diff --git a/doc/command/scion/scion_ping.rst b/doc/command/scion/scion_ping.rst index 313d8b24cc..2c8050d044 100644 --- a/doc/command/scion/scion_ping.rst +++ b/doc/command/scion/scion_ping.rst @@ -88,6 +88,8 @@ Options -c, --count uint16 total number of packets to send --epic Enable EPIC for path probing. + --fabridquery string the query for policies that the path must adhere to + --fetch-detached Fetch FABRID maps for hops where they have been detached. This increases the overhead of path finding. (default true) --format string Specify the output format (human|json|yaml) (default "human") --healthy-only only use healthy paths -h, --help help for ping diff --git a/docker/BUILD.bazel b/docker/BUILD.bazel index ec356b2378..ed6d2c6ff9 100644 --- a/docker/BUILD.bazel +++ b/docker/BUILD.bazel @@ -1,6 +1,7 @@ load("@rules_debian_packages//debian_packages:defs.bzl", "debian_packages_lockfile") load(":scion_app.bzl", "scion_app_base", "scion_app_image") load(":tester.bzl", "scion_tester_image") +load(":endhost.bzl", "scion_endhost_image") load(":labels.bzl", "scion_labels") filegroup( @@ -17,6 +18,7 @@ filegroup( filegroup( name = "test", srcs = [ + ":endhost.tar", ":tester.tar", ], ) @@ -94,3 +96,5 @@ debian_packages_lockfile( ) scion_tester_image() + +scion_endhost_image() diff --git a/docker/endhost.bzl b/docker/endhost.bzl new file mode 100644 index 0000000000..3604af4ee7 --- /dev/null +++ b/docker/endhost.bzl @@ -0,0 +1,79 @@ +load("@aspect_bazel_lib//lib:copy_file.bzl", "copy_file") +load("@rules_oci//oci:defs.bzl", "oci_image", "oci_tarball") +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") +load("@tester_debian10_packages//:packages.bzl", "debian_package_layer") + +def scion_endhost_image(): + pkg_tar( + name = "endhost_layer_packages", + deps = [ + debian_package_layer("bridge-utils"), + debian_package_layer("iperf3"), + debian_package_layer("iptables"), + debian_package_layer("netcat-openbsd"), + debian_package_layer("openssh-server"), + debian_package_layer("openssh-client"), + debian_package_layer("procps"), + debian_package_layer("telnet"), + debian_package_layer("tshark"), + debian_package_layer("wget"), + ], + ) + + pkg_tar( + name = "endhost_layer_bin", + srcs = [ + "//tools/end2end:end2end", + "//scion/cmd/scion", + "//scion-pki/cmd/scion-pki:scion-pki", + "//daemon/cmd/daemon", + ], + package_dir = "share/bin", + ) + + pkg_tar( + name = "endhost_layer_tools_integration", + srcs = [ + "//tools/integration:bin_wrapper.sh", + ], + package_dir = "share/tools/integration", + ) + + pkg_tar( + name = "endhost_layer_share", + srcs = native.glob(["files/*"]), + package_dir = "share", + ) + + oci_image( + name = "endhost", + base = "@debian10", + env = { + "TZ": "UTC", + "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/share/bin", + }, + workdir = "/share", + cmd = ["tail", "-f", "/dev/null"], + tars = [ + ":endhost_layer_packages", + ":endhost_layer_share", + ":endhost_layer_tools_integration", + ":endhost_layer_bin", + ], + labels = ":labels", + visibility = ["//visibility:public"], + ) + oci_tarball( + name = "endhost.load", + format = "docker", + image = "endhost", + repo_tags = ["scion/endhost:latest"], + ) + + # see comment on scion_app.bzl + copy_file( + name = "endhost.tarball", + src = "endhost.load", + out = "endhost.tar", + visibility = ["//visibility:public"], + ) diff --git a/docker/files/endhost.sh b/docker/files/endhost.sh new file mode 100644 index 0000000000..33aef7a5df --- /dev/null +++ b/docker/files/endhost.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +term() { + exit 0 +} + +trap term TERM + +/share/bin/daemon --config /etc/scion/endhost.toml & + +echo "Endhost started" + +# Wake up from sleep once in a while so that SIGTERM is handled. +while : +do + sleep 0.1 +done diff --git a/scion/cmd/scion/ping.go b/scion/cmd/scion/ping.go index d5a7ec3bf1..f74b2f75cb 100644 --- a/scion/cmd/scion/ping.go +++ b/scion/cmd/scion/ping.go @@ -70,22 +70,24 @@ type PingUpdate struct { func newPing(pather CommandPather) *cobra.Command { var envFlags flag.SCIONEnvironment var flags struct { - count uint16 - features []string - interactive bool - interval time.Duration - logLevel string - maxMTU bool - noColor bool - refresh bool - healthyOnly bool - sequence string - size uint - pktSize uint - timeout time.Duration - tracer string - epic bool - format string + count uint16 + features []string + interactive bool + interval time.Duration + logLevel string + maxMTU bool + noColor bool + refresh bool + healthyOnly bool + sequence string + size uint + pktSize uint + timeout time.Duration + tracer string + epic bool + format string + fabridQuery string + fetchDetached bool } var cmd = &cobra.Command{ @@ -168,16 +170,44 @@ On other errors, ping will exit with code 2. LocalIP: localIP, })) } - path, err := path.Choose(traceCtx, sd, remote.IA, opts...) + if flags.fabridQuery != "" { + cfg := snetpath.FabridConfig{ + LocalIA: info.IA, + LocalAddr: localIP.String(), + DestinationIA: remote.IA, + DestinationAddr: remote.Host.IP.String(), + } + if localIP == nil { + daemonIPString, _, err := net.SplitHostPort(daemonAddr) + if err != nil { + return err + } + daemonIP, err := net.ResolveIPAddr("ip", daemonIPString) + if err != nil { + return serrors.New("resolving daemon ip", "daemonIP", daemonIPString) + } + localIP = daemonIP.IP + cfg.LocalAddr = daemonIPString + } + opts = append(opts, path.WithFABRID(&path.FABRIDQuery{ + Query: flags.fabridQuery, + FabridConfig: cfg, + })) + opts = append(opts, path.WithFetchDetachedFabridMaps(flags.fetchDetached)) + } + cs := path.DefaultColorScheme(false) + pingPath, err := path.Choose(traceCtx, sd, remote.IA, opts...) + if err != nil { return err } + fmt.Println(cs.Path(pingPath)) // If the EPIC flag is set, use the EPIC-HP path type if flags.epic { - switch s := path.Dataplane().(type) { + switch s := pingPath.Dataplane().(type) { case snetpath.SCION: - epicPath, err := snetpath.NewEPICDataplanePath(s, path.Metadata().EpicAuths) + epicPath, err := snetpath.NewEPICDataplanePath(s, pingPath.Metadata().EpicAuths) if err != nil { return err } @@ -187,10 +217,19 @@ On other errors, ping will exit with code 2. default: return serrors.New("unsupported path type") } + } else if flags.fabridQuery != "" { + switch s := pingPath.Dataplane().(type) { + case *snetpath.FABRID: + remote.Path = s + s.RegisterDRKeyFetcher(sd.FabridKeys) + + default: + return serrors.New("unsupported path type") + } } else { - remote.Path = path.Dataplane() + remote.Path = pingPath.Dataplane() } - remote.NextHop = path.UnderlayNextHop() + remote.NextHop = pingPath.UnderlayNextHop() // Resolve local IP based on underlay next hop if localIP == nil { @@ -204,7 +243,7 @@ On other errors, ping will exit with code 2. } printf("Resolved local address:\n %s\n", localIP) } - printf("Using path:\n %s\n\n", path) + printf("Using path:\n %s\n\n", pingPath) span.SetTag("src.host", localIP) local := &snet.UDPAddr{ IA: info.IA, @@ -225,7 +264,7 @@ On other errors, ping will exit with code 2. pldSize = int(flags.pktSize - uint(overhead)) } if flags.maxMTU { - mtu := int(path.Metadata().MTU) + mtu := int(pingPath.Metadata().MTU) pldSize, err = calcMaxPldSize(local, remote, mtu) if err != nil { return err @@ -244,18 +283,18 @@ On other errors, ping will exit with code 2. count = math.MaxUint16 } - seq, err := pathpol.GetSequence(path) + seq, err := pathpol.GetSequence(pingPath) if err != nil { return serrors.New("get sequence from used path") } res := Result{ ScionPacketSize: pktSize, Path: Path{ - Fingerprint: snet.Fingerprint(path).String(), - Hops: getHops(path), + Fingerprint: snet.Fingerprint(pingPath).String(), + Hops: getHops(pingPath), Sequence: seq, LocalIP: localIP, - NextHop: path.UnderlayNextHop().String(), + NextHop: pingPath.UnderlayNextHop().String(), }, PayloadSize: pldSize, } @@ -336,6 +375,8 @@ On other errors, ping will exit with code 2. cmd.Flags().BoolVar(&flags.noColor, "no-color", false, "disable colored output") cmd.Flags().DurationVar(&flags.timeout, "timeout", time.Second, "timeout per packet") cmd.Flags().StringVar(&flags.sequence, "sequence", "", app.SequenceUsage) + cmd.Flags().StringVar(&flags.fabridQuery, "fabridquery", "", "the query for policies that the "+ + "path must adhere to") cmd.Flags().BoolVar(&flags.healthyOnly, "healthy-only", false, "only use healthy paths") cmd.Flags().BoolVar(&flags.refresh, "refresh", false, "set refresh flag for path request") cmd.Flags().DurationVar(&flags.interval, "interval", time.Second, "time between packets") @@ -357,6 +398,9 @@ SCMP echo header and payload are equal to the MTU of the path. This flag overrid cmd.Flags().StringVar(&flags.logLevel, "log.level", "", app.LogLevelUsage) cmd.Flags().StringVar(&flags.tracer, "tracing.agent", "", "Tracing agent address") cmd.Flags().BoolVar(&flags.epic, "epic", false, "Enable EPIC for path probing.") + cmd.Flags().BoolVar(&flags.fetchDetached, "fetch-detached", true, + "Fetch FABRID maps for hops where they have been detached. "+ + "This increases the overhead of path finding.") cmd.Flags().StringVar(&flags.format, "format", "human", "Specify the output format (human|json|yaml)") return cmd diff --git a/tools/end2end/BUILD.bazel b/tools/end2end/BUILD.bazel index 6e44df874a..eabd6e2754 100644 --- a/tools/end2end/BUILD.bazel +++ b/tools/end2end/BUILD.bazel @@ -9,10 +9,16 @@ go_library( deps = [ "//pkg/addr:go_default_library", "//pkg/daemon:go_default_library", + "//pkg/drkey:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/experimental/fabrid/crypto:go_default_library", "//pkg/log:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/serrors:go_default_library", "//pkg/private/util:go_default_library", + "//pkg/slayers:go_default_library", + "//pkg/slayers/extension:go_default_library", + "//pkg/slayers/path/scion:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/metrics:go_default_library", "//pkg/snet/path:go_default_library", diff --git a/tools/end2end/main.go b/tools/end2end/main.go index d16578140d..654d5c319d 100644 --- a/tools/end2end/main.go +++ b/tools/end2end/main.go @@ -37,10 +37,16 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" + "github.com/scionproto/scion/pkg/drkey" + libfabrid "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" + "github.com/scionproto/scion/pkg/slayers/path/scion" "github.com/scionproto/scion/pkg/snet" "github.com/scionproto/scion/pkg/snet/metrics" snetpath "github.com/scionproto/scion/pkg/snet/path" @@ -73,6 +79,7 @@ var ( scionPacketConnMetrics = metrics.NewSCIONPacketConnMetrics() scmpErrorsCounter = scionPacketConnMetrics.SCMPErrors epic bool + fabrid bool ) func main() { @@ -109,6 +116,7 @@ func addFlags() { flag.Var(&remote, "remote", "(Mandatory for clients) address to connect to") flag.Var(timeout, "timeout", "The timeout for each attempt") flag.BoolVar(&epic, "epic", false, "Enable EPIC") + flag.BoolVar(&fabrid, "fabrid", false, "Enable FABRID") } func validateFlags() { @@ -123,7 +131,10 @@ func validateFlags() { integration.LogFatal("Invalid timeout provided", "timeout", timeout) } } - log.Info("Flags", "timeout", timeout, "epic", epic, "remote", remote) + if epic && fabrid { + integration.LogFatal("FABRID is incompatible with EPIC") + } + log.Info("Flags", "timeout", timeout, "epic", epic, "fabrid", fabrid, "remote", remote) } type server struct{} @@ -142,22 +153,44 @@ func (s server) run() { PacketConnMetrics: scionPacketConnMetrics, Topology: sdConn, } - conn, err := sn.Listen(context.Background(), "udp", integration.Local.Host) - if err != nil { - integration.LogFatal("Error listening", "err", err) - } - defer conn.Close() - localAddr := conn.LocalAddr().(*snet.UDPAddr) - if len(os.Getenv(libint.GoIntegrationEnv)) > 0 { - // Needed for integration test ready signal. - fmt.Printf("Port=%d\n", localAddr.Host.Port) - fmt.Printf("%s%s\n\n", libint.ReadySignal, integration.Local.IA) - } - log.Info("Listening", "local", fmt.Sprintf("%v:%d", localAddr.Host.IP, localAddr.Host.Port)) - // Receive ping message - for { - if err := s.handlePing(conn); err != nil { - log.Error("Error handling ping", "err", err) + if fabrid { + conn, err := sn.OpenRaw(context.Background(), integration.Local.Host) + if err != nil { + integration.LogFatal("Error listening", "err", err) + } + defer conn.Close() + localAddr := conn.LocalAddr().(*net.UDPAddr) + if len(os.Getenv(libint.GoIntegrationEnv)) > 0 { + // Needed for integration test ready signal. + fmt.Printf("Port=%d\n", localAddr.Port) + fmt.Printf("%s%s\n\n", libint.ReadySignal, integration.Local.IA) + } + log.Info("Listening", "local", + fmt.Sprintf("%v:%d", integration.Local.Host.IP, localAddr.Port)) + // Receive ping message + for { + if err := s.handlePingFabrid(conn); err != nil { + log.Error("Error handling ping", "err", err) + } + } + } else { + conn, err := sn.Listen(context.Background(), "udp", integration.Local.Host) + if err != nil { + integration.LogFatal("Error listening", "err", err) + } + defer conn.Close() + localAddr := conn.LocalAddr().(*snet.UDPAddr) + if len(os.Getenv(libint.GoIntegrationEnv)) > 0 { + // Needed for integration test ready signal. + fmt.Printf("Port=%d\n", localAddr.Host.Port) + fmt.Printf("%s%s\n\n", libint.ReadySignal, integration.Local.IA) + } + log.Info("Listening", "local", fmt.Sprintf("%v:%d", localAddr.Host.IP, localAddr.Host.Port)) + // Receive ping message + for { + if err := s.handlePing(conn); err != nil { + log.Error("Error handling ping", "err", err) + } } } } @@ -218,6 +251,158 @@ func (s server) handlePing(conn *snet.Conn) error { return nil } +func (s server) handlePingFabrid(conn snet.PacketConn) error { + var p snet.Packet + var ov net.UDPAddr + err := readFromFabrid(conn, &p, &ov) + if err != nil { + return serrors.WrapStr("reading packet", err) + } + + // If the packet is from remote IA, validate the FABRID path + if p.Source.IA != integration.Local.IA { + if p.HbhExtension == nil { + return serrors.New("Missing HBH extension") + } + + // Check extensions for relevant options + var identifierOption *extension.IdentifierOption + var fabridOption *extension.FabridOption + var err error + + for _, opt := range p.HbhExtension.Options { + switch opt.OptType { + case slayers.OptTypeIdentifier: + decoded := scion.Decoded{} + err = decoded.DecodeFromBytes(p.Path.(snet.RawPath).Raw) + if err != nil { + return err + } + baseTimestamp := decoded.InfoFields[0].Timestamp + identifierOption, err = extension.ParseIdentifierOption(opt, baseTimestamp) + if err != nil { + return err + } + case slayers.OptTypeFabrid: + fabridOption, err = extension.ParseFabridOptionFullExtension(opt, + (opt.OptDataLen-4)/4) + if err != nil { + return err + } + } + } + + if identifierOption == nil { + return serrors.New("Missing identifier option") + } + + if fabridOption == nil { + return serrors.New("Missing FABRID option") + } + + meta := drkey.HostHostMeta{ + Validity: identifierOption.Timestamp, + SrcIA: integration.Local.IA, + SrcHost: integration.Local.Host.IP.String(), + DstIA: p.Source.IA, + DstHost: p.Source.Host.IP().String(), + ProtoId: drkey.FABRID, + } + hostHostKey, err := integration.SDConn().DRKeyGetHostHostKey(context.Background(), meta) + if err != nil { + return serrors.WrapStr("getting host key", err) + } + + tmpBuffer := make([]byte, (len(fabridOption.HopfieldMetadata)*3+15)&^15+16) + _, err = crypto.VerifyPathValidator(fabridOption, tmpBuffer, hostHostKey.Key[:]) + if err != nil { + return err + } + } + + udp, ok := p.Payload.(snet.UDPPayload) + if !ok { + return serrors.New("unexpected payload received", + "source", p.Source, + "destination", p.Destination, + "type", common.TypeOf(p.Payload), + ) + } + var pld Ping + if err := json.Unmarshal(udp.Payload, &pld); err != nil { + return serrors.New("invalid payload contents", + "source", p.Source, + "destination", p.Destination, + "data", string(udp.Payload), + ) + } + + spanCtx, err := opentracing.GlobalTracer().Extract( + opentracing.Binary, + bytes.NewReader(pld.Trace), + ) + if err != nil { + return serrors.WrapStr("extracting trace information", err) + } + span, _ := opentracing.StartSpanFromContext( + context.Background(), + "handle_ping", + ext.RPCServerOption(spanCtx), + ) + defer span.Finish() + withTag := func(err error) error { + tracing.Error(span, err) + return err + } + + if pld.Message != ping || !pld.Server.Equal(integration.Local.IA) { + return withTag(serrors.New("unexpected data in payload", + "source", p.Source, + "destination", p.Destination, + "data", pld, + )) + } + log.Info(fmt.Sprintf("Ping received from %s, sending pong.", p.Source)) + raw, err := json.Marshal(Pong{ + Client: p.Source.IA, + Server: integration.Local.IA, + Message: pong, + Trace: pld.Trace, + }) + if err != nil { + return withTag(serrors.WrapStr("packing pong", err)) + } + + p.Destination, p.Source = p.Source, p.Destination + p.Payload = snet.UDPPayload{ + DstPort: udp.SrcPort, + SrcPort: udp.DstPort, + Payload: raw, + } + + // Remove header extension for reverse path + p.HbhExtension = nil + p.E2eExtension = nil + + // reverse path + rpath, ok := p.Path.(snet.RawPath) + if !ok { + return serrors.New("unexpected path", "type", common.TypeOf(p.Path)) + } + replypather := snet.DefaultReplyPather{} + replyPath, err := replypather.ReplyPath(rpath) + if err != nil { + return serrors.WrapStr("creating reply path", err) + } + p.Path = replyPath + // Send pong + if err := conn.WriteTo(&p, &ov); err != nil { + return withTag(serrors.WrapStr("sending reply", err)) + } + log.Info("Sent pong to", "client", p.Destination) + return nil +} + type client struct { network *snet.SCIONNetwork conn *snet.Conn @@ -368,6 +553,43 @@ func (c *client) getRemote(ctx context.Context, n int) (snet.Path, error) { return nil, err } remote.Path = epicPath + } else if fabrid { + // If the fabrid flag is set, try to create FABRID dataplane path. + if len(path.Metadata().FabridInfo) > 0 { + // Check if fabrid info is available, otherwise the source + // AS does not support fabrid + + scionPath, ok := path.Dataplane().(snetpath.SCION) + if !ok { + return nil, serrors.New("provided path must be of type scion") + } + fabridConfig := &snetpath.FabridConfig{ + LocalIA: integration.Local.IA, + LocalAddr: integration.Local.Host.IP.String(), + DestinationIA: remote.IA, + DestinationAddr: remote.Host.IP.String(), + } + hops := path.Metadata().Hops() + log.Info("Fabrid path", "path", path, "hops", hops) + // Use ZERO policy for all hops with fabrid, to just do path validation + policies := make([]*libfabrid.PolicyID, len(hops)) + zeroPol := libfabrid.PolicyID(0) + for i, hop := range hops { + if hop.FabridEnabled { + policies[i] = &zeroPol + } + } + fabridPath, err := snetpath.NewFABRIDDataplanePath(scionPath, hops, + policies, fabridConfig) + if err != nil { + return nil, serrors.New("Error creating FABRID path", "err", err) + } + remote.Path = fabridPath + fabridPath.RegisterDRKeyFetcher(c.sdConn.FabridKeys) + } else { + log.Info("FABRID flag was set for client in non-FABRID AS. Proceeding without FABRID.") + remote.Path = path.Dataplane() + } } else { remote.Path = path.Dataplane() } @@ -422,3 +644,16 @@ func readFrom(conn *snet.Conn, pld []byte) (int, net.Addr, error) { "interface", opErr.RevInfo().IfID, ) } + +func readFromFabrid(conn snet.PacketConn, pkt *snet.Packet, ov *net.UDPAddr) error { + err := conn.ReadFrom(pkt, ov) + // Attach more context to error + var opErr *snet.OpError + if !(errors.As(err, &opErr) && opErr.RevInfo() != nil) { + return err + } + return serrors.WithCtx(err, + "isd_as", opErr.RevInfo().IA(), + "interface", opErr.RevInfo().IfID, + ) +} diff --git a/tools/end2end_integration/main.go b/tools/end2end_integration/main.go index 5b4ff4cdf2..61540cfe20 100644 --- a/tools/end2end_integration/main.go +++ b/tools/end2end_integration/main.go @@ -44,6 +44,7 @@ var ( cmd string features string epic bool + fabrid bool ) func getCmd() (string, bool) { @@ -76,10 +77,12 @@ func realMain() int { "-local", integration.SrcAddrPattern + ":0", "-remote", integration.DstAddrPattern + ":" + integration.ServerPortReplace, fmt.Sprintf("-epic=%t", epic), + fmt.Sprintf("-fabrid=%t", fabrid), } serverArgs := []string{ "-mode", "server", "-local", integration.DstAddrPattern + ":0", + fmt.Sprintf("-fabrid=%t", fabrid), } if len(features) != 0 { clientArgs = append(clientArgs, "--features", features) @@ -89,9 +92,19 @@ func realMain() int { clientArgs = append(clientArgs, "-sciond", integration.Daemon) serverArgs = append(serverArgs, "-sciond", integration.Daemon) } - - in := integration.NewBinaryIntegration(name, cmd, clientArgs, serverArgs) - pairs, err := getPairs() + var in integration.Integration + if fabrid { + in = integration.NewBinaryEndhostIntegration(name, cmd, clientArgs, serverArgs) + } else { + in = integration.NewBinaryIntegration(name, cmd, clientArgs, serverArgs) + } + var pairs []integration.IAPair + var err error + if fabrid { + pairs, err = getPairs(integration.SDAddr) + } else { + pairs, err = getPairs(integration.CSAddr) + } if err != nil { log.Error("Error selecting tests", "err", err) return 1 @@ -119,6 +132,7 @@ func addFlags() { flag.StringVar(&features, "features", "", fmt.Sprintf("enable development features (%v)", feature.String(&feature.Default{}, "|"))) flag.BoolVar(&epic, "epic", false, "Enable EPIC.") + flag.BoolVar(&fabrid, "fabrid", false, "Enable FABRID.") } // runTests runs the end2end tests for all pairs. In case of an error the @@ -245,6 +259,9 @@ func runTests(in integration.Integration, pairs []integration.IAPair) error { var tester string if *integration.Docker { tester = integration.TesterID(src) + if fabrid { + tester = integration.EndhostID(src) + } } logFile := fmt.Sprintf("%s/client_%s.log", logDir(), @@ -296,6 +313,7 @@ func clientTemplate(progressSock string) integration.Cmd { "-local", integration.SrcAddrPattern + ":0", "-remote", integration.DstAddrPattern + ":" + integration.ServerPortReplace, fmt.Sprintf("-epic=%t", epic), + fmt.Sprintf("-fabrid=%t", fabrid), }, } if len(features) != 0 { @@ -319,8 +337,8 @@ func clientTemplate(progressSock string) integration.Cmd { // This implies that IFF role1 == role2, then h1:h2 pairs are mirrored with h2:h1 and, unless // remote[ISD/AS] is specified, h2:h2 and h1:h1. Not all combinations yield something useful... // caveat emptor. -func getPairs() ([]integration.IAPair, error) { - pairs := integration.IAPairs(integration.CSAddr) +func getPairs(hostAddr integration.HostAddr) ([]integration.IAPair, error) { + pairs := integration.IAPairs(hostAddr) if subset == "all" { return pairs, nil } diff --git a/tools/integration/binary.go b/tools/integration/binary.go index 6d4d8d2cb0..fe05eb9a3b 100644 --- a/tools/integration/binary.go +++ b/tools/integration/binary.go @@ -104,6 +104,24 @@ func NewBinaryIntegration(name string, cmd string, clientArgs, serverArgs []stri return dockerize(bi) } +func NewBinaryEndhostIntegration(name string, cmd string, clientArgs, + serverArgs []string) Integration { + logDir := filepath.Join(LogDir(), name) + err := os.Mkdir(logDir, os.ModePerm) + if err != nil && !os.IsExist(err) { + log.Error("Failed to create log folder for testrun", "dir", name, "err", err) + return nil + } + bi := &binaryIntegration{ + name: name, + cmd: cmd, + clientArgs: clientArgs, + serverArgs: serverArgs, + logDir: logDir, + } + return dockerizeEndhost(bi) +} + func (bi *binaryIntegration) Name() string { return bi.name } diff --git a/tools/integration/docker.go b/tools/integration/docker.go index 0b26344a31..b6da97e50a 100644 --- a/tools/integration/docker.go +++ b/tools/integration/docker.go @@ -48,6 +48,10 @@ type dockerIntegration struct { *binaryIntegration } +type dockerizedEndhostIntegration struct { + *binaryIntegration +} + func dockerize(bi *binaryIntegration) Integration { if *Docker { return &dockerIntegration{ @@ -57,7 +61,40 @@ func dockerize(bi *binaryIntegration) Integration { return bi } +func dockerizeEndhost(bi *binaryIntegration) Integration { + if *Docker { + return &dockerizedEndhostIntegration{ + binaryIntegration: bi, + } + } + return bi +} + // StartServer starts a server and blocks until the ReadySignal is received on Stdout. +func (di *dockerizedEndhostIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, + error) { + bi := *di.binaryIntegration + bi.serverArgs = append(dockerArgs, + append([]string{EndhostID(dst), bi.cmd}, bi.serverArgs...)...) + bi.cmd = dockerCmd + log.Debug(fmt.Sprintf("Starting server for %s in a docker container", + addr.FormatIA(dst.IA, addr.WithFileSeparator())), + ) + return bi.StartServer(ctx, dst) +} + +func (di *dockerizedEndhostIntegration) StartClient(ctx context.Context, + src, dst *snet.UDPAddr) (*BinaryWaiter, error) { + bi := *di.binaryIntegration + bi.clientArgs = append(dockerArgs, + append([]string{EndhostID(src), bi.cmd}, bi.clientArgs...)...) + bi.cmd = dockerCmd + log.Debug(fmt.Sprintf("Starting client for %s in a docker container", + addr.FormatIA(src.IA, addr.WithFileSeparator())), + ) + return bi.StartClient(ctx, src, dst) +} + func (di *dockerIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, error) { bi := *di.binaryIntegration bi.serverArgs = append(dockerArgs, append([]string{TesterID(dst), bi.cmd}, bi.serverArgs...)...) @@ -88,3 +125,12 @@ func TesterID(a *snet.UDPAddr) string { } return envID } + +func EndhostID(a *snet.UDPAddr) string { + ia := addr.FormatIA(a.IA, addr.WithFileSeparator()) + envID, ok := os.LookupEnv(fmt.Sprintf("endhost_%s", strings.Replace(ia, "-", "_", -1))) + if !ok { + return fmt.Sprintf("endhost_%s", ia) + } + return envID +} diff --git a/tools/integration/integration.go b/tools/integration/integration.go index 518bef3de7..11a18a6be2 100644 --- a/tools/integration/integration.go +++ b/tools/integration/integration.go @@ -218,7 +218,8 @@ func generateAllSrcDst(hostAddr HostAddr, unique bool) []IAPair { type HostAddr func(ia addr.IA) *snet.UDPAddr -// CSAddr reads the CS host Addr from the topology for the specified IA. +// CSAddr reads the tester host Addr from the topology for the specified IA. +// If the address cannot be found, the CS address is returned. var CSAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { if a := loadAddr(ia); a != nil { return a @@ -245,6 +246,40 @@ var CSAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress} } +// SDAddr reads the endhost (dockerized) or scion daemon (normal) host Addr from the topology +// for the specified IA. If the address cannot be found, the CS address is returned. +var SDAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { + if a := loadAddr(ia); a != nil { + return a + } + var name string + if *Docker { + name = "endhost_" + } else { + name = "sd" + } + if raw, err := os.ReadFile(GenFile("networks.conf")); err == nil { + pattern := fmt.Sprintf("%s%s = (.*)", name, addr.FormatIA(ia, addr.WithFileSeparator())) + matches := regexp.MustCompile(pattern).FindSubmatch(raw) + if len(matches) == 2 { + return &snet.UDPAddr{IA: ia, Host: &net.UDPAddr{IP: net.ParseIP(string(matches[1]))}} + } + } + path := GenFile( + filepath.Join( + addr.FormatAS(ia.AS(), addr.WithDefaultPrefix(), addr.WithFileSeparator()), + "topology.json", + ), + ) + topo, err := topology.RWTopologyFromJSONFile(path) + if err != nil { + log.Error("Error loading topology", "err", err) + os.Exit(1) + } + cs := topo.CS["cs"+addr.FormatIA(ia, addr.WithFileSeparator())+"-1"] + return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress} +} + var addrs map[addr.IA]*snet.UDPAddr func initAddrs() { diff --git a/tools/topogen.py b/tools/topogen.py index 937fad04aa..403b74a293 100755 --- a/tools/topogen.py +++ b/tools/topogen.py @@ -53,6 +53,9 @@ def add_arguments(parser): to be built manually e.g. when running acceptance tests)') parser.add_argument('--fabrid', action='store_true', help='Enables FABRID and DRKey on all CSes, BRs and SDs') + parser.add_argument('--endhosts', action='store_true', + help='Generates an endhost per AS that contains a scion daemon.\ + Requires the daemon flag.') parser.add_argument('--features', help='Feature flags to enable, a comma separated list\ e.g. foo,bar enables foo and bar feature.') return parser diff --git a/tools/topology/common.py b/tools/topology/common.py index acdaa17b16..023e2f52b0 100644 --- a/tools/topology/common.py +++ b/tools/topology/common.py @@ -116,8 +116,8 @@ def join_host_port(host: str, port: int) -> str: return '[{}]:{}'.format(host, port) -def sciond_ip(docker, topo_id, networks: Mapping[IPNetwork, - NetworkDescription]): +def sciond_ip(docker, topo_id, + networks: Mapping[IPNetwork, NetworkDescription]): for net_desc in networks.values(): for prog, ip_net in net_desc.ip_net.items(): if prog == 'sd%s' % topo_id.file_fmt(): @@ -125,9 +125,17 @@ def sciond_ip(docker, topo_id, networks: Mapping[IPNetwork, return None +def endhost_ip(docker, topo_id, + networks: Mapping[IPNetwork, NetworkDescription]): + for net_desc in networks.values(): + for prog, ip_net in net_desc.ip_net.items(): + if prog == 'endhost_%s' % topo_id.file_fmt(): + return ip_net.ip + return None + + def prom_addr_dispatcher(docker, topo_id, - networks: Mapping[IPNetwork, - NetworkDescription], port, name): + networks: Mapping[IPNetwork, NetworkDescription], port, name): if not docker: return "[127.0.0.1]:%s" % port target_name = '' diff --git a/tools/topology/config.py b/tools/topology/config.py index b5af6a6960..b65a16417c 100644 --- a/tools/topology/config.py +++ b/tools/topology/config.py @@ -75,6 +75,13 @@ def __init__(self, args): if self.args.sig and not self.args.docker: logging.critical("Cannot use sig without docker!") sys.exit(1) + if self.args.endhosts and not self.args.docker: + logging.critical("Cannot generate endhosts without the docker flag!") + sys.exit(1) + if self.args.fabrid and self.args.docker and not self.args.endhosts: + logging.critical( + "Cannot generate dockerized fabrid topologies without the endhosts flag!") + sys.exit(1) self.default_mtu = None self._read_defaults() @@ -130,6 +137,8 @@ def _generate_go(self, topo_dicts): args = self._go_args(topo_dicts) go_gen = GoGenerator(args) go_gen.generate_br() + if self.args.endhosts: + go_gen.generate_endhost() go_gen.generate_sciond() go_gen.generate_control_service() go_gen.generate_disp() @@ -196,9 +205,14 @@ def _write_sciond_conf(self, networks: Mapping[IPNetwork, NetworkDescription], o d = dict() for net_desc in networks.values(): for prog, ip_net in net_desc.ip_net.items(): - if prog.startswith("sd"): - ia = prog[2:].replace("_", ":") - d[ia] = str(ip_net.ip) + if self.args.endhosts: + if prog.startswith("endhost_"): + ia = prog[8:].replace("_", ":") + d[ia] = str(ip_net.ip) + else: + if prog.startswith("sd"): + ia = prog[2:].replace("_", ":") + d[ia] = str(ip_net.ip) with open(os.path.join(self.args.output_dir, out_file), mode="w") as f: json.dump(d, f, sort_keys=True, indent=4) diff --git a/tools/topology/docker_utils.py b/tools/topology/docker_utils.py index 6bd9be0b21..ab2f4ba0a5 100644 --- a/tools/topology/docker_utils.py +++ b/tools/topology/docker_utils.py @@ -51,10 +51,46 @@ def __init__(self, args): def generate(self): for topo_id in self.args.topo_dicts: self._test_conf(topo_id) + if self.args.endhosts: + self._endhost_conf(topo_id) if self.args.sig: self._sig_testing_conf() return self.dc_conf + def _endhost_conf(self, topo_id): + cntr_base = '/share' + name = 'endhost_%s' % topo_id.file_fmt() + entry = { + 'image': docker_image(self.args, 'endhost'), + 'privileged': True, + 'entrypoint': 'sh endhost.sh', + 'environment': {}, + 'user': self.user, + 'volumes': [ + self.output_base + '/logs:' + cntr_base + '/logs:rw', + self.output_base + '/gen:' + cntr_base + '/gen:rw', + self.output_base + '/gen-certs:' + cntr_base + '/gen-certs:rw', + self.output_base + '/gen-cache:' + cntr_base + '/cache:rw', + self.output_base + '/gen/AS' + name.split('-')[1] + ":" + '/etc/scion:ro', + ], + } + net = self.args.networks[name][0] + ipv = 'ipv4' + if ipv not in net: + ipv = 'ipv6' + ip = str(net[ipv]) + entry['networks'] = {} + entry['networks'][self.args.bridges[net['net']]] = { + '%s_address' % ipv: ip + } + disp_net = self.args.networks[name][0] + entry['environment']['SCION_LOCAL_ADDR'] = str(disp_net[ipv]) + if ipv == 'ipv4': + entry['environment']['SCION_DAEMON'] = '%s:30255' % str(disp_net[ipv]) + else: + entry['environment']['SCION_DAEMON'] = '[%s]:30255' % str(disp_net[ipv]) + self.dc_conf['services'][name] = entry + def _test_conf(self, topo_id): cntr_base = '/share' name = 'tester_%s' % topo_id.file_fmt() diff --git a/tools/topology/go.py b/tools/topology/go.py index 10cf6e63b9..8b5b2964f9 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -30,6 +30,7 @@ prom_addr, prom_addr_dispatcher, sciond_ip, + endhost_ip, sciond_name, translate_features, SD_API_PORT, @@ -160,6 +161,46 @@ def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): raw_entry['ca'] = {'mode': 'in-process'} return raw_entry + def generate_endhost(self): + for topo_id, topo in self.args.topo_dicts.items(): + base = topo_id.base_dir(self.args.output_dir) + sciond_conf = self._build_endhost_sciond_conf(topo_id, topo["isd_as"], base) + write_file(os.path.join(base, "endhost.toml"), toml.dumps(sciond_conf)) + + def _build_endhost_sciond_conf(self, topo_id, ia, base): + name = 'endhost_%s' % topo_id.file_fmt() + config_dir = '/etc/scion' if self.args.docker else base + ip = endhost_ip(self.args.docker, topo_id, self.args.networks) + raw_entry = { + 'general': { + 'id': name, + 'config_dir': config_dir, + }, + 'log': self._log_entry(name), + 'trust_db': { + 'connection': os.path.join(self.db_dir, '%s.trust.db' % name), + }, + 'path_db': { + 'connection': os.path.join(self.db_dir, '%s.path.db' % name), + }, + 'sd': { + 'address': socket_address_str(ip, SD_API_PORT), + }, + 'tracing': self._tracing_entry(), + 'metrics': { + 'prometheus': socket_address_str(ip, SCIOND_PROM_PORT) + }, + 'features': translate_features(self.args.features), + 'api': { + 'addr': socket_address_str(ip, SD_API_PORT+700), + }, + } + if self.args.fabrid: + raw_entry['drkey_level2_db'] = { + 'connection': os.path.join(self.db_dir, '%s.drkey_level2.db' % name), + } + return raw_entry + def generate_sciond(self): for topo_id, topo in self.args.topo_dicts.items(): base = topo_id.base_dir(self.args.output_dir) diff --git a/tools/topology/topo.py b/tools/topology/topo.py index 9fb39e7ce0..bc16164676 100644 --- a/tools/topology/topo.py +++ b/tools/topology/topo.py @@ -145,6 +145,8 @@ def _register_addrs(self, topo_id, as_conf): self._register_br_entries(topo_id, as_conf) if self.args.sig: self._register_sig(topo_id, as_conf) + if self.args.endhosts: + self._register_endhost(topo_id, as_conf) self._register_sciond(topo_id, as_conf) def _register_srv_entries(self, topo_id, as_conf): @@ -179,6 +181,10 @@ def _register_sig(self, topo_id, as_conf): addr_type = addr_type_from_underlay(as_conf.get('underlay', DEFAULT_UNDERLAY)) self._reg_addr(topo_id, "sig" + topo_id.file_fmt(), addr_type) + def _register_endhost(self, topo_id, as_conf): + addr_type = addr_type_from_underlay(as_conf.get('underlay', DEFAULT_UNDERLAY)) + self._reg_addr(topo_id, "endhost_" + topo_id.file_fmt(), addr_type) + def _register_sciond(self, topo_id, as_conf): addr_type = addr_type_from_underlay(as_conf.get('underlay', DEFAULT_UNDERLAY)) self._reg_addr(topo_id, "sd" + topo_id.file_fmt(), addr_type) diff --git a/tools/wireshark/scion.lua b/tools/wireshark/scion.lua index 5ec622c68b..0acfa10d04 100644 --- a/tools/wireshark/scion.lua +++ b/tools/wireshark/scion.lua @@ -504,6 +504,8 @@ local scion_extn_tlv_option_types = { [0] = "Pad1", [1] = "PadN", [2] = "Packet Authenticator Option", + [3] = "Packet Identifier", + [4] = "Fabrid Extension", } local scion_extn_tlv_option_type = ProtoField.uint8("scion_extn_tlv_option.type", "Type", base.DEC, scion_extn_tlv_option_types) @@ -555,6 +557,8 @@ function scion_extn_tlv_option_dissect(tvbuf, pktinfo, root) local ret_len if tlv["type"]:uint() == 2 then ret_len = scion_packet_authenticator_option_dissect(tvbuf(2, data_len), pktinfo, tree) + elseif tlv["type"]:uint() == 4 then + ret_len = scion_fabrid_extension_dissect(tvbuf(2, data_len), pktinfo, tree) else -- no specific dissector ret_len = data_len @@ -736,6 +740,60 @@ function scion_packet_authenticator_option_dissect(buffer, pktinfo, tree) return length end +scion_fabrid_path_validation_field = Proto("scion_fabrid_path_validation_field", "Path Validation Field") +scion_fabrid_extension = Proto("scion_fabrid_extension", "Hop Validation Field") +scion_fabrid_extension_encrypted_policy_id = ProtoField.uint8("scion_fabrid_extension.encrypted_policy_id", "Encrypted Policy ID", base.HEX) +scion_fabrid_extension_enabled = ProtoField.uint8("scion_fabrid_extension.enabled", "FABRID Enabled", base.DEC, nil, 0x80) +scion_fabrid_extension_as_level_key = ProtoField.uint8("scion_fabrid_extension.as_level_key", "AS-Level key", base.DEC, nil, 0x40) +scion_fabrid_extension_hop_validation_field = ProtoField.uint32("scion_fabrid_extension.hop_validation_field", "Hop Validation Field", base.HEX) +scion_fabrid_path_validation_field_value = ProtoField.uint32("scion_fabrid_path_validation_field.value", "Value", base.HEX) +scion_fabrid_path_validation_field.fields = { + scion_fabrid_path_validation_field_value +} +scion_fabrid_extension.fields = { + scion_fabrid_extension_encrypted_policy_id, + scion_fabrid_extension_enabled, + scion_fabrid_extension_as_level_key, + scion_fabrid_extension_hop_validation_field +} +-- FABRID dissector +function scion_fabrid_extension_dissect(buffer, pktinfo, root) + local length = buffer:len() + if length < 4 then + root:add_proto_expert_info(e_too_short) + return -1 + end + + local offset = 0 + while offset < (buffer:len() - 4) + do + local len = scion_fabrid_hop_validation_dissect(buffer(offset, buffer:len()-offset), pktinfo, root) + if len <= 0 then + return -1 + end + offset = offset + len + end + local tree = root:add(scion_fabrid_path_validation_field, buffer(offset, 4)) + tree:add(scion_fabrid_path_validation_field_value, buffer(offset,4)) + return length +end + +function scion_fabrid_hop_validation_dissect(buffer, pktinfo, root) + local length = buffer:len() + if length < 4 then + tree:add_proto_expert_info(e_too_short) + return -1 + end + + local tree = root:add(scion_fabrid_extension, buffer(0, length)) + tree:add(scion_fabrid_extension_encrypted_policy_id, buffer(0,1)) + tree:add(scion_fabrid_extension_enabled, buffer(1,1)) + tree:add(scion_fabrid_extension_as_level_key, buffer(1,1)) + tree:add(scion_fabrid_extension_hop_validation_field, buffer(1,3)) + + return 4 +end + -- EPIC Path epic_path = Proto("epic_path", "EPIC Path") From b68263dbe32b9d92a8c07b3dfeeccb91eff1fc34 Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:02:21 +0200 Subject: [PATCH 14/26] resolved some router and fabrid crypto related PR comments --- .../fabrid/crypto/fabrid_crypto.go | 25 ++++++++----------- .../fabrid/crypto/fabrid_crypto_test.go | 10 +++----- router/config/config.go | 16 +++--------- router/control/drkey.go | 6 ++--- router/control/fetcher.go | 2 +- 5 files changed, 22 insertions(+), 37 deletions(-) diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto.go b/pkg/experimental/fabrid/crypto/fabrid_crypto.go index 614de736b9..aa8950c68d 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto.go @@ -179,7 +179,7 @@ func VerifyPathValidator(f *ext.FabridOption, tmpBuffer []byte, pathKey []byte) // path validator. func InitValidators(f *ext.FabridOption, id *ext.IdentifierOption, s *slayers.SCION, tmpBuffer []byte, pathKey *drkey.FabridKey, asHostKeys map[addr.IA]*drkey.FabridKey, - asAsKeys map[addr.IA]drkey.FabridKey, hops []snet.HopInterface) error { + asAsKeys map[addr.IA]*drkey.FabridKey, hops []snet.HopInterface) error { outBuffer := make([]byte, 16) var pathValInputLength int @@ -190,24 +190,19 @@ func InitValidators(f *ext.FabridOption, id *ext.IdentifierOption, s *slayers.SC } for i, meta := range f.HopfieldMetadata { if meta.FabridEnabled { - var key drkey.Key + var key *drkey.FabridKey + var found bool if meta.ASLevelKey { - asAsKey, found := asAsKeys[hops[i].IA] - if !found { - return serrors.New("InitValidators expected AS to AS key but was not in"+ - " dictionary", "AS", hops[i].IA) - } - key = asAsKey.Key + key, found = asAsKeys[hops[i].IA] } else { - asHostKey, found := asHostKeys[hops[i].IA] - if !found { - return serrors.New("InitValidators expected AS to AS key but was not in"+ - " dictionary", "AS", hops[i].IA) - } - key = asHostKey.Key + key, found = asHostKeys[hops[i].IA] + } + if !found { + return serrors.New("InitValidators expected AS to AS key but was not in"+ + " dictionary", "AS", hops[i].IA) } - err := computeFabridHVF(meta, id, s, tmpBuffer, outBuffer, key[:], + err := computeFabridHVF(meta, id, s, tmpBuffer, outBuffer, key.Key[:], uint16(hops[i].IgIf), uint16(hops[i].EgIf)) if err != nil { return err diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go index a40ad85e27..9722efd4a3 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go @@ -93,7 +93,7 @@ func TestFailedValidation(t *testing.T) { Key: drkey.Key{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, } asHostKeys := make(map[addr.IA]*drkey.FabridKey) - asAsKeys := make(map[addr.IA]drkey.FabridKey) + asAsKeys := make(map[addr.IA]*drkey.FabridKey) hops := make([]snet.HopInterface, len(f.HopfieldMetadata)) for i := 0; i < len(f.HopfieldMetadata); i++ { @@ -109,7 +109,7 @@ func TestFailedValidation(t *testing.T) { } keyBytes := drkey.Key{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1} if f.HopfieldMetadata[i].ASLevelKey { - asAsKeys[hops[i].IA] = drkey.FabridKey{Key: keyBytes} + asAsKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} } else { asHostKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} } @@ -227,10 +227,8 @@ func TestSuccessfullValidators(t *testing.T) { copy(keyBytes[:], generateRandomBytes(16)) pathKey := &drkey.FabridKey{Key: keyBytes} asHostKeys := make(map[addr.IA]*drkey.FabridKey) - asAsKeys := make(map[addr.IA]drkey.FabridKey) + asAsKeys := make(map[addr.IA]*drkey.FabridKey) hops := make([]snet.HopInterface, len(f.HopfieldMetadata)) - //ingresses := []uint16{} - //egresses := []uint16{} for i := 0; i < len(f.HopfieldMetadata); i++ { hops[i] = snet.HopInterface{ @@ -246,7 +244,7 @@ func TestSuccessfullValidators(t *testing.T) { keyBytes = drkey.Key{} copy(keyBytes[:], generateRandomBytes(16)) if f.HopfieldMetadata[i].ASLevelKey { - asAsKeys[hops[i].IA] = drkey.FabridKey{Key: keyBytes} + asAsKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} } else { asHostKeys[hops[i].IA] = &drkey.FabridKey{Key: keyBytes} } diff --git a/router/config/config.go b/router/config/config.go index 629f5b3bf7..60a460a6d9 100644 --- a/router/config/config.go +++ b/router/config/config.go @@ -20,6 +20,7 @@ package config import ( "io" "runtime" + "slices" "time" "github.com/scionproto/scion/pkg/log" @@ -87,18 +88,9 @@ func (cfg *RouterConfig) Validate() error { if cfg.NumSlowPathProcessors < 1 { return serrors.New("Provided router config is invalid. NumSlowPathProcessors < 1") } - if cfg.Fabrid { - fabrid_drkey := false - for _, protocol := range cfg.DRKey { - if protocol == "FABRID" { - fabrid_drkey = true - break - } - } - if !fabrid_drkey { - return serrors.New("Provided router config is invalid." + - "Enabling FABRID requires adding it to the DRKey protocols.") - } + if cfg.Fabrid && !slices.Contains(cfg.DRKey, "FABRID") { + return serrors.New("Provided router config is invalid." + + "Enabling FABRID requires adding it to the DRKey protocols.") } if cfg.DispatchedPortStart != nil { if cfg.DispatchedPortEnd == nil { diff --git a/router/control/drkey.go b/router/control/drkey.go index 23db229259..b2ca8f4daa 100644 --- a/router/control/drkey.go +++ b/router/control/drkey.go @@ -56,9 +56,6 @@ func (d *DRKeyProvider) Init() { } func (d *DRKeyProvider) AddSecret(protocolID int32, sv SecretValue) error { - if d == nil { - return serrors.New("Error while adding new drkey. DRKeyProvider not initialized.") - } d.mtx.Lock() defer d.mtx.Unlock() if d.drKeySecrets == nil { @@ -78,6 +75,9 @@ func (d *DRKeyProvider) AddSecret(protocolID int32, sv SecretValue) error { } func (d *DRKeyProvider) getSecret(protocolID int32, t time.Time) (*SecretValue, error) { + if d.drKeySecrets == nil { + return nil, errDRKeyNotInitialized + } secrets := d.drKeySecrets[protocolID] since := time.Since(t) if since > pastValidity { diff --git a/router/control/fetcher.go b/router/control/fetcher.go index 1ad73203b0..92a7b1fa73 100644 --- a/router/control/fetcher.go +++ b/router/control/fetcher.go @@ -100,7 +100,7 @@ func ipPoliciesMapFromPB(mplsPolicyResp map[uint32]*experimental. for _, ipRange := range ipArray.Entry { var m net.IPMask - if len(ipRange.Ip) == 4 { //TODO(jvanbommel): test this + if len(ipRange.Ip) == 4 { m = net.CIDRMask(int(ipRange.Prefix), 8*net.IPv4len) } else { m = net.CIDRMask(int(ipRange.Prefix), 8*net.IPv6len) From 2538c15c56b981418bda2582d290aa8ad69f3c9b Mon Sep 17 00:00:00 2001 From: jelte Date: Tue, 6 Aug 2024 16:27:08 +0200 Subject: [PATCH 15/26] Fixing minor issues from last review round. --- .../fabrid/crypto/fabrid_crypto.go | 25 +++++++++++-------- private/path/fabridquery/matchlist_test.go | 4 --- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto.go b/pkg/experimental/fabrid/crypto/fabrid_crypto.go index aa8950c68d..6428e9b7ad 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto.go @@ -118,33 +118,36 @@ func VerifyAndUpdate(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, return nil } -func ComputePolicyID(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, - key []byte) (fabrid.PolicyID, error) { - +func calcPolicyEncryptionMask(key []byte, id *ext.IdentifierOption) ([]byte, error) { cipher, err := aes.NewCipher(key) if err != nil { - return 0, err + return nil, err } buf := make([]byte, aes.BlockSize) if err = id.Serialize(buf); err != nil { - return 0, err + return nil, err } cipher.Encrypt(buf, buf) + return buf, nil +} + +func ComputePolicyID(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, + key []byte) (fabrid.PolicyID, error) { + + buf, err := calcPolicyEncryptionMask(key, id) + if err != nil { + return 0, err + } return fabrid.PolicyID(f.EncryptedPolicyID ^ buf[0]), nil } func EncryptPolicyID(f fabrid.PolicyID, id *ext.IdentifierOption, key []byte) (uint8, error) { - cipher, err := aes.NewCipher(key) + buf, err := calcPolicyEncryptionMask(key, id) if err != nil { return 0, err } - buf := make([]byte, aes.BlockSize) - if err = id.Serialize(buf); err != nil { - return 0, err - } - cipher.Encrypt(buf, buf) return uint8(f) ^ buf[0], nil } diff --git a/private/path/fabridquery/matchlist_test.go b/private/path/fabridquery/matchlist_test.go index 1518d40c40..7bef46522f 100644 --- a/private/path/fabridquery/matchlist_test.go +++ b/private/path/fabridquery/matchlist_test.go @@ -77,7 +77,3 @@ func TestAcceptedHop(t *testing.T) { require.Equal(t, fabrid.PolicyID(200+i), *pol) } } - -func TestPolicies(t *testing.T) { - -} From 50331c20ddcc2d5ea1450ef4481714ffe40df800 Mon Sep 17 00:00:00 2001 From: jelte Date: Tue, 6 Aug 2024 17:07:36 +0200 Subject: [PATCH 16/26] Now pretty printing the selected policies. --- private/app/path/path.go | 63 +++++++++++++++++++++++++-- private/path/fabridquery/matchlist.go | 5 --- scion/cmd/scion/ping.go | 7 ++- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/private/app/path/path.go b/private/app/path/path.go index dd897c46dd..921f1c4e3f 100644 --- a/private/app/path/path.go +++ b/private/app/path/path.go @@ -127,8 +127,15 @@ func Choose( if err != nil { return nil, serrors.WrapStr("creating fabrid path from scion path", err) } - return snetpath.Path{Src: p.Source(), Dst: p.Destination(), DataplanePath: fabridPath, - NextHop: p.UnderlayNextHop(), Meta: *p.Metadata()}, nil + resPath := snetpath.Path{Src: p.Source(), Dst: p.Destination(), + DataplanePath: fabridPath, NextHop: p.UnderlayNextHop(), Meta: *p.Metadata()} + + if o.fabrid.PrintSelectedPolicies { + cs := DefaultColorScheme(false) + fmt.Printf("Using selected FABRID policies:\n %s\n\n", cs.FabridPath(resPath, + ml.SelectedPolicies)) + } + return resPath, nil } return nil, serrors.New( fmt.Sprintf("no fabrid paths available satisfying query '%s'", @@ -333,7 +340,54 @@ func (cs ColorScheme) Policies(policies []snet.FabridInfo, idx int) string { } } return fmt.Sprintf("~%s~", strings.Join(policyStr, ",")) +} + +func (cs ColorScheme) SelectedPolicy(policy *fabridquery.Policy) string { + if policy == nil { + return "" + } else if policy.Type == fabridquery.WILDCARD_POLICY_TYPE || policy. + Type == fabridquery.REJECT_POLICY_TYPE { + return cs.GlobalPolicy.Sprintf("~ZERO~") + } else if policy.IsLocal { + return cs.LocalPolicy.Sprintf("~%s~", policy.String()) + } else { + return cs.GlobalPolicy.Sprintf("~%s~", policy.String()) + } +} +// FabridPath prints the path with only the selected policies for each hop. +func (cs ColorScheme) FabridPath(path snet.Path, policies []*fabridquery.Policy) string { + if path == nil { + return "" + } + intfs := path.Metadata().Interfaces + if len(intfs) == 0 { + return "" + } + var hops []string + intf := intfs[0] + hops = append(hops, cs.Values.Sprintf("%s %s %s", + cs.Values.Sprint(intf.IA), + cs.SelectedPolicy(policies[0]), + cs.Intf.Sprint(intf.ID), + )) + for i := 1; i < len(intfs)-1; i += 2 { + inIntf := intfs[i] + outIntf := intfs[i+1] + hops = append(hops, cs.Values.Sprintf("%s %s %s %s", + cs.Intf.Sprint(inIntf.ID), + cs.Values.Sprint(inIntf.IA), + cs.SelectedPolicy(policies[(i+1)/2]), + cs.Intf.Sprint(outIntf.ID), + )) + } + intf = intfs[len(intfs)-1] + hops = append(hops, cs.Values.Sprintf("%s %s %s", + cs.Intf.Sprint(intf.ID), + cs.Values.Sprint(intf.IA), + cs.SelectedPolicy(policies[len(intfs)/2]), + )) + return fmt.Sprintf("[%s]", strings.Join(hops, cs.Link.Sprintf(">"))) } func (cs ColorScheme) Path(path snet.Path) string { @@ -380,8 +434,9 @@ type ProbeConfig struct { } type FABRIDQuery struct { - Query string - FabridConfig snetpath.FabridConfig + Query string + FabridConfig snetpath.FabridConfig + PrintSelectedPolicies bool } type options struct { interactive bool diff --git a/private/path/fabridquery/matchlist.go b/private/path/fabridquery/matchlist.go index 5d73e4a0bd..574993b3b7 100644 --- a/private/path/fabridquery/matchlist.go +++ b/private/path/fabridquery/matchlist.go @@ -15,8 +15,6 @@ package fabridquery import ( - "fmt" - "github.com/scionproto/scion/pkg/experimental/fabrid" ) @@ -60,14 +58,11 @@ func (ml MatchList) Policies() (pols []*fabrid.PolicyID) { for i, selected := range ml.SelectedPolicies { if selected == nil { pols[i] = nil - fmt.Println(i, " is not using a policy") } else if selected.Type == WILDCARD_POLICY_TYPE || selected.Type == REJECT_POLICY_TYPE { zeroPol := fabrid.PolicyID(0) pols[i] = &zeroPol - fmt.Println(i, " is using zero policy") } else { pols[i] = &selected.Policy.Index - fmt.Println(i, " is using policy ", selected.String(), " idx: ", selected.Policy.Index) } } return pols diff --git a/scion/cmd/scion/ping.go b/scion/cmd/scion/ping.go index f74b2f75cb..1f7134ff63 100644 --- a/scion/cmd/scion/ping.go +++ b/scion/cmd/scion/ping.go @@ -190,18 +190,17 @@ On other errors, ping will exit with code 2. cfg.LocalAddr = daemonIPString } opts = append(opts, path.WithFABRID(&path.FABRIDQuery{ - Query: flags.fabridQuery, - FabridConfig: cfg, + PrintSelectedPolicies: true, + Query: flags.fabridQuery, + FabridConfig: cfg, })) opts = append(opts, path.WithFetchDetachedFabridMaps(flags.fetchDetached)) } - cs := path.DefaultColorScheme(false) pingPath, err := path.Choose(traceCtx, sd, remote.IA, opts...) if err != nil { return err } - fmt.Println(cs.Path(pingPath)) // If the EPIC flag is set, use the EPIC-HP path type if flags.epic { From 6f9b582dc19492f72bfea250e713013890fbaff2 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Wed, 7 Aug 2024 12:33:28 +0200 Subject: [PATCH 17/26] Refactor fabrid accumulator --- daemon/internal/servers/BUILD.bazel | 2 +- daemon/internal/servers/grpc.go | 12 ++++++------ pkg/experimental/fabrid/graphutils/BUILD.bazel | 14 ++++++++++++++ .../experimental/fabrid/graphutils/maps.go | 4 ++-- private/path/combinator/BUILD.bazel | 4 +--- private/path/combinator/graph.go | 7 ++++--- 6 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 pkg/experimental/fabrid/graphutils/BUILD.bazel rename private/path/combinator/fabrid_accumulator.go => pkg/experimental/fabrid/graphutils/maps.go (97%) diff --git a/daemon/internal/servers/BUILD.bazel b/daemon/internal/servers/BUILD.bazel index 01e28ca333..290053034c 100644 --- a/daemon/internal/servers/BUILD.bazel +++ b/daemon/internal/servers/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/addr:go_default_library", "//pkg/drkey:go_default_library", "//pkg/experimental/fabrid:go_default_library", + "//pkg/experimental/fabrid/graphutils:go_default_library", "//pkg/grpc:go_default_library", "//pkg/log:go_default_library", "//pkg/metrics:go_default_library", @@ -28,7 +29,6 @@ go_library( "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/snet:go_default_library", "//pkg/snet/path:go_default_library", - "//private/path/combinator:go_default_library", "//private/revcache:go_default_library", "//private/topology:go_default_library", "//private/trust:go_default_library", diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index 5592ee5606..4928db80e1 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -31,6 +31,7 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/experimental/fabrid" + fabrid_utils "github.com/scionproto/scion/pkg/experimental/fabrid/graphutils" libgrpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" @@ -45,7 +46,6 @@ import ( fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" "github.com/scionproto/scion/pkg/snet" snetpath "github.com/scionproto/scion/pkg/snet/path" - "github.com/scionproto/scion/private/path/combinator" "github.com/scionproto/scion/private/revcache" "github.com/scionproto/scion/private/topology" "github.com/scionproto/scion/private/trust" @@ -138,13 +138,13 @@ func updateFabridInfo(ctx context.Context, dialer libgrpc.Dialer, detachedHops [ } defer conn.Close() client := experimental.NewFABRIDIntraServiceClient(conn) - fabridMaps := make(map[addr.IA]combinator.FabridMapEntry) + fabridMaps := make(map[addr.IA]fabrid_utils.FabridMapEntry) for _, detachedHop := range detachedHops { if _, ok := fabridMaps[detachedHop.IA]; !ok { fabridMaps[detachedHop.IA] = fetchMaps(ctx, detachedHop.IA, client, detachedHop.Meta.FabridInfo[detachedHop.fiIdx].Digest) } - detachedHop.Meta.FabridInfo[detachedHop.fiIdx] = *combinator. + detachedHop.Meta.FabridInfo[detachedHop.fiIdx] = *fabrid_utils. GetFabridInfoForIntfs(detachedHop.IA, detachedHop.Ingress, detachedHop.Egress, fabridMaps, true) } @@ -194,7 +194,7 @@ func findDetachedHops(paths []snet.Path) []tempHopInfo { // It uses the provided client to communicate with the Control Service and returns a FabridMapEntry // to be used directly in the combinator. func fetchMaps(ctx context.Context, ia addr.IA, client experimental.FABRIDIntraServiceClient, - digest []byte) combinator.FabridMapEntry { + digest []byte) fabrid_utils.FabridMapEntry { maps, err := client.RemoteMaps(ctx, &experimental.RemoteMapsRequest{ Digest: digest, IsdAs: uint64(ia), @@ -202,14 +202,14 @@ func fetchMaps(ctx context.Context, ia addr.IA, client experimental.FABRIDIntraS if err != nil || maps.Maps == nil { log.FromCtx(ctx).Debug("Retrieving remote map from CS failed", "err", err, "ia", ia) - return combinator.FabridMapEntry{} + return fabrid_utils.FabridMapEntry{} } detached := fabrid_ext.Detached{ SupportedIndicesMap: fabrid_ext.SupportedIndicesMapFromPB(maps.Maps.SupportedIndicesMap), IndexIdentiferMap: fabrid_ext.IndexIdentifierMapFromPB(maps.Maps.IndexIdentifierMap), } - return combinator.FabridMapEntry{ + return fabrid_utils.FabridMapEntry{ Map: &detached, Ts: time.Now(), Digest: []byte{}, // leave empty, it can be calculated using detached.Hash() diff --git a/pkg/experimental/fabrid/graphutils/BUILD.bazel b/pkg/experimental/fabrid/graphutils/BUILD.bazel new file mode 100644 index 0000000000..dd0add83ca --- /dev/null +++ b/pkg/experimental/fabrid/graphutils/BUILD.bazel @@ -0,0 +1,14 @@ +load("//tools/lint:go.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["maps.go"], + importpath = "github.com/scionproto/scion/pkg/experimental/fabrid/graphutils", + visibility = ["//visibility:public"], + deps = [ + "//pkg/addr:go_default_library", + "//pkg/experimental/fabrid:go_default_library", + "//pkg/segment/extensions/fabrid:go_default_library", + "//pkg/snet:go_default_library", + ], +) diff --git a/private/path/combinator/fabrid_accumulator.go b/pkg/experimental/fabrid/graphutils/maps.go similarity index 97% rename from private/path/combinator/fabrid_accumulator.go rename to pkg/experimental/fabrid/graphutils/maps.go index 1040b3b65d..131f251e9f 100644 --- a/private/path/combinator/fabrid_accumulator.go +++ b/pkg/experimental/fabrid/graphutils/maps.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package combinator +package graphutils import ( "time" @@ -34,7 +34,7 @@ type FabridMapEntry struct { Digest []byte } -func collectFabridPolicies(ifaces []snet.PathInterface, +func CollectFabridPolicies(ifaces []snet.PathInterface, maps map[addr.IA]FabridMapEntry) []snet.FabridInfo { switch { diff --git a/private/path/combinator/BUILD.bazel b/private/path/combinator/BUILD.bazel index de9b76cb07..f03deeb2ab 100644 --- a/private/path/combinator/BUILD.bazel +++ b/private/path/combinator/BUILD.bazel @@ -4,7 +4,6 @@ go_library( name = "go_default_library", srcs = [ "combinator.go", - "fabrid_accumulator.go", "graph.go", "staticinfo_accumulator.go", ], @@ -12,12 +11,11 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/addr:go_default_library", - "//pkg/experimental/fabrid:go_default_library", + "//pkg/experimental/fabrid/graphutils:go_default_library", "//pkg/private/common:go_default_library", "//pkg/private/ctrl/path_mgmt/proto:go_default_library", "//pkg/private/util:go_default_library", "//pkg/segment:go_default_library", - "//pkg/segment/extensions/fabrid:go_default_library", "//pkg/segment/extensions/staticinfo:go_default_library", "//pkg/slayers/path:go_default_library", "//pkg/slayers/path/scion:go_default_library", diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index 253d8e5576..cbedda1e52 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -23,6 +23,7 @@ import ( "time" "github.com/scionproto/scion/pkg/addr" + fabrid_utils "github.com/scionproto/scion/pkg/experimental/fabrid/graphutils" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/ctrl/path_mgmt/proto" "github.com/scionproto/scion/pkg/private/util" @@ -314,7 +315,7 @@ type pathSolution struct { func (solution *pathSolution) Path() Path { mtu := ^uint16(0) var segments segmentList - fabridMaps := make(map[addr.IA]FabridMapEntry) + fabridMaps := make(map[addr.IA]fabrid_utils.FabridMapEntry) var epicPathAuths [][]byte for _, solEdge := range solution.edges { var hops []path.HopField @@ -384,7 +385,7 @@ func (solution *pathSolution) Path() Path { fabridMap, exists := fabridMaps[asEntry.Local] if (!exists || fabridMap.Ts.Before(solEdge.segment.Info.Timestamp)) && asEntry. Extensions.Digests != nil { - fabridMaps[asEntry.Local] = FabridMapEntry{ + fabridMaps[asEntry.Local] = fabrid_utils.FabridMapEntry{ Map: asEntry.UnsignedExtensions.FabridDetached, Digest: asEntry.Extensions.Digests.Fabrid.Digest, Ts: solEdge.segment.Info.Timestamp, @@ -425,7 +426,7 @@ func (solution *pathSolution) Path() Path { interfaces := segments.Interfaces() asEntries := segments.ASEntries() staticInfo := collectMetadata(interfaces, asEntries) - fabridInfo := collectFabridPolicies(interfaces, fabridMaps) + fabridInfo := fabrid_utils.CollectFabridPolicies(interfaces, fabridMaps) path := Path{ SCIONPath: segments.ScionPath(), Metadata: snet.PathMetadata{ From 97bf83f1308a7864ba44283f2dc5a3222645e7f9 Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Sun, 1 Sep 2024 14:50:19 +0200 Subject: [PATCH 18/26] code comments for FABRID dataplane and router --- pkg/experimental/fabrid/crypto/fabrid_crypto.go | 6 ++++++ pkg/slayers/extension/fabrid.go | 6 ++++++ pkg/slayers/extension/identifier.go | 5 +++++ router/control/drkey.go | 10 ++++++++++ router/control/fetcher.go | 7 +++++++ 5 files changed, 34 insertions(+) diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto.go b/pkg/experimental/fabrid/crypto/fabrid_crypto.go index 6428e9b7ad..09885163c8 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto.go @@ -78,6 +78,7 @@ func computeFabridHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, return nil } +// Computes and sets the base HVF for the provided FABRID Hopfield func ComputeBaseHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { computedHVF := make([]byte, 16) @@ -90,6 +91,7 @@ func ComputeBaseHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, return nil } +// Computes and sets the verified HVF for the provided FABRID Hopfield func ComputeVerifiedHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { computedHVF := make([]byte, 16) @@ -102,6 +104,8 @@ func ComputeVerifiedHVF(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, return nil } +// VerifyAndUpdate recomputes the FABRID HVF and verifies that the provided HVF +// matches the base HVF. In that case it overwrites the provided HVF with the verified HVF. func VerifyAndUpdate(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, s *slayers.SCION, tmpBuffer []byte, key []byte, ingress uint16, egress uint16) error { computedHVF := make([]byte, 16) @@ -131,6 +135,7 @@ func calcPolicyEncryptionMask(key []byte, id *ext.IdentifierOption) ([]byte, err return buf, nil } +// ComputePolicyID acts as a decryptor for an encrypted FABRID policy index. func ComputePolicyID(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, key []byte) (fabrid.PolicyID, error) { @@ -141,6 +146,7 @@ func ComputePolicyID(f *ext.FabridHopfieldMetadata, id *ext.IdentifierOption, return fabrid.PolicyID(f.EncryptedPolicyID ^ buf[0]), nil } +// EncryptPolicyID encrypts a FABRID policy index. func EncryptPolicyID(f fabrid.PolicyID, id *ext.IdentifierOption, key []byte) (uint8, error) { diff --git a/pkg/slayers/extension/fabrid.go b/pkg/slayers/extension/fabrid.go index 566cc755df..711e5351ef 100644 --- a/pkg/slayers/extension/fabrid.go +++ b/pkg/slayers/extension/fabrid.go @@ -129,6 +129,7 @@ func (f *FabridOption) DecodeForHF(b []byte, currHf uint8, numHfs uint8) error { return nil } +// DecodeFull decodes the full FABRID extension including the PathValidator. func (f *FabridOption) DecodeFull(b []byte, numHfs uint8) error { if err := f.validate(b, 0, numHfs); err != nil { return err @@ -167,10 +168,13 @@ func (f *FabridOption) SerializeTo(b []byte) error { return nil } +// FabridOptionLen returns the number of bytes it takes to store the FABRID HBH option consisting +// of a certain number of hopfields. func FabridOptionLen(numHopfields uint8) uint8 { return baseFabridLen + numHopfields*uint8(FabridMetadataLen) } +// ParseFabridOptionFullExtension parses the full FABRID HBH extension including the PathValidator. func ParseFabridOptionFullExtension(o *slayers.HopByHopOption, numHfs uint8) ( *FabridOption, error) { @@ -186,6 +190,8 @@ func ParseFabridOptionFullExtension(o *slayers.HopByHopOption, numHfs uint8) ( return f, nil } +// ParseFabridOptionCurrentHop parses only the metadata of the current hop and stores it in +// f.HopfieldMetadata[0]. The PathValidator will not be decoded. func ParseFabridOptionCurrentHop(o *slayers.HopByHopOption, currHf uint8, numHfs uint8) ( *FabridOption, error) { diff --git a/pkg/slayers/extension/identifier.go b/pkg/slayers/extension/identifier.go index f50026bf35..be3f6bbb07 100644 --- a/pkg/slayers/extension/identifier.go +++ b/pkg/slayers/extension/identifier.go @@ -42,6 +42,8 @@ type IdentifierOption struct { BaseTimestamp uint32 } +// GetRelativeTimestamp returns the time difference between id.Timestamp and id.BaseTimestamp +// as milliseconds. func (id *IdentifierOption) GetRelativeTimestamp() uint32 { return uint32(id.Timestamp.UnixMilli()-int64(id.BaseTimestamp)*1000) & 0x7FFFFFF } @@ -65,6 +67,8 @@ func (id *IdentifierOption) decode(b []byte) error { return nil } +// Serialize writes the packet ID and the relative timestamp to a byte slice. +// Requires that id.Timestamp, id.PacketID and id.BaseTimestamp are set accordingly. func (id *IdentifierOption) Serialize(b []byte) error { if id == nil { return serrors.New("identifier option must not be nil") @@ -77,6 +81,7 @@ func (id *IdentifierOption) Serialize(b []byte) error { return nil } +// ParseIdentifierOption parses the Identifier HBH extension. func ParseIdentifierOption(o *slayers.HopByHopOption, baseTimestamp uint32) ( *IdentifierOption, error) { if o.OptType != slayers.OptTypeIdentifier { diff --git a/router/control/drkey.go b/router/control/drkey.go index b2ca8f4daa..e5134ff48b 100644 --- a/router/control/drkey.go +++ b/router/control/drkey.go @@ -40,6 +40,7 @@ type DRKeyProvider struct { mtx sync.Mutex } +// Init initializes the necessary data structures for the DRKeyProvider. func (d *DRKeyProvider) Init() { d.mtx.Lock() defer d.mtx.Unlock() @@ -55,6 +56,9 @@ func (d *DRKeyProvider) Init() { d.drKeySecretNextOverwrite = make([]uint8, numDRKeyProtocols) } +// AddSecret registers the DRKey secret value for a particular protocol. +// The DRKeyProvider holds at most 2 secret values for a protocol and when registering a new one +// it will overwrite the older secret value. func (d *DRKeyProvider) AddSecret(protocolID int32, sv SecretValue) error { d.mtx.Lock() defer d.mtx.Unlock() @@ -74,6 +78,8 @@ func (d *DRKeyProvider) AddSecret(protocolID int32, sv SecretValue) error { return nil } +// Returns the secret value for a protocol that is valid at a specific point in time, +// or an error, if no matching secret value is stored. func (d *DRKeyProvider) getSecret(protocolID int32, t time.Time) (*SecretValue, error) { if d.drKeySecrets == nil { return nil, errDRKeyNotInitialized @@ -92,6 +98,8 @@ func (d *DRKeyProvider) getSecret(protocolID int32, t time.Time) (*SecretValue, return nil, errDRKeySecretInvalid } +// DeriveASASKey derives an Level1 DRKey that is valid for a specific protocol and AS at a +// specific point in time, given a matching secret value is stored. func (d *DRKeyProvider) DeriveASASKey(protocolID int32, t time.Time, srcAS addr.IA) ([16]byte, error) { drv := specific.Deriver{} @@ -106,6 +114,8 @@ func (d *DRKeyProvider) DeriveASASKey(protocolID int32, t time.Time, srcAS addr. return asToAsKey, nil } +// DeriveASASKey derives an AS-Host DRKey that is valid for a specific protocol and AS-Host at a +// specific point in time, given a matching secret value is stored. func (d *DRKeyProvider) DeriveASHostKey(protocolID int32, t time.Time, srcAS addr.IA, src string) ( [16]byte, error) { diff --git a/router/control/fetcher.go b/router/control/fetcher.go index 92a7b1fa73..3f60e4c3ff 100644 --- a/router/control/fetcher.go +++ b/router/control/fetcher.go @@ -47,6 +47,7 @@ type Fetcher struct { dp Dataplane } +// NewFetcher returns a new fetcher that is used to make queries to the control service. func NewFetcher(localIP string, csAddr string, dp Dataplane) (*Fetcher, error) { localAddr := &net.TCPAddr{ IP: net.ParseIP(localIP), @@ -64,6 +65,8 @@ func NewFetcher(localIP string, csAddr string, dp Dataplane) (*Fetcher, error) { return f, nil } +// StartFabridPolicyFetcher starts the FABRID policy fetcher that fetches the FABRID +// policies from the local control service every 30 minutes. func (f *Fetcher) StartFabridPolicyFetcher() { retryAfterErrorDuration := 10 * time.Second for { @@ -137,6 +140,10 @@ func (f *Fetcher) queryFabridPolicies() (*experimental.MPLSMapResponse, error) { return rep, err } +// StartSecretUpdater is responsible for quering the local control service to request the +// DRKey secret values for the registerd DRKey protocols. (e.g. FABRID, SCMP, ...) +// It will automatically register the received DRKey secrets in the dataplane and start +// prefetching the upcoming secret values 3 minutes before they become valid. func (f *Fetcher) StartSecretUpdater(protocols []string) { retryAfterErrorDuration := 5 * time.Second prefetchTime := time.Minute * 3 From c0654295c1c92cc4a98a9c9aabb917d226d40193 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Mon, 2 Sep 2024 08:35:39 +0200 Subject: [PATCH 19/26] Update copyright to 2024 --- control/config/fabrid.go | 2 +- control/config/fabrid_test.go | 2 +- control/fabrid/fabrid_manager.go | 2 +- control/fabrid/fabrid_manager_test.go | 2 +- control/fabrid/grpc/fabrid_service.go | 2 +- control/fabrid/grpc/fabrid_service_test.go | 2 +- control/fabrid/grpc/fetcher.go | 2 +- control/fabrid/grpc/fetcher_test.go | 2 +- control/fabrid/mpls_map.go | 2 +- control/fabrid/mpls_map_test.go | 2 +- pkg/experimental/fabrid/crypto/fabrid_crypto.go | 2 +- pkg/experimental/fabrid/crypto/fabrid_crypto_test.go | 2 +- pkg/experimental/fabrid/defs.go | 2 +- pkg/segment/extensions/fabrid/fabrid.go | 2 +- pkg/segment/extensions/fabrid/fabrid_test.go | 2 +- pkg/slayers/extension/fabrid.go | 2 +- pkg/slayers/extension/fabrid_test.go | 2 +- pkg/slayers/extension/identifier.go | 2 +- pkg/slayers/extension/identifier_test.go | 2 +- pkg/snet/path/fabrid.go | 2 +- private/path/fabridquery/matchlist.go | 2 +- private/path/fabridquery/matchlist_test.go | 2 +- private/path/fabridquery/parser.go | 2 +- private/path/fabridquery/query.go | 2 +- private/path/fabridquery/query_test.go | 2 +- proto/control_plane/experimental/v1/fabrid.proto | 2 +- proto/control_plane/experimental/v1/fabrid_extensions.proto | 2 +- router/control/fetcher.go | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/control/config/fabrid.go b/control/config/fabrid.go index cb35c0f04e..d9e5bf15bf 100644 --- a/control/config/fabrid.go +++ b/control/config/fabrid.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/config/fabrid_test.go b/control/config/fabrid_test.go index 6ffe65ed92..31ea9f4141 100644 --- a/control/config/fabrid_test.go +++ b/control/config/fabrid_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/fabrid_manager.go b/control/fabrid/fabrid_manager.go index 89d52ed503..3b88172f85 100644 --- a/control/fabrid/fabrid_manager.go +++ b/control/fabrid/fabrid_manager.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/fabrid_manager_test.go b/control/fabrid/fabrid_manager_test.go index 3aecb2b7c5..ccc78f108a 100644 --- a/control/fabrid/fabrid_manager_test.go +++ b/control/fabrid/fabrid_manager_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/grpc/fabrid_service.go b/control/fabrid/grpc/fabrid_service.go index cdb0f3bd03..ad0c672e77 100644 --- a/control/fabrid/grpc/fabrid_service.go +++ b/control/fabrid/grpc/fabrid_service.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/grpc/fabrid_service_test.go b/control/fabrid/grpc/fabrid_service_test.go index 0baa1a9a07..189154af3e 100644 --- a/control/fabrid/grpc/fabrid_service_test.go +++ b/control/fabrid/grpc/fabrid_service_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/grpc/fetcher.go b/control/fabrid/grpc/fetcher.go index 800c983ff6..85314894f9 100644 --- a/control/fabrid/grpc/fetcher.go +++ b/control/fabrid/grpc/fetcher.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/grpc/fetcher_test.go b/control/fabrid/grpc/fetcher_test.go index 04184857e9..863768559f 100644 --- a/control/fabrid/grpc/fetcher_test.go +++ b/control/fabrid/grpc/fetcher_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/mpls_map.go b/control/fabrid/mpls_map.go index 0635b32623..c64b407f50 100644 --- a/control/fabrid/mpls_map.go +++ b/control/fabrid/mpls_map.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/control/fabrid/mpls_map_test.go b/control/fabrid/mpls_map_test.go index 3a7c5d48b8..36dcd9b7fb 100644 --- a/control/fabrid/mpls_map_test.go +++ b/control/fabrid/mpls_map_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto.go b/pkg/experimental/fabrid/crypto/fabrid_crypto.go index 09885163c8..b10200607f 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go index 9722efd4a3..a1c4732892 100644 --- a/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go +++ b/pkg/experimental/fabrid/crypto/fabrid_crypto_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/experimental/fabrid/defs.go b/pkg/experimental/fabrid/defs.go index 23a6ca3269..50c1be0b47 100644 --- a/pkg/experimental/fabrid/defs.go +++ b/pkg/experimental/fabrid/defs.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/segment/extensions/fabrid/fabrid.go b/pkg/segment/extensions/fabrid/fabrid.go index 570c68a2be..659b2627f5 100644 --- a/pkg/segment/extensions/fabrid/fabrid.go +++ b/pkg/segment/extensions/fabrid/fabrid.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/segment/extensions/fabrid/fabrid_test.go b/pkg/segment/extensions/fabrid/fabrid_test.go index a490b741e8..1fa9a8b278 100644 --- a/pkg/segment/extensions/fabrid/fabrid_test.go +++ b/pkg/segment/extensions/fabrid/fabrid_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/slayers/extension/fabrid.go b/pkg/slayers/extension/fabrid.go index 711e5351ef..5cfd2849ba 100644 --- a/pkg/slayers/extension/fabrid.go +++ b/pkg/slayers/extension/fabrid.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/slayers/extension/fabrid_test.go b/pkg/slayers/extension/fabrid_test.go index 736edd170a..f86a21328e 100644 --- a/pkg/slayers/extension/fabrid_test.go +++ b/pkg/slayers/extension/fabrid_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/slayers/extension/identifier.go b/pkg/slayers/extension/identifier.go index be3f6bbb07..a018315e39 100644 --- a/pkg/slayers/extension/identifier.go +++ b/pkg/slayers/extension/identifier.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/slayers/extension/identifier_test.go b/pkg/slayers/extension/identifier_test.go index ac298a727e..477c6ccc74 100644 --- a/pkg/slayers/extension/identifier_test.go +++ b/pkg/slayers/extension/identifier_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/snet/path/fabrid.go b/pkg/snet/path/fabrid.go index b6dd13aa40..839693faf3 100644 --- a/pkg/snet/path/fabrid.go +++ b/pkg/snet/path/fabrid.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/private/path/fabridquery/matchlist.go b/private/path/fabridquery/matchlist.go index 574993b3b7..063c0645d7 100644 --- a/private/path/fabridquery/matchlist.go +++ b/private/path/fabridquery/matchlist.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/private/path/fabridquery/matchlist_test.go b/private/path/fabridquery/matchlist_test.go index 7bef46522f..29cd4dcb97 100644 --- a/private/path/fabridquery/matchlist_test.go +++ b/private/path/fabridquery/matchlist_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/private/path/fabridquery/parser.go b/private/path/fabridquery/parser.go index 1f2f501227..358ffd4a21 100644 --- a/private/path/fabridquery/parser.go +++ b/private/path/fabridquery/parser.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/private/path/fabridquery/query.go b/private/path/fabridquery/query.go index adb5920ea9..6ff37b2b73 100644 --- a/private/path/fabridquery/query.go +++ b/private/path/fabridquery/query.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/private/path/fabridquery/query_test.go b/private/path/fabridquery/query_test.go index badf28d379..c1a5c52185 100644 --- a/private/path/fabridquery/query_test.go +++ b/private/path/fabridquery/query_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/proto/control_plane/experimental/v1/fabrid.proto b/proto/control_plane/experimental/v1/fabrid.proto index f6183f9168..baa96c9d54 100644 --- a/proto/control_plane/experimental/v1/fabrid.proto +++ b/proto/control_plane/experimental/v1/fabrid.proto @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/proto/control_plane/experimental/v1/fabrid_extensions.proto b/proto/control_plane/experimental/v1/fabrid_extensions.proto index fe5602d9bb..75d5f50664 100644 --- a/proto/control_plane/experimental/v1/fabrid_extensions.proto +++ b/proto/control_plane/experimental/v1/fabrid_extensions.proto @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zurich +// Copyright 2024 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/router/control/fetcher.go b/router/control/fetcher.go index 3f60e4c3ff..160e0a06e3 100644 --- a/router/control/fetcher.go +++ b/router/control/fetcher.go @@ -1,4 +1,4 @@ -// Copyright 2023 ETH Zürich +// Copyright 2024 ETH Zürich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From b86ea1e5273d7bae45bb6d6a07c6fd8481d244b6 Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Mon, 16 Sep 2024 11:56:33 +0200 Subject: [PATCH 20/26] Revert change from rebase + lint --- pkg/snet/reply_pather.go | 1 + private/path/combinator/graph.go | 1 + router/control/fetcher.go | 4 ++-- router/dataplane.go | 19 +++++++++++-------- router/dataplane_internal_test.go | 3 +-- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/pkg/snet/reply_pather.go b/pkg/snet/reply_pather.go index cbd6c8c7af..d081260bcf 100644 --- a/pkg/snet/reply_pather.go +++ b/pkg/snet/reply_pather.go @@ -58,6 +58,7 @@ func (p RawReplyPath) SetPath(s *slayers.SCION) error { s.Path, s.PathType = p.Path, p.Path.Type() return nil } + func (p RawReplyPath) SetExtensions(s *slayers.SCION, pi *PacketInfo) error { return nil } diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index cbedda1e52..6c34211ac9 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -476,6 +476,7 @@ func getAuthPeer(a *seg.ASEntry, i int) []byte { copy(auth[6:16], a.UnsignedExtensions.EpicDetached.AuthPeerEntries[i]) return auth } + func isEpicAvailable(epicPathAuths [][]byte) ([]byte, []byte, bool) { l := len(epicPathAuths) if l < 2 { diff --git a/router/control/fetcher.go b/router/control/fetcher.go index 160e0a06e3..40dcad94b8 100644 --- a/router/control/fetcher.go +++ b/router/control/fetcher.go @@ -140,8 +140,8 @@ func (f *Fetcher) queryFabridPolicies() (*experimental.MPLSMapResponse, error) { return rep, err } -// StartSecretUpdater is responsible for quering the local control service to request the -// DRKey secret values for the registerd DRKey protocols. (e.g. FABRID, SCMP, ...) +// StartSecretUpdater is responsible for querying the local control service to request the +// DRKey secret values for the registered DRKey protocols. (e.g. FABRID, SCMP, ...) // It will automatically register the received DRKey secrets in the dataplane and start // prefetching the upcoming secret values 3 minutes before they become valid. func (f *Fetcher) StartSecretUpdater(protocols []string) { diff --git a/router/dataplane.go b/router/dataplane.go index ca60d185db..55bb04aa0c 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -2593,14 +2593,17 @@ func (p *slowPathPacketProcessor) prepareSCMP( scmpH := slayers.SCMP{TypeCode: typeCode} scmpH.SetNetworkLayerForChecksum(&scionL) - // Error messages must be authenticated. - // Traceroute are OPTIONALLY authenticated ONLY IF the request - // was authenticated. - // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth - // if SCMPTypeTracerouteReply to create the response. - needsAuth := cause != nil || - (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && - p.hasValidAuth(time.Now())) + needsAuth := false + if p.d.ExperimentalSCMPAuthentication { + // Error messages must be authenticated. + // Traceroute are OPTIONALLY authenticated ONLY IF the request + // was authenticated. + // TODO(JordiSubira): Reuse the key computed in p.hasValidAuth + // if SCMPTypeTracerouteReply to create the response. + needsAuth = cause != nil || + (scmpH.TypeCode.Type() == slayers.SCMPTypeTracerouteReply && + p.hasValidAuth(time.Now())) + } var quote []byte if cause != nil { diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go index 5636831135..b813777f18 100644 --- a/router/dataplane_internal_test.go +++ b/router/dataplane_internal_test.go @@ -588,8 +588,7 @@ func TestSlowPathProcessing(t *testing.T) { nil, mock_router.NewMockBatchConn(ctrl), fakeInternalNextHops, map[addr.SVC][]*net.UDPAddr{}, - xtest.MustParseIA("1-ff00:0:110"), - nil, testKey) + xtest.MustParseIA("1-ff00:0:110"), nil, testKey) }, mockMsg: func() []byte { spkt := prepBaseMsg(t, payload, 0) From a25dc7e766f3e4bb978cccfba21de51a7d8397fe Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:25:57 +0200 Subject: [PATCH 21/26] extraced FABRID functions and moved to new files --- daemon/drkey/BUILD.bazel | 5 +- daemon/drkey/client_engine.go | 49 - daemon/drkey/client_engine_fabrid.go | 72 + daemon/internal/servers/BUILD.bazel | 1 + daemon/internal/servers/grpc.go | 163 --- daemon/internal/servers/grpc_fabrid.go | 195 +++ pkg/daemon/BUILD.bazel | 1 + pkg/daemon/grpc.go | 69 - pkg/daemon/grpc_fabrid.go | 93 ++ pkg/drkey/BUILD.bazel | 1 + pkg/drkey/drkey.go | 21 - pkg/drkey/drkey_fabrid.go | 38 + pkg/grpc/BUILD.bazel | 1 + pkg/grpc/dialer.go | 41 - pkg/grpc/dialer_drkey.go | 69 + pkg/private/xtest/graph/BUILD.bazel | 1 + pkg/private/xtest/graph/graph.go | 18 - pkg/private/xtest/graph/graph_fabrid.go | 34 + .../seg_detached_extensions.pb.go | 114 +- .../seg_detached_extensions_fabrid.pb.go | 162 ++ pkg/proto/control_plane/seg_extensions.pb.go | 306 ++-- pkg/proto/daemon/daemon.pb.go | 1302 ++++++----------- pkg/proto/daemon/daemon_fabrid.pb.go | 531 +++++++ pkg/snet/BUILD.bazel | 1 + pkg/snet/path.go | 64 - pkg/snet/path/BUILD.bazel | 1 + pkg/snet/path/empty.go | 5 - pkg/snet/path/epic.go | 4 - pkg/snet/path/onehop.go | 5 - pkg/snet/path/path_ext.go | 36 + pkg/snet/path/scion.go | 5 - pkg/snet/path_fabrid.go | 85 ++ .../control_plane/experimental/v1/BUILD.bazel | 1 + .../v1/seg_detached_extensions.proto | 9 - .../v1/seg_detached_extensions_fabrid.proto | 26 + proto/control_plane/v1/seg_extensions.proto | 1 + proto/daemon/v1/BUILD.bazel | 1 + proto/daemon/v1/daemon.proto | 51 +- proto/daemon/v1/daemon_fabrid.proto | 67 + router/BUILD.bazel | 3 + router/connector.go | 13 - router/connector_fabrid.go | 30 + router/dataplane.go | 117 -- router/dataplane_fabrid.go | 141 ++ router/dataplane_internal_fabrid_test.go | 166 +++ router/dataplane_internal_test.go | 142 -- tools/end2end/BUILD.bazel | 5 +- tools/end2end/fabrid.go | 204 +++ tools/end2end/main.go | 170 --- tools/integration/BUILD.bazel | 1 + tools/integration/binary.go | 18 - tools/integration/docker.go | 47 - tools/integration/endhost_integration.go | 129 ++ tools/integration/integration.go | 34 - tools/topology/endhost.py | 28 + 55 files changed, 2738 insertions(+), 2159 deletions(-) create mode 100644 daemon/drkey/client_engine_fabrid.go create mode 100644 daemon/internal/servers/grpc_fabrid.go create mode 100644 pkg/daemon/grpc_fabrid.go create mode 100644 pkg/drkey/drkey_fabrid.go create mode 100644 pkg/grpc/dialer_drkey.go create mode 100644 pkg/private/xtest/graph/graph_fabrid.go create mode 100755 pkg/proto/control_plane/experimental/seg_detached_extensions_fabrid.pb.go create mode 100644 pkg/proto/daemon/daemon_fabrid.pb.go create mode 100644 pkg/snet/path/path_ext.go create mode 100644 pkg/snet/path_fabrid.go create mode 100644 proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto create mode 100644 proto/daemon/v1/daemon_fabrid.proto create mode 100644 router/connector_fabrid.go create mode 100644 router/dataplane_fabrid.go create mode 100644 router/dataplane_internal_fabrid_test.go create mode 100644 tools/end2end/fabrid.go create mode 100644 tools/integration/endhost_integration.go create mode 100644 tools/topology/endhost.py diff --git a/daemon/drkey/BUILD.bazel b/daemon/drkey/BUILD.bazel index 95dcc79a92..140993f8f1 100644 --- a/daemon/drkey/BUILD.bazel +++ b/daemon/drkey/BUILD.bazel @@ -2,7 +2,10 @@ load("//tools/lint:go.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["client_engine.go"], + srcs = [ + "client_engine.go", + "client_engine_fabrid.go", + ], importpath = "github.com/scionproto/scion/daemon/drkey", visibility = ["//visibility:public"], deps = [ diff --git a/daemon/drkey/client_engine.go b/daemon/drkey/client_engine.go index 9546482178..658e997dbd 100644 --- a/daemon/drkey/client_engine.go +++ b/daemon/drkey/client_engine.go @@ -38,55 +38,6 @@ type ClientEngine struct { Fetcher Fetcher } -// For all ASHost Keys and for the HostHost Key, it checks whether the keys are in the database. -// If this is the case, those keys are returned. If not, the keys are requested from CS. -func (e *ClientEngine) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, -) (drkey.FabridKeysResponse, error) { - now := time.Now() - hostHostKey := drkey.FabridKey{} - if meta.DstHost != nil && len(meta.PathASes) > 0 { - key, err := e.GetHostHostKey(ctx, drkey.HostHostMeta{ - ProtoId: drkey.FABRID, - Validity: now, - SrcIA: meta.DstAS, - SrcHost: *meta.DstHost, - DstIA: meta.SrcAS, - DstHost: meta.SrcHost, - }) - if err != nil { - return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID host-host key", err) - } - hostHostKey = drkey.FabridKey{ - Epoch: key.Epoch, - AS: meta.DstAS, - Key: key.Key, - } - } - asHostKeys := make([]drkey.FabridKey, 0, len(meta.PathASes)) - for _, as := range meta.PathASes { - key, err := e.GetASHostKey(ctx, drkey.ASHostMeta{ - ProtoId: drkey.FABRID, - Validity: now, - SrcIA: as, - DstIA: meta.SrcAS, - DstHost: meta.SrcHost, - }) - if err != nil { - return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID AS-host key", err) - } - asHostKeys = append(asHostKeys, drkey.FabridKey{ - Epoch: key.Epoch, - AS: as, - Key: key.Key, - }) - } - - return drkey.FabridKeysResponse{ - ASHostKeys: asHostKeys, - PathKey: hostHostKey, - }, nil -} - // GetASHostKey returns the ASHost key from the local DB or if not found, by asking our local CS. func (e *ClientEngine) GetASHostKey( ctx context.Context, diff --git a/daemon/drkey/client_engine_fabrid.go b/daemon/drkey/client_engine_fabrid.go new file mode 100644 index 0000000000..0aaf752741 --- /dev/null +++ b/daemon/drkey/client_engine_fabrid.go @@ -0,0 +1,72 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package drkey + +import ( + "context" + "time" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/private/serrors" +) + +// For all ASHost Keys and for the HostHost Key, it checks whether the keys are in the database. +// If this is the case, those keys are returned. If not, the keys are requested from CS. +func (e *ClientEngine) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, +) (drkey.FabridKeysResponse, error) { + now := time.Now() + hostHostKey := drkey.FabridKey{} + if meta.DstHost != nil && len(meta.PathASes) > 0 { + key, err := e.GetHostHostKey(ctx, drkey.HostHostMeta{ + ProtoId: drkey.FABRID, + Validity: now, + SrcIA: meta.DstAS, + SrcHost: *meta.DstHost, + DstIA: meta.SrcAS, + DstHost: meta.SrcHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID host-host key", err) + } + hostHostKey = drkey.FabridKey{ + Epoch: key.Epoch, + AS: meta.DstAS, + Key: key.Key, + } + } + asHostKeys := make([]drkey.FabridKey, 0, len(meta.PathASes)) + for _, as := range meta.PathASes { + key, err := e.GetASHostKey(ctx, drkey.ASHostMeta{ + ProtoId: drkey.FABRID, + Validity: now, + SrcIA: as, + DstIA: meta.SrcAS, + DstHost: meta.SrcHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, serrors.WrapStr("prepare FABRID AS-host key", err) + } + asHostKeys = append(asHostKeys, drkey.FabridKey{ + Epoch: key.Epoch, + AS: as, + Key: key.Key, + }) + } + + return drkey.FabridKeysResponse{ + ASHostKeys: asHostKeys, + PathKey: hostHostKey, + }, nil +} diff --git a/daemon/internal/servers/BUILD.bazel b/daemon/internal/servers/BUILD.bazel index 290053034c..e0a0e42474 100644 --- a/daemon/internal/servers/BUILD.bazel +++ b/daemon/internal/servers/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "grpc.go", + "grpc_fabrid.go", "metrics.go", ], importpath = "github.com/scionproto/scion/daemon/internal/servers", diff --git a/daemon/internal/servers/grpc.go b/daemon/internal/servers/grpc.go index 4928db80e1..54243cf3be 100644 --- a/daemon/internal/servers/grpc.go +++ b/daemon/internal/servers/grpc.go @@ -30,8 +30,6 @@ import ( "github.com/scionproto/scion/daemon/fetcher" "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" - "github.com/scionproto/scion/pkg/experimental/fabrid" - fabrid_utils "github.com/scionproto/scion/pkg/experimental/fabrid/graphutils" libgrpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" @@ -40,10 +38,8 @@ import ( "github.com/scionproto/scion/pkg/private/prom" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/proto/control_plane/experimental" pb_daemon "github.com/scionproto/scion/pkg/proto/daemon" sdpb "github.com/scionproto/scion/pkg/proto/daemon" - fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" "github.com/scionproto/scion/pkg/snet" snetpath "github.com/scionproto/scion/pkg/snet/path" "github.com/scionproto/scion/private/revcache" @@ -121,100 +117,6 @@ func (s *DaemonServer) paths(ctx context.Context, return reply, nil } -type tempHopInfo struct { - IA addr.IA - Meta *snet.PathMetadata - fiIdx int - Ingress uint16 - Egress uint16 -} - -// updateFabridInfo updates the FABRID info that is contained in the path Metadata for detached -// hops, by fetching the corresponding FABRID maps from the corresponding AS. -func updateFabridInfo(ctx context.Context, dialer libgrpc.Dialer, detachedHops []tempHopInfo) { - conn, err := dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) - if err != nil { - log.FromCtx(ctx).Debug("Dialing CS failed", "err", err) - } - defer conn.Close() - client := experimental.NewFABRIDIntraServiceClient(conn) - fabridMaps := make(map[addr.IA]fabrid_utils.FabridMapEntry) - for _, detachedHop := range detachedHops { - if _, ok := fabridMaps[detachedHop.IA]; !ok { - fabridMaps[detachedHop.IA] = fetchMaps(ctx, detachedHop.IA, client, - detachedHop.Meta.FabridInfo[detachedHop.fiIdx].Digest) - } - detachedHop.Meta.FabridInfo[detachedHop.fiIdx] = *fabrid_utils. - GetFabridInfoForIntfs(detachedHop.IA, detachedHop.Ingress, detachedHop.Egress, - fabridMaps, true) - } -} - -// findDetachedHops finds the hops where the FABRID maps have been detached in a given list of -// paths. -func findDetachedHops(paths []snet.Path) []tempHopInfo { - detachedHops := make([]tempHopInfo, 0) - for _, p := range paths { - if p.Metadata().FabridInfo[0].Enabled && p.Metadata().FabridInfo[0].Detached { - detachedHops = append(detachedHops, tempHopInfo{ - IA: p.Metadata().Interfaces[0].IA, - Meta: p.Metadata(), - fiIdx: 0, - Ingress: 0, - Egress: uint16(p.Metadata().Interfaces[0].ID), - }) - } - for i := 1; i < len(p.Metadata().Interfaces)-1; i += 2 { - if p.Metadata().FabridInfo[(i+1)/2].Enabled && - p.Metadata().FabridInfo[(i+1)/2].Detached { - detachedHops = append(detachedHops, tempHopInfo{ - IA: p.Metadata().Interfaces[i].IA, - Meta: p.Metadata(), - fiIdx: (i + 1) / 2, - Ingress: uint16(p.Metadata().Interfaces[i].ID), - Egress: uint16(p.Metadata().Interfaces[i+1].ID), - }) - } - } - if p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Enabled && - p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Detached { - detachedHops = append(detachedHops, tempHopInfo{ - IA: p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].IA, - Meta: p.Metadata(), - fiIdx: len(p.Metadata().Interfaces) / 2, - Ingress: uint16(p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].ID), - Egress: 0, - }) - } - } - return detachedHops -} - -// fetchMaps retrieves FABRID maps from the Control Service for a given ISD-AS. -// It uses the provided client to communicate with the Control Service and returns a FabridMapEntry -// to be used directly in the combinator. -func fetchMaps(ctx context.Context, ia addr.IA, client experimental.FABRIDIntraServiceClient, - digest []byte) fabrid_utils.FabridMapEntry { - maps, err := client.RemoteMaps(ctx, &experimental.RemoteMapsRequest{ - Digest: digest, - IsdAs: uint64(ia), - }) - if err != nil || maps.Maps == nil { - log.FromCtx(ctx).Debug("Retrieving remote map from CS failed", "err", err, "ia", - ia) - return fabrid_utils.FabridMapEntry{} - } - - detached := fabrid_ext.Detached{ - SupportedIndicesMap: fabrid_ext.SupportedIndicesMapFromPB(maps.Maps.SupportedIndicesMap), - IndexIdentiferMap: fabrid_ext.IndexIdentifierMapFromPB(maps.Maps.IndexIdentifierMap), - } - return fabrid_utils.FabridMapEntry{ - Map: &detached, - Ts: time.Now(), - Digest: []byte{}, // leave empty, it can be calculated using detached.Hash() - } -} func (s *DaemonServer) fetchPaths( ctx context.Context, group *singleflight.Group, @@ -300,28 +202,6 @@ func pathToPB(path snet.Path) *sdpb.Path { } } -func fabridPolicyToPB(fp *fabrid.Policy) *sdpb.FabridPolicy { - return &sdpb.FabridPolicy{ - PolicyIdentifier: &experimental.FABRIDPolicyIdentifier{ - PolicyIsLocal: fp.IsLocal, - PolicyIdentifier: fp.Identifier, - }, - PolicyIndex: uint32(fp.Index), - } -} - -func fabridInfoToPB(fi *snet.FabridInfo) *sdpb.FabridInfo { - pbPolicies := make([]*sdpb.FabridPolicy, len(fi.Policies)) - for i, fp := range fi.Policies { - pbPolicies[i] = fabridPolicyToPB(fp) - } - return &sdpb.FabridInfo{ - Enabled: fi.Enabled, - Digest: fi.Digest, - Policies: pbPolicies, - Detached: fi.Detached, - } -} func linkTypeToPB(lt snet.LinkType) sdpb.LinkType { switch lt { case snet.LinkTypeDirect: @@ -498,49 +378,6 @@ func (s *DaemonServer) PortRange( }, nil } -func (s *DaemonServer) FabridKeys(ctx context.Context, req *pb_daemon.FabridKeysRequest, -) (*pb_daemon.FabridKeysResponse, error) { - if s.DRKeyClient == nil { - return nil, serrors.New("DRKey is not available") - } - pathASes := make([]addr.IA, 0, len(req.PathAses)) - for _, as := range req.PathAses { - pathASes = append(pathASes, addr.IA(as)) - } - resp, err := s.DRKeyClient.FabridKeys(ctx, drkey.FabridKeysMeta{ - SrcAS: s.DRKeyClient.IA, - SrcHost: req.SrcHost, - DstHost: req.DstHost, - PathASes: pathASes, - DstAS: addr.IA(req.DstAs), - }) - if err != nil { - return nil, serrors.WrapStr("getting fabrid keys from client store", err) - } - fabridKeys := make([]*pb_daemon.FabridKeyResponse, 0, len(resp.ASHostKeys)) - for i := range resp.ASHostKeys { - key := resp.ASHostKeys[i] - fabridKeys = append(fabridKeys, &sdpb.FabridKeyResponse{ - EpochBegin: ×tamppb.Timestamp{Seconds: key.Epoch.NotBefore.Unix()}, - EpochEnd: ×tamppb.Timestamp{Seconds: key.Epoch.NotAfter.Unix()}, - Key: key.Key[:], - }) - } - - var hostHostKey *sdpb.FabridKeyResponse = nil - if req.DstHost != nil { - hostHostKey = &sdpb.FabridKeyResponse{ - EpochBegin: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotBefore.Unix()}, - EpochEnd: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotAfter.Unix()}, - Key: resp.PathKey.Key[:], - } - } - return &pb_daemon.FabridKeysResponse{ - AsHostKeys: fabridKeys, - HostHostKey: hostHostKey, - }, nil -} - func (s *DaemonServer) DRKeyASHost( ctx context.Context, req *pb_daemon.DRKeyASHostRequest, diff --git a/daemon/internal/servers/grpc_fabrid.go b/daemon/internal/servers/grpc_fabrid.go new file mode 100644 index 0000000000..a0f7c3f1f2 --- /dev/null +++ b/daemon/internal/servers/grpc_fabrid.go @@ -0,0 +1,195 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package servers + +import ( + "context" + "time" + + timestamppb "github.com/golang/protobuf/ptypes/timestamp" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" + fabrid_utils "github.com/scionproto/scion/pkg/experimental/fabrid/graphutils" + libgrpc "github.com/scionproto/scion/pkg/grpc" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + sdpb "github.com/scionproto/scion/pkg/proto/daemon" + fabrid_ext "github.com/scionproto/scion/pkg/segment/extensions/fabrid" + "github.com/scionproto/scion/pkg/snet" +) + +type tempHopInfo struct { + IA addr.IA + Meta *snet.PathMetadata + fiIdx int + Ingress uint16 + Egress uint16 +} + +// updateFabridInfo updates the FABRID info that is contained in the path Metadata for detached +// hops, by fetching the corresponding FABRID maps from the corresponding AS. +func updateFabridInfo(ctx context.Context, dialer libgrpc.Dialer, detachedHops []tempHopInfo) { + conn, err := dialer.Dial(ctx, &snet.SVCAddr{SVC: addr.SvcCS}) + if err != nil { + log.FromCtx(ctx).Debug("Dialing CS failed", "err", err) + } + defer conn.Close() + client := experimental.NewFABRIDIntraServiceClient(conn) + fabridMaps := make(map[addr.IA]fabrid_utils.FabridMapEntry) + for _, detachedHop := range detachedHops { + if _, ok := fabridMaps[detachedHop.IA]; !ok { + fabridMaps[detachedHop.IA] = fetchMaps(ctx, detachedHop.IA, client, + detachedHop.Meta.FabridInfo[detachedHop.fiIdx].Digest) + } + detachedHop.Meta.FabridInfo[detachedHop.fiIdx] = *fabrid_utils. + GetFabridInfoForIntfs(detachedHop.IA, detachedHop.Ingress, detachedHop.Egress, + fabridMaps, true) + } +} + +// findDetachedHops finds the hops where the FABRID maps have been detached in a given list of +// paths. +func findDetachedHops(paths []snet.Path) []tempHopInfo { + detachedHops := make([]tempHopInfo, 0) + for _, p := range paths { + if p.Metadata().FabridInfo[0].Enabled && p.Metadata().FabridInfo[0].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[0].IA, + Meta: p.Metadata(), + fiIdx: 0, + Ingress: 0, + Egress: uint16(p.Metadata().Interfaces[0].ID), + }) + } + for i := 1; i < len(p.Metadata().Interfaces)-1; i += 2 { + if p.Metadata().FabridInfo[(i+1)/2].Enabled && + p.Metadata().FabridInfo[(i+1)/2].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[i].IA, + Meta: p.Metadata(), + fiIdx: (i + 1) / 2, + Ingress: uint16(p.Metadata().Interfaces[i].ID), + Egress: uint16(p.Metadata().Interfaces[i+1].ID), + }) + } + } + if p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Enabled && + p.Metadata().FabridInfo[len(p.Metadata().Interfaces)/2].Detached { + detachedHops = append(detachedHops, tempHopInfo{ + IA: p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].IA, + Meta: p.Metadata(), + fiIdx: len(p.Metadata().Interfaces) / 2, + Ingress: uint16(p.Metadata().Interfaces[len(p.Metadata().Interfaces)-1].ID), + Egress: 0, + }) + } + } + return detachedHops +} + +// fetchMaps retrieves FABRID maps from the Control Service for a given ISD-AS. +// It uses the provided client to communicate with the Control Service and returns a FabridMapEntry +// to be used directly in the combinator. +func fetchMaps(ctx context.Context, ia addr.IA, client experimental.FABRIDIntraServiceClient, + digest []byte) fabrid_utils.FabridMapEntry { + maps, err := client.RemoteMaps(ctx, &experimental.RemoteMapsRequest{ + Digest: digest, + IsdAs: uint64(ia), + }) + if err != nil || maps.Maps == nil { + log.FromCtx(ctx).Debug("Retrieving remote map from CS failed", "err", err, "ia", + ia) + return fabrid_utils.FabridMapEntry{} + } + + detached := fabrid_ext.Detached{ + SupportedIndicesMap: fabrid_ext.SupportedIndicesMapFromPB(maps.Maps.SupportedIndicesMap), + IndexIdentiferMap: fabrid_ext.IndexIdentifierMapFromPB(maps.Maps.IndexIdentifierMap), + } + return fabrid_utils.FabridMapEntry{ + Map: &detached, + Ts: time.Now(), + Digest: []byte{}, // leave empty, it can be calculated using detached.Hash() + } +} + +func fabridPolicyToPB(fp *fabrid.Policy) *sdpb.FabridPolicy { + return &sdpb.FabridPolicy{ + PolicyIdentifier: &experimental.FABRIDPolicyIdentifier{ + PolicyIsLocal: fp.IsLocal, + PolicyIdentifier: fp.Identifier, + }, + PolicyIndex: uint32(fp.Index), + } +} + +func fabridInfoToPB(fi *snet.FabridInfo) *sdpb.FabridInfo { + pbPolicies := make([]*sdpb.FabridPolicy, len(fi.Policies)) + for i, fp := range fi.Policies { + pbPolicies[i] = fabridPolicyToPB(fp) + } + return &sdpb.FabridInfo{ + Enabled: fi.Enabled, + Digest: fi.Digest, + Policies: pbPolicies, + Detached: fi.Detached, + } +} + +func (s *DaemonServer) FabridKeys(ctx context.Context, req *sdpb.FabridKeysRequest, +) (*sdpb.FabridKeysResponse, error) { + if s.DRKeyClient == nil { + return nil, serrors.New("DRKey is not available") + } + pathASes := make([]addr.IA, 0, len(req.PathAses)) + for _, as := range req.PathAses { + pathASes = append(pathASes, addr.IA(as)) + } + resp, err := s.DRKeyClient.FabridKeys(ctx, drkey.FabridKeysMeta{ + SrcAS: s.DRKeyClient.IA, + SrcHost: req.SrcHost, + DstHost: req.DstHost, + PathASes: pathASes, + DstAS: addr.IA(req.DstAs), + }) + if err != nil { + return nil, serrors.WrapStr("getting fabrid keys from client store", err) + } + fabridKeys := make([]*sdpb.FabridKeyResponse, 0, len(resp.ASHostKeys)) + for i := range resp.ASHostKeys { + key := resp.ASHostKeys[i] + fabridKeys = append(fabridKeys, &sdpb.FabridKeyResponse{ + EpochBegin: ×tamppb.Timestamp{Seconds: key.Epoch.NotBefore.Unix()}, + EpochEnd: ×tamppb.Timestamp{Seconds: key.Epoch.NotAfter.Unix()}, + Key: key.Key[:], + }) + } + + var hostHostKey *sdpb.FabridKeyResponse = nil + if req.DstHost != nil { + hostHostKey = &sdpb.FabridKeyResponse{ + EpochBegin: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotBefore.Unix()}, + EpochEnd: ×tamppb.Timestamp{Seconds: resp.PathKey.Epoch.NotAfter.Unix()}, + Key: resp.PathKey.Key[:], + } + } + return &sdpb.FabridKeysResponse{ + AsHostKeys: fabridKeys, + HostHostKey: hostHostKey, + }, nil +} diff --git a/pkg/daemon/BUILD.bazel b/pkg/daemon/BUILD.bazel index cb0fe57cab..4c245e9fe4 100644 --- a/pkg/daemon/BUILD.bazel +++ b/pkg/daemon/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "apitypes.go", "daemon.go", "grpc.go", + "grpc_fabrid.go", "metrics.go", ], importpath = "github.com/scionproto/scion/pkg/daemon", diff --git a/pkg/daemon/grpc.go b/pkg/daemon/grpc.go index 8e2a5ac6c3..3b37fbc5db 100644 --- a/pkg/daemon/grpc.go +++ b/pkg/daemon/grpc.go @@ -26,7 +26,6 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/drkey" - "github.com/scionproto/scion/pkg/experimental/fabrid" libgrpc "github.com/scionproto/scion/pkg/grpc" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/ctrl/path_mgmt" @@ -226,57 +225,6 @@ func (c grpcConn) DRKeyGetHostHostKey(ctx context.Context, return key, nil } -// Returns all the ASHost DRKeys for the ASes inside the meta.PathAS -func (c grpcConn) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, -) (drkey.FabridKeysResponse, error) { - - client := sdpb.NewDaemonServiceClient((c.conn)) - pathASes := make([]uint64, 0, len(meta.PathASes)) - for i := 0; i < len(meta.PathASes); i++ { - pathASes = append(pathASes, uint64(meta.PathASes[i])) - } - resp, err := client.FabridKeys(ctx, &sdpb.FabridKeysRequest{ - SrcHost: meta.SrcHost, - PathAses: pathASes, - DstAs: uint64(meta.DstAS), - DstHost: meta.DstHost, - }) - if err != nil { - return drkey.FabridKeysResponse{}, err - } - asHostKeys := make([]drkey.FabridKey, 0, len(resp.AsHostKeys)) - for i, key := range resp.AsHostKeys { - epoch := drkey.Epoch{ - Validity: cppki.Validity{ - NotBefore: key.EpochBegin.AsTime(), - NotAfter: key.EpochEnd.AsTime(), - }, - } - asHostKeys = append(asHostKeys, drkey.FabridKey{ - Epoch: epoch, - AS: meta.PathASes[i], - Key: drkey.Key(key.Key), - }) - } - var hostHostKey drkey.FabridKey = drkey.FabridKey{} - if resp.HostHostKey != nil { - hostHostKey = drkey.FabridKey{ - Epoch: drkey.Epoch{ - Validity: cppki.Validity{ - NotBefore: resp.HostHostKey.EpochBegin.AsTime(), - NotAfter: resp.HostHostKey.EpochEnd.AsTime(), - }, - }, - AS: meta.DstAS, - Key: drkey.Key(resp.HostHostKey.Key), - } - } - return drkey.FabridKeysResponse{ - ASHostKeys: asHostKeys, - PathKey: hostHostKey, - }, nil -} - func (c grpcConn) Close() error { return c.conn.Close() } @@ -371,23 +319,6 @@ func convertPath(p *sdpb.Path, dst addr.IA) (path.Path, error) { return res, nil } -func fabridInfoFromPB(fi *sdpb.FabridInfo) snet.FabridInfo { - pbPolicies := make([]*fabrid.Policy, len(fi.Policies)) - for i, fp := range fi.Policies { - pbPolicies[i] = &fabrid.Policy{ - IsLocal: fp.PolicyIdentifier.PolicyIsLocal, - Identifier: fp.PolicyIdentifier.PolicyIdentifier, - Index: fabrid.PolicyID(fp.PolicyIndex), - } - } - return snet.FabridInfo{ - Enabled: fi.Enabled, - Policies: pbPolicies, - Digest: fi.Digest, - Detached: fi.Detached, - } -} - func linkTypeFromPB(lt sdpb.LinkType) snet.LinkType { switch lt { case sdpb.LinkType_LINK_TYPE_DIRECT: diff --git a/pkg/daemon/grpc_fabrid.go b/pkg/daemon/grpc_fabrid.go new file mode 100644 index 0000000000..3983c5a1b2 --- /dev/null +++ b/pkg/daemon/grpc_fabrid.go @@ -0,0 +1,93 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package daemon + +import ( + "context" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid" + sdpb "github.com/scionproto/scion/pkg/proto/daemon" + "github.com/scionproto/scion/pkg/scrypto/cppki" + "github.com/scionproto/scion/pkg/snet" +) + +func fabridInfoFromPB(fi *sdpb.FabridInfo) snet.FabridInfo { + pbPolicies := make([]*fabrid.Policy, len(fi.Policies)) + for i, fp := range fi.Policies { + pbPolicies[i] = &fabrid.Policy{ + IsLocal: fp.PolicyIdentifier.PolicyIsLocal, + Identifier: fp.PolicyIdentifier.PolicyIdentifier, + Index: fabrid.PolicyID(fp.PolicyIndex), + } + } + return snet.FabridInfo{ + Enabled: fi.Enabled, + Policies: pbPolicies, + Digest: fi.Digest, + Detached: fi.Detached, + } +} + +// Returns all the ASHost DRKeys for the ASes inside the meta.PathAS +func (c grpcConn) FabridKeys(ctx context.Context, meta drkey.FabridKeysMeta, +) (drkey.FabridKeysResponse, error) { + + client := sdpb.NewDaemonServiceClient((c.conn)) + pathASes := make([]uint64, 0, len(meta.PathASes)) + for i := 0; i < len(meta.PathASes); i++ { + pathASes = append(pathASes, uint64(meta.PathASes[i])) + } + resp, err := client.FabridKeys(ctx, &sdpb.FabridKeysRequest{ + SrcHost: meta.SrcHost, + PathAses: pathASes, + DstAs: uint64(meta.DstAS), + DstHost: meta.DstHost, + }) + if err != nil { + return drkey.FabridKeysResponse{}, err + } + asHostKeys := make([]drkey.FabridKey, 0, len(resp.AsHostKeys)) + for i, key := range resp.AsHostKeys { + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: key.EpochBegin.AsTime(), + NotAfter: key.EpochEnd.AsTime(), + }, + } + asHostKeys = append(asHostKeys, drkey.FabridKey{ + Epoch: epoch, + AS: meta.PathASes[i], + Key: drkey.Key(key.Key), + }) + } + var hostHostKey drkey.FabridKey = drkey.FabridKey{} + if resp.HostHostKey != nil { + hostHostKey = drkey.FabridKey{ + Epoch: drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: resp.HostHostKey.EpochBegin.AsTime(), + NotAfter: resp.HostHostKey.EpochEnd.AsTime(), + }, + }, + AS: meta.DstAS, + Key: drkey.Key(resp.HostHostKey.Key), + } + } + return drkey.FabridKeysResponse{ + ASHostKeys: asHostKeys, + PathKey: hostHostKey, + }, nil +} diff --git a/pkg/drkey/BUILD.bazel b/pkg/drkey/BUILD.bazel index 45d90b984d..1998b90997 100644 --- a/pkg/drkey/BUILD.bazel +++ b/pkg/drkey/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "db.go", "drkey.go", + "drkey_fabrid.go", "protocol.go", ], importpath = "github.com/scionproto/scion/pkg/drkey", diff --git a/pkg/drkey/drkey.go b/pkg/drkey/drkey.go index 635cebaa39..9e8bdfb3ab 100644 --- a/pkg/drkey/drkey.go +++ b/pkg/drkey/drkey.go @@ -199,24 +199,3 @@ type HostHostKey struct { DstHost string Key Key } - -type FabridKeysMeta struct { - SrcAS addr.IA - SrcHost string - // ASes on the path. Don't have to be in order - PathASes []addr.IA - // Field is optional. If DstHost is nil, no path-key will be fetched - DstHost *string - DstAS addr.IA -} - -type FabridKey struct { - Epoch Epoch - AS addr.IA - Key Key -} - -type FabridKeysResponse struct { - ASHostKeys []FabridKey - PathKey FabridKey -} diff --git a/pkg/drkey/drkey_fabrid.go b/pkg/drkey/drkey_fabrid.go new file mode 100644 index 0000000000..713504e323 --- /dev/null +++ b/pkg/drkey/drkey_fabrid.go @@ -0,0 +1,38 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package drkey + +import "github.com/scionproto/scion/pkg/addr" + +type FabridKeysMeta struct { + SrcAS addr.IA + SrcHost string + // ASes on the path. Don't have to be in order + PathASes []addr.IA + // Field is optional. If DstHost is nil, no path-key will be fetched + DstHost *string + DstAS addr.IA +} + +type FabridKey struct { + Epoch Epoch + AS addr.IA + Key Key +} + +type FabridKeysResponse struct { + ASHostKeys []FabridKey + PathKey FabridKey +} diff --git a/pkg/grpc/BUILD.bazel b/pkg/grpc/BUILD.bazel index e82853d5ff..2f2a4d3d06 100644 --- a/pkg/grpc/BUILD.bazel +++ b/pkg/grpc/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "creds.go", "dialer.go", + "dialer_drkey.go", "interceptor.go", ], importpath = "github.com/scionproto/scion/pkg/grpc", diff --git a/pkg/grpc/dialer.go b/pkg/grpc/dialer.go index f67eae2d20..abaf419852 100644 --- a/pkg/grpc/dialer.go +++ b/pkg/grpc/dialer.go @@ -50,47 +50,6 @@ func (SimpleDialer) Dial(ctx context.Context, address net.Addr) (*grpc.ClientCon ) } -// The FixedLocalIPTCPDialer behaves the same as the TCP Dialer but allows for setting a local -// IP address. Without this it would not be possible to call IP sensitive endpoints like -// control service drkey. -type FixedLocalIPTCPDialer struct { - LocalAddr *net.TCPAddr - SvcResolver func(addr.SVC) []resolver.Address -} - -func (d *FixedLocalIPTCPDialer) Dial(ctx context.Context, dst net.Addr) (*grpc.ClientConn, error) { - dialer := func(ctx context.Context, addr string) (net.Conn, error) { - csAddr, err := net.ResolveTCPAddr("tcp", addr) - if err != nil { - return nil, err - } - return net.DialTCP("tcp", d.LocalAddr, csAddr) - } - if v, ok := dst.(*snet.SVCAddr); ok { - targets := d.SvcResolver(v.SVC) - r := manual.NewBuilderWithScheme("svc") - r.InitialState(resolver.State{Addresses: targets}) - if len(targets) == 0 { - return nil, serrors.New("could not resolve") - } - return grpc.DialContext(ctx, r.Scheme()+":///"+v.SVC.BaseString(), - grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`), - grpc.WithInsecure(), - grpc.WithContextDialer(dialer), - grpc.WithResolvers(r), - UnaryClientInterceptor(), - StreamClientInterceptor(), - ) - } else { - return grpc.DialContext(ctx, dst.String(), - grpc.WithInsecure(), - grpc.WithContextDialer(dialer), - UnaryClientInterceptor(), - StreamClientInterceptor(), - ) - } -} - // XXX(roosd): // // Dialing a grpc.ClientConn is hidden behind the dialer interface due to diff --git a/pkg/grpc/dialer_drkey.go b/pkg/grpc/dialer_drkey.go new file mode 100644 index 0000000000..ac69a3c5bb --- /dev/null +++ b/pkg/grpc/dialer_drkey.go @@ -0,0 +1,69 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package grpc + +import ( + "context" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/resolver" + "google.golang.org/grpc/resolver/manual" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/snet" +) + +// The FixedLocalIPTCPDialer behaves the same as the TCP Dialer but allows for setting a local +// IP address. Without this it would not be possible to call IP sensitive endpoints like +// control service drkey. +type FixedLocalIPTCPDialer struct { + LocalAddr *net.TCPAddr + SvcResolver func(addr.SVC) []resolver.Address +} + +func (d *FixedLocalIPTCPDialer) Dial(ctx context.Context, dst net.Addr) (*grpc.ClientConn, error) { + dialer := func(ctx context.Context, addr string) (net.Conn, error) { + csAddr, err := net.ResolveTCPAddr("tcp", addr) + if err != nil { + return nil, err + } + return net.DialTCP("tcp", d.LocalAddr, csAddr) + } + if v, ok := dst.(*snet.SVCAddr); ok { + targets := d.SvcResolver(v.SVC) + r := manual.NewBuilderWithScheme("svc") + r.InitialState(resolver.State{Addresses: targets}) + if len(targets) == 0 { + return nil, serrors.New("could not resolve") + } + return grpc.DialContext(ctx, r.Scheme()+":///"+v.SVC.BaseString(), + grpc.WithDefaultServiceConfig(`{"loadBalancingConfig": [{"round_robin":{}}]}`), + grpc.WithInsecure(), + grpc.WithContextDialer(dialer), + grpc.WithResolvers(r), + UnaryClientInterceptor(), + StreamClientInterceptor(), + ) + } else { + return grpc.DialContext(ctx, dst.String(), + grpc.WithInsecure(), + grpc.WithContextDialer(dialer), + UnaryClientInterceptor(), + StreamClientInterceptor(), + ) + } +} diff --git a/pkg/private/xtest/graph/BUILD.bazel b/pkg/private/xtest/graph/BUILD.bazel index 6ddcb1a1ab..b5031b2114 100644 --- a/pkg/private/xtest/graph/BUILD.bazel +++ b/pkg/private/xtest/graph/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "default_gen.go", "graph.go", + "graph_fabrid.go", ], importpath = "github.com/scionproto/scion/pkg/private/xtest/graph", visibility = ["//visibility:public"], diff --git a/pkg/private/xtest/graph/graph.go b/pkg/private/xtest/graph/graph.go index 690a58ecb6..bc34543665 100644 --- a/pkg/private/xtest/graph/graph.go +++ b/pkg/private/xtest/graph/graph.go @@ -37,7 +37,6 @@ import ( "google.golang.org/protobuf/proto" "github.com/scionproto/scion/pkg/addr" - "github.com/scionproto/scion/pkg/experimental/fabrid" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" cppb "github.com/scionproto/scion/pkg/proto/control_plane" @@ -417,23 +416,6 @@ func (g *Graph) InternalHops(a, b uint16) uint32 { return uint32(a * b % 10) } -// FabridPolicy returns an arbitrary set of policies between between two interfaces of an AS. -func (g *Graph) FabridPolicy(a, b uint16) []*fabrid.Policy { - if g.parents[a] != g.parents[b] && a != 0 && b != 0 { - panic("interfaces must be in the same AS") - } - amtOfPols := int(a*b%10 + 3) - policies := make([]*fabrid.Policy, amtOfPols) - for i := 0; i < amtOfPols; i++ { - policies[i] = &fabrid.Policy{ - IsLocal: false, - Identifier: (uint32(a)*uint32(b)*uint32(i)*39 + uint32(i) + 1) % 20000, - Index: fabrid.PolicyID(a * b), - } - } - return policies -} - // SignerOption allows customizing the generated Signer. type SignerOption func(o *Signer) diff --git a/pkg/private/xtest/graph/graph_fabrid.go b/pkg/private/xtest/graph/graph_fabrid.go new file mode 100644 index 0000000000..04683abddb --- /dev/null +++ b/pkg/private/xtest/graph/graph_fabrid.go @@ -0,0 +1,34 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package graph + +import "github.com/scionproto/scion/pkg/experimental/fabrid" + +// FabridPolicy returns an arbitrary set of policies between between two interfaces of an AS. +func (g *Graph) FabridPolicy(a, b uint16) []*fabrid.Policy { + if g.parents[a] != g.parents[b] && a != 0 && b != 0 { + panic("interfaces must be in the same AS") + } + amtOfPols := int(a*b%10 + 3) + policies := make([]*fabrid.Policy, amtOfPols) + for i := 0; i < amtOfPols; i++ { + policies[i] = &fabrid.Policy{ + IsLocal: false, + Identifier: (uint32(a)*uint32(b)*uint32(i)*39 + uint32(i) + 1) % 20000, + Index: fabrid.PolicyID(a * b), + } + } + return policies +} diff --git a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go index 667bbc38ad..da4342be28 100755 --- a/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go +++ b/pkg/proto/control_plane/experimental/seg_detached_extensions.pb.go @@ -75,53 +75,6 @@ func (x *EPICDetachedExtension) GetAuthPeerEntries() [][]byte { return nil } -type FABRIDDetachedExtension struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Maps *FABRIDDetachableMaps `protobuf:"bytes,1,opt,name=maps,proto3" json:"maps,omitempty"` -} - -func (x *FABRIDDetachedExtension) Reset() { - *x = FABRIDDetachedExtension{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FABRIDDetachedExtension) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FABRIDDetachedExtension) ProtoMessage() {} - -func (x *FABRIDDetachedExtension) ProtoReflect() protoreflect.Message { - mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FABRIDDetachedExtension.ProtoReflect.Descriptor instead. -func (*FABRIDDetachedExtension) Descriptor() ([]byte, []int) { - return file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDescGZIP(), []int{1} -} - -func (x *FABRIDDetachedExtension) GetMaps() *FABRIDDetachableMaps { - if x != nil { - return x.Maps - } - return nil -} - var File_proto_control_plane_experimental_v1_seg_detached_extensions_proto protoreflect.FileDescriptor var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDesc = []byte{ @@ -131,29 +84,18 @@ var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDe 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, - 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x69, 0x0a, 0x15, 0x45, 0x50, 0x49, 0x43, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, - 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x48, 0x6f, 0x70, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x65, 0x65, - 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x0f, 0x61, 0x75, 0x74, 0x68, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, - 0x22, 0x68, 0x0a, 0x17, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x04, 0x6d, - 0x61, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, - 0x4d, 0x61, 0x70, 0x73, 0x52, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x22, 0x69, 0x0a, 0x15, 0x45, 0x50, 0x49, 0x43, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x48, + 0x6f, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x5f, + 0x70, 0x65, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x50, 0x65, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, + 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, + 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -168,19 +110,16 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawD return file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDescData } -var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_goTypes = []interface{}{ - (*EPICDetachedExtension)(nil), // 0: proto.control_plane.experimental.v1.EPICDetachedExtension - (*FABRIDDetachedExtension)(nil), // 1: proto.control_plane.experimental.v1.FABRIDDetachedExtension - (*FABRIDDetachableMaps)(nil), // 2: proto.control_plane.experimental.v1.FABRIDDetachableMaps + (*EPICDetachedExtension)(nil), // 0: proto.control_plane.experimental.v1.EPICDetachedExtension } var file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_depIdxs = []int32{ - 2, // 0: proto.control_plane.experimental.v1.FABRIDDetachedExtension.maps:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init() } @@ -188,7 +127,6 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init if File_proto_control_plane_experimental_v1_seg_detached_extensions_proto != nil { return } - file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() if !protoimpl.UnsafeEnabled { file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EPICDetachedExtension); i { @@ -202,18 +140,6 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init return nil } } - file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FABRIDDetachedExtension); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } type x struct{} out := protoimpl.TypeBuilder{ @@ -221,7 +147,7 @@ func file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_init GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_control_plane_experimental_v1_seg_detached_extensions_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 1, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/proto/control_plane/experimental/seg_detached_extensions_fabrid.pb.go b/pkg/proto/control_plane/experimental/seg_detached_extensions_fabrid.pb.go new file mode 100755 index 0000000000..9b4e706ec4 --- /dev/null +++ b/pkg/proto/control_plane/experimental/seg_detached_extensions_fabrid.pb.go @@ -0,0 +1,162 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.10 +// source: proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto + +package experimental + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FABRIDDetachedExtension struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Maps *FABRIDDetachableMaps `protobuf:"bytes,1,opt,name=maps,proto3" json:"maps,omitempty"` +} + +func (x *FABRIDDetachedExtension) Reset() { + *x = FABRIDDetachedExtension{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FABRIDDetachedExtension) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FABRIDDetachedExtension) ProtoMessage() {} + +func (x *FABRIDDetachedExtension) ProtoReflect() protoreflect.Message { + mi := &file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FABRIDDetachedExtension.ProtoReflect.Descriptor instead. +func (*FABRIDDetachedExtension) Descriptor() ([]byte, []int) { + return file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescGZIP(), []int{0} +} + +func (x *FABRIDDetachedExtension) GetMaps() *FABRIDDetachableMaps { + if x != nil { + return x.Maps + } + return nil +} + +var File_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto protoreflect.FileDescriptor + +var file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDesc = []byte{ + 0x0a, 0x48, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x66, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x1a, + 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x68, 0x0a, 0x17, + 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, + 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, + 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, + 0x52, 0x04, 0x6d, 0x61, 0x70, 0x73, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, + 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescOnce sync.Once + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescData = file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDesc +) + +func file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescGZIP() []byte { + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescOnce.Do(func() { + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescData) + }) + return file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDescData +} + +var file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_goTypes = []interface{}{ + (*FABRIDDetachedExtension)(nil), // 0: proto.control_plane.experimental.v1.FABRIDDetachedExtension + (*FABRIDDetachableMaps)(nil), // 1: proto.control_plane.experimental.v1.FABRIDDetachableMaps +} +var file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_depIdxs = []int32{ + 1, // 0: proto.control_plane.experimental.v1.FABRIDDetachedExtension.maps:type_name -> proto.control_plane.experimental.v1.FABRIDDetachableMaps + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_init() } +func file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_init() { + if File_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto != nil { + return + } + file_proto_control_plane_experimental_v1_fabrid_extensions_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FABRIDDetachedExtension); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_goTypes, + DependencyIndexes: file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_depIdxs, + MessageInfos: file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_msgTypes, + }.Build() + File_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto = out.File + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_rawDesc = nil + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_goTypes = nil + file_proto_control_plane_experimental_v1_seg_detached_extensions_fabrid_proto_depIdxs = nil +} diff --git a/pkg/proto/control_plane/seg_extensions.pb.go b/pkg/proto/control_plane/seg_extensions.pb.go index 0c8b1e4831..5b0ddb9162 100644 --- a/pkg/proto/control_plane/seg_extensions.pb.go +++ b/pkg/proto/control_plane/seg_extensions.pb.go @@ -674,170 +674,174 @@ var file_proto_control_plane_v1_seg_extensions_proto_rawDesc = []byte{ 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf7, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x74, - 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x4c, 0x0a, 0x0b, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, - 0x69, 0x64, 0x64, 0x65, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x0a, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12, 0x42, - 0x0a, 0x07, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x73, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x64, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x73, 0x22, 0x32, 0x0a, 0x13, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x50, 0x61, 0x74, 0x68, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, - 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, - 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x22, 0x89, 0x06, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, - 0x0a, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a, - 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, - 0x74, 0x68, 0x12, 0x56, 0x0a, 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, - 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, 0x6f, - 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x03, 0x67, 0x65, - 0x6f, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x67, - 0x65, 0x6f, 0x12, 0x56, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x62, 0x0a, 0x0d, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x48, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, + 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, + 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xf7, 0x01, 0x0a, 0x15, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4c, 0x0a, 0x0b, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x49, + 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4c, 0x0a, 0x0b, 0x68, 0x69, + 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x50, + 0x61, 0x74, 0x68, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x68, 0x69, + 0x64, 0x64, 0x65, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12, 0x42, 0x0a, 0x07, 0x64, 0x69, 0x67, 0x65, + 0x73, 0x74, 0x73, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x73, 0x22, 0x32, 0x0a, 0x13, + 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, + 0x22, 0x89, 0x06, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x07, 0x6c, 0x61, 0x74, 0x65, + 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, + 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, + 0x69, 0x64, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x56, 0x0a, 0x10, + 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x03, 0x67, 0x65, 0x6f, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x47, + 0x65, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x67, 0x65, 0x6f, 0x12, 0x56, 0x0a, 0x09, + 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x39, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, + 0x6e, 0x66, 0x6f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x69, 0x6e, + 0x6b, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x62, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x49, 0x6e, 0x66, 0x6f, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x1a, 0x5e, 0x0a, 0x08, + 0x47, 0x65, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, + 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5d, 0x0a, 0x0d, + 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3f, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, - 0x74, 0x65, 0x1a, 0x5e, 0x0a, 0x08, 0x47, 0x65, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, - 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x5d, 0x0a, 0x0d, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x3f, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x8d, 0x02, 0x0a, 0x0b, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8d, 0x02, 0x0a, + 0x0b, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x05, + 0x69, 0x6e, 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, + 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x12, 0x44, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, - 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x12, 0x44, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, + 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x72, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x93, 0x02, 0x0a, + 0x0d, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, + 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x12, 0x46, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x93, 0x02, 0x0a, 0x0d, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6e, - 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x12, 0x46, 0x0a, 0x05, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x49, 0x6e, - 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x38, - 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa5, 0x02, 0x0a, 0x13, 0x43, 0x61, 0x72, - 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x4c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x36, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, - 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x12, 0x4c, - 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x1a, 0x38, 0x0a, 0x0a, - 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xa5, 0x02, 0x0a, 0x13, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4c, 0x0a, 0x05, 0x69, 0x6e, + 0x74, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x12, 0x4c, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, + 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0f, 0x44, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x04, 0x65, 0x70, - 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, - 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, - 0x47, 0x0a, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x52, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x1a, 0x20, 0x0a, 0x06, 0x44, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0xc7, 0x01, 0x0a, 0x1d, 0x50, - 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4f, 0x0a, 0x04, - 0x65, 0x70, 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x50, 0x49, 0x43, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, 0x55, 0x0a, - 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x66, 0x61, - 0x62, 0x72, 0x69, 0x64, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, - 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, - 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, - 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, - 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, - 0x10, 0x03, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, - 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x1a, 0x38, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, + 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, + 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, + 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, + 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x22, 0xc1, 0x01, 0x0a, 0x0f, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x04, 0x65, 0x70, 0x69, 0x63, 0x18, 0xe8, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x06, 0x66, 0x61, 0x62, + 0x72, 0x69, 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x06, 0x66, 0x61, 0x62, 0x72, + 0x69, 0x64, 0x1a, 0x20, 0x0a, 0x06, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x22, 0xc7, 0x01, 0x0a, 0x1d, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4f, 0x0a, 0x04, 0x65, 0x70, 0x69, 0x63, 0x18, 0xe8, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, 0x78, 0x70, 0x65, + 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x50, 0x49, 0x43, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x04, 0x65, 0x70, 0x69, 0x63, 0x12, 0x55, 0x0a, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, + 0x64, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x41, 0x42, 0x52, 0x49, 0x44, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x2a, 0x6c, + 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, + 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, + 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, + 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x42, 0x35, 0x5a, 0x33, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, + 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/proto/daemon/daemon.pb.go b/pkg/proto/daemon/daemon.pb.go index 63de459029..1b2bcfa487 100644 --- a/pkg/proto/daemon/daemon.pb.go +++ b/pkg/proto/daemon/daemon.pb.go @@ -8,7 +8,6 @@ package daemon import ( context "context" - experimental "github.com/scionproto/scion/pkg/proto/control_plane/experimental" drkey "github.com/scionproto/scion/pkg/proto/drkey" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -358,321 +357,6 @@ func (x *Path) GetFabridInfo() []*FabridInfo { return nil } -type FabridInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - Digest []byte `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"` - Policies []*FabridPolicy `protobuf:"bytes,3,rep,name=policies,proto3" json:"policies,omitempty"` - Detached bool `protobuf:"varint,4,opt,name=detached,proto3" json:"detached,omitempty"` -} - -func (x *FabridInfo) Reset() { - *x = FabridInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FabridInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FabridInfo) ProtoMessage() {} - -func (x *FabridInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FabridInfo.ProtoReflect.Descriptor instead. -func (*FabridInfo) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} -} - -func (x *FabridInfo) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *FabridInfo) GetDigest() []byte { - if x != nil { - return x.Digest - } - return nil -} - -func (x *FabridInfo) GetPolicies() []*FabridPolicy { - if x != nil { - return x.Policies - } - return nil -} - -func (x *FabridInfo) GetDetached() bool { - if x != nil { - return x.Detached - } - return false -} - -type FabridPolicy struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PolicyIdentifier *experimental.FABRIDPolicyIdentifier `protobuf:"bytes,1,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` - PolicyIndex uint32 `protobuf:"varint,2,opt,name=policy_index,json=policyIndex,proto3" json:"policy_index,omitempty"` -} - -func (x *FabridPolicy) Reset() { - *x = FabridPolicy{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FabridPolicy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FabridPolicy) ProtoMessage() {} - -func (x *FabridPolicy) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FabridPolicy.ProtoReflect.Descriptor instead. -func (*FabridPolicy) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{4} -} - -func (x *FabridPolicy) GetPolicyIdentifier() *experimental.FABRIDPolicyIdentifier { - if x != nil { - return x.PolicyIdentifier - } - return nil -} - -func (x *FabridPolicy) GetPolicyIndex() uint32 { - if x != nil { - return x.PolicyIndex - } - return 0 -} - -type FabridKeysRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SrcHost string `protobuf:"bytes,1,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` - DstAs uint64 `protobuf:"varint,2,opt,name=dst_as,json=dstAs,proto3" json:"dst_as,omitempty"` - PathAses []uint64 `protobuf:"varint,3,rep,packed,name=path_ases,json=pathAses,proto3" json:"path_ases,omitempty"` - DstHost *string `protobuf:"bytes,4,opt,name=dst_host,json=dstHost,proto3,oneof" json:"dst_host,omitempty"` -} - -func (x *FabridKeysRequest) Reset() { - *x = FabridKeysRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FabridKeysRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FabridKeysRequest) ProtoMessage() {} - -func (x *FabridKeysRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FabridKeysRequest.ProtoReflect.Descriptor instead. -func (*FabridKeysRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} -} - -func (x *FabridKeysRequest) GetSrcHost() string { - if x != nil { - return x.SrcHost - } - return "" -} - -func (x *FabridKeysRequest) GetDstAs() uint64 { - if x != nil { - return x.DstAs - } - return 0 -} - -func (x *FabridKeysRequest) GetPathAses() []uint64 { - if x != nil { - return x.PathAses - } - return nil -} - -func (x *FabridKeysRequest) GetDstHost() string { - if x != nil && x.DstHost != nil { - return *x.DstHost - } - return "" -} - -type FabridKeyResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` - EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` - Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` -} - -func (x *FabridKeyResponse) Reset() { - *x = FabridKeyResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FabridKeyResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FabridKeyResponse) ProtoMessage() {} - -func (x *FabridKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FabridKeyResponse.ProtoReflect.Descriptor instead. -func (*FabridKeyResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} -} - -func (x *FabridKeyResponse) GetEpochBegin() *timestamppb.Timestamp { - if x != nil { - return x.EpochBegin - } - return nil -} - -func (x *FabridKeyResponse) GetEpochEnd() *timestamppb.Timestamp { - if x != nil { - return x.EpochEnd - } - return nil -} - -func (x *FabridKeyResponse) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -type FabridKeysResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AsHostKeys []*FabridKeyResponse `protobuf:"bytes,1,rep,name=as_host_keys,json=asHostKeys,proto3" json:"as_host_keys,omitempty"` - HostHostKey *FabridKeyResponse `protobuf:"bytes,2,opt,name=host_host_key,json=hostHostKey,proto3,oneof" json:"host_host_key,omitempty"` -} - -func (x *FabridKeysResponse) Reset() { - *x = FabridKeysResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FabridKeysResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FabridKeysResponse) ProtoMessage() {} - -func (x *FabridKeysResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FabridKeysResponse.ProtoReflect.Descriptor instead. -func (*FabridKeysResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} -} - -func (x *FabridKeysResponse) GetAsHostKeys() []*FabridKeyResponse { - if x != nil { - return x.AsHostKeys - } - return nil -} - -func (x *FabridKeysResponse) GetHostHostKey() *FabridKeyResponse { - if x != nil { - return x.HostHostKey - } - return nil -} - type EpicAuths struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -685,7 +369,7 @@ type EpicAuths struct { func (x *EpicAuths) Reset() { *x = EpicAuths{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -698,7 +382,7 @@ func (x *EpicAuths) String() string { func (*EpicAuths) ProtoMessage() {} func (x *EpicAuths) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -711,7 +395,7 @@ func (x *EpicAuths) ProtoReflect() protoreflect.Message { // Deprecated: Use EpicAuths.ProtoReflect.Descriptor instead. func (*EpicAuths) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} } func (x *EpicAuths) GetAuthPhvf() []byte { @@ -740,7 +424,7 @@ type PathInterface struct { func (x *PathInterface) Reset() { *x = PathInterface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -753,7 +437,7 @@ func (x *PathInterface) String() string { func (*PathInterface) ProtoMessage() {} func (x *PathInterface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -766,7 +450,7 @@ func (x *PathInterface) ProtoReflect() protoreflect.Message { // Deprecated: Use PathInterface.ProtoReflect.Descriptor instead. func (*PathInterface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{4} } func (x *PathInterface) GetIsdAs() uint64 { @@ -796,7 +480,7 @@ type GeoCoordinates struct { func (x *GeoCoordinates) Reset() { *x = GeoCoordinates{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -809,7 +493,7 @@ func (x *GeoCoordinates) String() string { func (*GeoCoordinates) ProtoMessage() {} func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -822,7 +506,7 @@ func (x *GeoCoordinates) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoCoordinates.ProtoReflect.Descriptor instead. func (*GeoCoordinates) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} } func (x *GeoCoordinates) GetLatitude() float32 { @@ -857,7 +541,7 @@ type ASRequest struct { func (x *ASRequest) Reset() { *x = ASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -870,7 +554,7 @@ func (x *ASRequest) String() string { func (*ASRequest) ProtoMessage() {} func (x *ASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -883,7 +567,7 @@ func (x *ASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ASRequest.ProtoReflect.Descriptor instead. func (*ASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} } func (x *ASRequest) GetIsdAs() uint64 { @@ -906,7 +590,7 @@ type ASResponse struct { func (x *ASResponse) Reset() { *x = ASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -919,7 +603,7 @@ func (x *ASResponse) String() string { func (*ASResponse) ProtoMessage() {} func (x *ASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -932,7 +616,7 @@ func (x *ASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ASResponse.ProtoReflect.Descriptor instead. func (*ASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} } func (x *ASResponse) GetIsdAs() uint64 { @@ -965,7 +649,7 @@ type InterfacesRequest struct { func (x *InterfacesRequest) Reset() { *x = InterfacesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -978,7 +662,7 @@ func (x *InterfacesRequest) String() string { func (*InterfacesRequest) ProtoMessage() {} func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -991,7 +675,7 @@ func (x *InterfacesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesRequest.ProtoReflect.Descriptor instead. func (*InterfacesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} } type InterfacesResponse struct { @@ -1005,7 +689,7 @@ type InterfacesResponse struct { func (x *InterfacesResponse) Reset() { *x = InterfacesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1018,7 +702,7 @@ func (x *InterfacesResponse) String() string { func (*InterfacesResponse) ProtoMessage() {} func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1031,7 +715,7 @@ func (x *InterfacesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InterfacesResponse.ProtoReflect.Descriptor instead. func (*InterfacesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} } func (x *InterfacesResponse) GetInterfaces() map[uint64]*Interface { @@ -1052,7 +736,7 @@ type Interface struct { func (x *Interface) Reset() { *x = Interface{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1065,7 +749,7 @@ func (x *Interface) String() string { func (*Interface) ProtoMessage() {} func (x *Interface) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1078,7 +762,7 @@ func (x *Interface) ProtoReflect() protoreflect.Message { // Deprecated: Use Interface.ProtoReflect.Descriptor instead. func (*Interface) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} } func (x *Interface) GetAddress() *Underlay { @@ -1097,7 +781,7 @@ type ServicesRequest struct { func (x *ServicesRequest) Reset() { *x = ServicesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1110,7 +794,7 @@ func (x *ServicesRequest) String() string { func (*ServicesRequest) ProtoMessage() {} func (x *ServicesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1123,7 +807,7 @@ func (x *ServicesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesRequest.ProtoReflect.Descriptor instead. func (*ServicesRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} } type ServicesResponse struct { @@ -1137,7 +821,7 @@ type ServicesResponse struct { func (x *ServicesResponse) Reset() { *x = ServicesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1150,7 +834,7 @@ func (x *ServicesResponse) String() string { func (*ServicesResponse) ProtoMessage() {} func (x *ServicesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1163,7 +847,7 @@ func (x *ServicesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ServicesResponse.ProtoReflect.Descriptor instead. func (*ServicesResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} } func (x *ServicesResponse) GetServices() map[string]*ListService { @@ -1184,7 +868,7 @@ type ListService struct { func (x *ListService) Reset() { *x = ListService{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1197,7 +881,7 @@ func (x *ListService) String() string { func (*ListService) ProtoMessage() {} func (x *ListService) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1210,7 +894,7 @@ func (x *ListService) ProtoReflect() protoreflect.Message { // Deprecated: Use ListService.ProtoReflect.Descriptor instead. func (*ListService) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} } func (x *ListService) GetServices() []*Service { @@ -1231,7 +915,7 @@ type Service struct { func (x *Service) Reset() { *x = Service{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1244,7 +928,7 @@ func (x *Service) String() string { func (*Service) ProtoMessage() {} func (x *Service) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1257,7 +941,7 @@ func (x *Service) ProtoReflect() protoreflect.Message { // Deprecated: Use Service.ProtoReflect.Descriptor instead. func (*Service) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} } func (x *Service) GetUri() string { @@ -1278,7 +962,7 @@ type Underlay struct { func (x *Underlay) Reset() { *x = Underlay{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1291,7 +975,7 @@ func (x *Underlay) String() string { func (*Underlay) ProtoMessage() {} func (x *Underlay) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1304,7 +988,7 @@ func (x *Underlay) ProtoReflect() protoreflect.Message { // Deprecated: Use Underlay.ProtoReflect.Descriptor instead. func (*Underlay) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} } func (x *Underlay) GetAddress() string { @@ -1326,7 +1010,7 @@ type NotifyInterfaceDownRequest struct { func (x *NotifyInterfaceDownRequest) Reset() { *x = NotifyInterfaceDownRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1339,7 +1023,7 @@ func (x *NotifyInterfaceDownRequest) String() string { func (*NotifyInterfaceDownRequest) ProtoMessage() {} func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1352,7 +1036,7 @@ func (x *NotifyInterfaceDownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownRequest.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} } func (x *NotifyInterfaceDownRequest) GetIsdAs() uint64 { @@ -1378,7 +1062,7 @@ type NotifyInterfaceDownResponse struct { func (x *NotifyInterfaceDownResponse) Reset() { *x = NotifyInterfaceDownResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1391,7 +1075,7 @@ func (x *NotifyInterfaceDownResponse) String() string { func (*NotifyInterfaceDownResponse) ProtoMessage() {} func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1404,7 +1088,7 @@ func (x *NotifyInterfaceDownResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NotifyInterfaceDownResponse.ProtoReflect.Descriptor instead. func (*NotifyInterfaceDownResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} } type PortRangeResponse struct { @@ -1419,7 +1103,7 @@ type PortRangeResponse struct { func (x *PortRangeResponse) Reset() { *x = PortRangeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1432,7 +1116,7 @@ func (x *PortRangeResponse) String() string { func (*PortRangeResponse) ProtoMessage() {} func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1445,7 +1129,7 @@ func (x *PortRangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PortRangeResponse.ProtoReflect.Descriptor instead. func (*PortRangeResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} } func (x *PortRangeResponse) GetDispatchedPortStart() uint32 { @@ -1477,7 +1161,7 @@ type DRKeyHostASRequest struct { func (x *DRKeyHostASRequest) Reset() { *x = DRKeyHostASRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1490,7 +1174,7 @@ func (x *DRKeyHostASRequest) String() string { func (*DRKeyHostASRequest) ProtoMessage() {} func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1503,7 +1187,7 @@ func (x *DRKeyHostASRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostASRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} } func (x *DRKeyHostASRequest) GetValTime() *timestamppb.Timestamp { @@ -1554,7 +1238,7 @@ type DRKeyHostASResponse struct { func (x *DRKeyHostASResponse) Reset() { *x = DRKeyHostASResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1567,7 +1251,7 @@ func (x *DRKeyHostASResponse) String() string { func (*DRKeyHostASResponse) ProtoMessage() {} func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[25] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1580,7 +1264,7 @@ func (x *DRKeyHostASResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostASResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostASResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{25} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} } func (x *DRKeyHostASResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1619,7 +1303,7 @@ type DRKeyASHostRequest struct { func (x *DRKeyASHostRequest) Reset() { *x = DRKeyASHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1632,7 +1316,7 @@ func (x *DRKeyASHostRequest) String() string { func (*DRKeyASHostRequest) ProtoMessage() {} func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[26] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1645,7 +1329,7 @@ func (x *DRKeyASHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyASHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{26} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} } func (x *DRKeyASHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1696,7 +1380,7 @@ type DRKeyASHostResponse struct { func (x *DRKeyASHostResponse) Reset() { *x = DRKeyASHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[27] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1709,7 +1393,7 @@ func (x *DRKeyASHostResponse) String() string { func (*DRKeyASHostResponse) ProtoMessage() {} func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[27] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1722,7 +1406,7 @@ func (x *DRKeyASHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyASHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyASHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{27} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} } func (x *DRKeyASHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1762,7 +1446,7 @@ type DRKeyHostHostRequest struct { func (x *DRKeyHostHostRequest) Reset() { *x = DRKeyHostHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[28] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1775,7 +1459,7 @@ func (x *DRKeyHostHostRequest) String() string { func (*DRKeyHostHostRequest) ProtoMessage() {} func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[28] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1788,7 +1472,7 @@ func (x *DRKeyHostHostRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostRequest.ProtoReflect.Descriptor instead. func (*DRKeyHostHostRequest) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{28} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{23} } func (x *DRKeyHostHostRequest) GetValTime() *timestamppb.Timestamp { @@ -1846,7 +1530,7 @@ type DRKeyHostHostResponse struct { func (x *DRKeyHostHostResponse) Reset() { *x = DRKeyHostHostResponse{} if protoimpl.UnsafeEnabled { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[29] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1859,7 +1543,7 @@ func (x *DRKeyHostHostResponse) String() string { func (*DRKeyHostHostResponse) ProtoMessage() {} func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_daemon_v1_daemon_proto_msgTypes[29] + mi := &file_proto_daemon_v1_daemon_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1872,7 +1556,7 @@ func (x *DRKeyHostHostResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DRKeyHostHostResponse.ProtoReflect.Descriptor instead. func (*DRKeyHostHostResponse) Descriptor() ([]byte, []int) { - return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{29} + return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{24} } func (x *DRKeyHostHostResponse) GetEpochBegin() *timestamppb.Timestamp { @@ -1909,240 +1593,142 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x72, - 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, - 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, - 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x73, 0x64, 0x41, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, - 0x65, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x66, - 0x65, 0x74, 0x63, 0x68, 0x5f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x64, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x17, 0x66, 0x65, 0x74, 0x63, 0x68, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x44, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, 0x22, 0x3c, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x61, 0x74, - 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, - 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, - 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, - 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x3a, 0x0a, - 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x07, 0x6c, 0x61, 0x74, - 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1c, - 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x03, - 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, - 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x03, 0x67, 0x65, 0x6f, 0x12, - 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6c, - 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x48, 0x6f, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, - 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, - 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x73, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, - 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x29, 0x0a, - 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, - 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, - 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x0b, 0x66, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x66, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, - 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, - 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x22, 0x9b, - 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x68, 0x0a, 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x2e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x46, 0x41, 0x42, 0x52, 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0b, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, - 0x11, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x0a, - 0x06, 0x64, 0x73, 0x74, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, - 0x73, 0x74, 0x41, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x41, 0x73, 0x65, - 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x88, 0x01, - 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x9b, - 0x01, 0x0a, 0x11, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, - 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, - 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xb9, 0x01, 0x0a, - 0x12, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x61, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, - 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, - 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x61, - 0x73, 0x48, 0x6f, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, - 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, - 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x45, 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, - 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, - 0x76, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, - 0x76, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, - 0x36, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, - 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, - 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, - 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, - 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, - 0x09, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, - 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, - 0x73, 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, - 0x75, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, + 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x5f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcf, + 0x01, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x22, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x73, + 0x64, 0x41, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x73, 0x64, 0x41, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x68, + 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, + 0x64, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x66, 0x61, 0x62, + 0x72, 0x69, 0x64, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x70, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x66, 0x65, 0x74, 0x63, 0x68, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x73, + 0x22, 0x3c, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xfd, + 0x04, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, - 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, - 0x79, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, - 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, - 0x59, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x1b, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, - 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, - 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, - 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, - 0x72, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, - 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, - 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, - 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, - 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, - 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, - 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, - 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, - 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, - 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x3a, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, - 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, - 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, - 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, - 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x33, 0x0a, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6c, + 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, + 0x69, 0x64, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x03, 0x67, 0x65, 0x6f, 0x18, 0x08, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x03, 0x67, 0x65, 0x6f, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x6e, + 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x70, 0x73, + 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x48, 0x6f, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x65, 0x70, + 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x52, 0x09, 0x65, 0x70, 0x69, 0x63, + 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x03, 0x52, + 0x0f, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, + 0x12, 0x3c, 0x0a, 0x0b, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x0a, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x45, + 0x0a, 0x09, 0x45, 0x70, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x5f, 0x70, 0x68, 0x76, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, + 0x61, 0x75, 0x74, 0x68, 0x50, 0x68, 0x76, 0x66, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x6c, 0x68, 0x76, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x61, 0x75, 0x74, + 0x68, 0x4c, 0x68, 0x76, 0x66, 0x22, 0x36, 0x0a, 0x0d, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x64, 0x0a, + 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x02, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, + 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, + 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x22, 0x22, 0x0a, 0x09, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x22, 0x49, 0x0a, 0x0a, 0x41, 0x53, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d, + 0x74, 0x75, 0x22, 0x13, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc4, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, + 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x40, + 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0xba, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x1a, 0x59, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x34, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x1b, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x69, 0x22, 0x24, 0x0a, 0x08, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x43, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x69, + 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x64, 0x5f, 0x61, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, + 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x77, 0x0a, 0x11, + 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, + 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x11, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x6f, + 0x72, 0x74, 0x45, 0x6e, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, + 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, @@ -2154,85 +1740,131 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, - 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, - 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, 0x4b, 0x65, + 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x44, 0x52, 0x4b, 0x65, + 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, + 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, + 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, + 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, + 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, + 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x13, 0x44, 0x52, + 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, + 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, - 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, - 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, - 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, - 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, - 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, - 0x10, 0x03, 0x32, 0xf8, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, - 0x0a, 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x57, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, - 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x49, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, - 0x6f, 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, - 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, - 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x14, 0x44, 0x52, + 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, + 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, + 0x49, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x15, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, - 0x79, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, - 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, - 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, - 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, + 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, + 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, + 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, + 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, + 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0xf8, 0x06, 0x0a, 0x0d, 0x44, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, + 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, + 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x5a, 0x0a, 0x0b, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, + 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x41, 0x53, 0x48, 0x6f, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0b, + 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x12, 0x23, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, + 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60, 0x0a, 0x0d, 0x44, 0x52, 0x4b, 0x65, + 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, + 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x46, 0x61, + 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, + 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, + 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2248,106 +1880,97 @@ func file_proto_daemon_v1_daemon_proto_rawDescGZIP() []byte { } var file_proto_daemon_v1_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 32) +var file_proto_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ - (LinkType)(0), // 0: proto.daemon.v1.LinkType - (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest - (*PathsResponse)(nil), // 2: proto.daemon.v1.PathsResponse - (*Path)(nil), // 3: proto.daemon.v1.Path - (*FabridInfo)(nil), // 4: proto.daemon.v1.FabridInfo - (*FabridPolicy)(nil), // 5: proto.daemon.v1.FabridPolicy - (*FabridKeysRequest)(nil), // 6: proto.daemon.v1.FabridKeysRequest - (*FabridKeyResponse)(nil), // 7: proto.daemon.v1.FabridKeyResponse - (*FabridKeysResponse)(nil), // 8: proto.daemon.v1.FabridKeysResponse - (*EpicAuths)(nil), // 9: proto.daemon.v1.EpicAuths - (*PathInterface)(nil), // 10: proto.daemon.v1.PathInterface - (*GeoCoordinates)(nil), // 11: proto.daemon.v1.GeoCoordinates - (*ASRequest)(nil), // 12: proto.daemon.v1.ASRequest - (*ASResponse)(nil), // 13: proto.daemon.v1.ASResponse - (*InterfacesRequest)(nil), // 14: proto.daemon.v1.InterfacesRequest - (*InterfacesResponse)(nil), // 15: proto.daemon.v1.InterfacesResponse - (*Interface)(nil), // 16: proto.daemon.v1.Interface - (*ServicesRequest)(nil), // 17: proto.daemon.v1.ServicesRequest - (*ServicesResponse)(nil), // 18: proto.daemon.v1.ServicesResponse - (*ListService)(nil), // 19: proto.daemon.v1.ListService - (*Service)(nil), // 20: proto.daemon.v1.Service - (*Underlay)(nil), // 21: proto.daemon.v1.Underlay - (*NotifyInterfaceDownRequest)(nil), // 22: proto.daemon.v1.NotifyInterfaceDownRequest - (*NotifyInterfaceDownResponse)(nil), // 23: proto.daemon.v1.NotifyInterfaceDownResponse - (*PortRangeResponse)(nil), // 24: proto.daemon.v1.PortRangeResponse - (*DRKeyHostASRequest)(nil), // 25: proto.daemon.v1.DRKeyHostASRequest - (*DRKeyHostASResponse)(nil), // 26: proto.daemon.v1.DRKeyHostASResponse - (*DRKeyASHostRequest)(nil), // 27: proto.daemon.v1.DRKeyASHostRequest - (*DRKeyASHostResponse)(nil), // 28: proto.daemon.v1.DRKeyASHostResponse - (*DRKeyHostHostRequest)(nil), // 29: proto.daemon.v1.DRKeyHostHostRequest - (*DRKeyHostHostResponse)(nil), // 30: proto.daemon.v1.DRKeyHostHostResponse - nil, // 31: proto.daemon.v1.InterfacesResponse.InterfacesEntry - nil, // 32: proto.daemon.v1.ServicesResponse.ServicesEntry - (*timestamppb.Timestamp)(nil), // 33: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 34: google.protobuf.Duration - (*experimental.FABRIDPolicyIdentifier)(nil), // 35: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier - (drkey.Protocol)(0), // 36: proto.drkey.v1.Protocol - (*emptypb.Empty)(nil), // 37: google.protobuf.Empty + (LinkType)(0), // 0: proto.daemon.v1.LinkType + (*PathsRequest)(nil), // 1: proto.daemon.v1.PathsRequest + (*PathsResponse)(nil), // 2: proto.daemon.v1.PathsResponse + (*Path)(nil), // 3: proto.daemon.v1.Path + (*EpicAuths)(nil), // 4: proto.daemon.v1.EpicAuths + (*PathInterface)(nil), // 5: proto.daemon.v1.PathInterface + (*GeoCoordinates)(nil), // 6: proto.daemon.v1.GeoCoordinates + (*ASRequest)(nil), // 7: proto.daemon.v1.ASRequest + (*ASResponse)(nil), // 8: proto.daemon.v1.ASResponse + (*InterfacesRequest)(nil), // 9: proto.daemon.v1.InterfacesRequest + (*InterfacesResponse)(nil), // 10: proto.daemon.v1.InterfacesResponse + (*Interface)(nil), // 11: proto.daemon.v1.Interface + (*ServicesRequest)(nil), // 12: proto.daemon.v1.ServicesRequest + (*ServicesResponse)(nil), // 13: proto.daemon.v1.ServicesResponse + (*ListService)(nil), // 14: proto.daemon.v1.ListService + (*Service)(nil), // 15: proto.daemon.v1.Service + (*Underlay)(nil), // 16: proto.daemon.v1.Underlay + (*NotifyInterfaceDownRequest)(nil), // 17: proto.daemon.v1.NotifyInterfaceDownRequest + (*NotifyInterfaceDownResponse)(nil), // 18: proto.daemon.v1.NotifyInterfaceDownResponse + (*PortRangeResponse)(nil), // 19: proto.daemon.v1.PortRangeResponse + (*DRKeyHostASRequest)(nil), // 20: proto.daemon.v1.DRKeyHostASRequest + (*DRKeyHostASResponse)(nil), // 21: proto.daemon.v1.DRKeyHostASResponse + (*DRKeyASHostRequest)(nil), // 22: proto.daemon.v1.DRKeyASHostRequest + (*DRKeyASHostResponse)(nil), // 23: proto.daemon.v1.DRKeyASHostResponse + (*DRKeyHostHostRequest)(nil), // 24: proto.daemon.v1.DRKeyHostHostRequest + (*DRKeyHostHostResponse)(nil), // 25: proto.daemon.v1.DRKeyHostHostResponse + nil, // 26: proto.daemon.v1.InterfacesResponse.InterfacesEntry + nil, // 27: proto.daemon.v1.ServicesResponse.ServicesEntry + (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 29: google.protobuf.Duration + (*FabridInfo)(nil), // 30: proto.daemon.v1.FabridInfo + (drkey.Protocol)(0), // 31: proto.drkey.v1.Protocol + (*emptypb.Empty)(nil), // 32: google.protobuf.Empty + (*FabridKeysRequest)(nil), // 33: proto.daemon.v1.FabridKeysRequest + (*FabridKeysResponse)(nil), // 34: proto.daemon.v1.FabridKeysResponse } var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 3, // 0: proto.daemon.v1.PathsResponse.paths:type_name -> proto.daemon.v1.Path - 16, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface - 10, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface - 33, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp - 34, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration - 11, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates + 11, // 1: proto.daemon.v1.Path.interface:type_name -> proto.daemon.v1.Interface + 5, // 2: proto.daemon.v1.Path.interfaces:type_name -> proto.daemon.v1.PathInterface + 28, // 3: proto.daemon.v1.Path.expiration:type_name -> google.protobuf.Timestamp + 29, // 4: proto.daemon.v1.Path.latency:type_name -> google.protobuf.Duration + 6, // 5: proto.daemon.v1.Path.geo:type_name -> proto.daemon.v1.GeoCoordinates 0, // 6: proto.daemon.v1.Path.link_type:type_name -> proto.daemon.v1.LinkType - 9, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths - 4, // 8: proto.daemon.v1.Path.fabrid_info:type_name -> proto.daemon.v1.FabridInfo - 5, // 9: proto.daemon.v1.FabridInfo.policies:type_name -> proto.daemon.v1.FabridPolicy - 35, // 10: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier - 33, // 11: proto.daemon.v1.FabridKeyResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 33, // 12: proto.daemon.v1.FabridKeyResponse.epoch_end:type_name -> google.protobuf.Timestamp - 7, // 13: proto.daemon.v1.FabridKeysResponse.as_host_keys:type_name -> proto.daemon.v1.FabridKeyResponse - 7, // 14: proto.daemon.v1.FabridKeysResponse.host_host_key:type_name -> proto.daemon.v1.FabridKeyResponse - 31, // 15: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry - 21, // 16: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay - 32, // 17: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry - 20, // 18: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service - 33, // 19: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp - 36, // 20: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 33, // 21: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 33, // 22: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp - 33, // 23: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp - 36, // 24: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 33, // 25: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 33, // 26: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 33, // 27: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp - 36, // 28: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol - 33, // 29: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp - 33, // 30: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp - 16, // 31: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface - 19, // 32: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService - 1, // 33: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest - 12, // 34: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest - 14, // 35: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest - 17, // 36: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest - 22, // 37: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest - 37, // 38: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty - 27, // 39: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest - 25, // 40: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest - 29, // 41: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest - 6, // 42: proto.daemon.v1.DaemonService.FabridKeys:input_type -> proto.daemon.v1.FabridKeysRequest - 2, // 43: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse - 13, // 44: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse - 15, // 45: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse - 18, // 46: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse - 23, // 47: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse - 24, // 48: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse - 28, // 49: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse - 26, // 50: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse - 30, // 51: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse - 8, // 52: proto.daemon.v1.DaemonService.FabridKeys:output_type -> proto.daemon.v1.FabridKeysResponse - 43, // [43:53] is the sub-list for method output_type - 33, // [33:43] is the sub-list for method input_type - 33, // [33:33] is the sub-list for extension type_name - 33, // [33:33] is the sub-list for extension extendee - 0, // [0:33] is the sub-list for field type_name + 4, // 7: proto.daemon.v1.Path.epic_auths:type_name -> proto.daemon.v1.EpicAuths + 30, // 8: proto.daemon.v1.Path.fabrid_info:type_name -> proto.daemon.v1.FabridInfo + 26, // 9: proto.daemon.v1.InterfacesResponse.interfaces:type_name -> proto.daemon.v1.InterfacesResponse.InterfacesEntry + 16, // 10: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay + 27, // 11: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry + 15, // 12: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service + 28, // 13: proto.daemon.v1.DRKeyHostASRequest.val_time:type_name -> google.protobuf.Timestamp + 31, // 14: proto.daemon.v1.DRKeyHostASRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 28, // 15: proto.daemon.v1.DRKeyHostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 28, // 16: proto.daemon.v1.DRKeyHostASResponse.epoch_end:type_name -> google.protobuf.Timestamp + 28, // 17: proto.daemon.v1.DRKeyASHostRequest.val_time:type_name -> google.protobuf.Timestamp + 31, // 18: proto.daemon.v1.DRKeyASHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 28, // 19: proto.daemon.v1.DRKeyASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 28, // 20: proto.daemon.v1.DRKeyASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 28, // 21: proto.daemon.v1.DRKeyHostHostRequest.val_time:type_name -> google.protobuf.Timestamp + 31, // 22: proto.daemon.v1.DRKeyHostHostRequest.protocol_id:type_name -> proto.drkey.v1.Protocol + 28, // 23: proto.daemon.v1.DRKeyHostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 28, // 24: proto.daemon.v1.DRKeyHostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 11, // 25: proto.daemon.v1.InterfacesResponse.InterfacesEntry.value:type_name -> proto.daemon.v1.Interface + 14, // 26: proto.daemon.v1.ServicesResponse.ServicesEntry.value:type_name -> proto.daemon.v1.ListService + 1, // 27: proto.daemon.v1.DaemonService.Paths:input_type -> proto.daemon.v1.PathsRequest + 7, // 28: proto.daemon.v1.DaemonService.AS:input_type -> proto.daemon.v1.ASRequest + 9, // 29: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest + 12, // 30: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest + 17, // 31: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest + 32, // 32: proto.daemon.v1.DaemonService.PortRange:input_type -> google.protobuf.Empty + 22, // 33: proto.daemon.v1.DaemonService.DRKeyASHost:input_type -> proto.daemon.v1.DRKeyASHostRequest + 20, // 34: proto.daemon.v1.DaemonService.DRKeyHostAS:input_type -> proto.daemon.v1.DRKeyHostASRequest + 24, // 35: proto.daemon.v1.DaemonService.DRKeyHostHost:input_type -> proto.daemon.v1.DRKeyHostHostRequest + 33, // 36: proto.daemon.v1.DaemonService.FabridKeys:input_type -> proto.daemon.v1.FabridKeysRequest + 2, // 37: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse + 8, // 38: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse + 10, // 39: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse + 13, // 40: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse + 18, // 41: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse + 19, // 42: proto.daemon.v1.DaemonService.PortRange:output_type -> proto.daemon.v1.PortRangeResponse + 23, // 43: proto.daemon.v1.DaemonService.DRKeyASHost:output_type -> proto.daemon.v1.DRKeyASHostResponse + 21, // 44: proto.daemon.v1.DaemonService.DRKeyHostAS:output_type -> proto.daemon.v1.DRKeyHostASResponse + 25, // 45: proto.daemon.v1.DaemonService.DRKeyHostHost:output_type -> proto.daemon.v1.DRKeyHostHostResponse + 34, // 46: proto.daemon.v1.DaemonService.FabridKeys:output_type -> proto.daemon.v1.FabridKeysResponse + 37, // [37:47] is the sub-list for method output_type + 27, // [27:37] is the sub-list for method input_type + 27, // [27:27] is the sub-list for extension type_name + 27, // [27:27] is the sub-list for extension extendee + 0, // [0:27] is the sub-list for field type_name } func init() { file_proto_daemon_v1_daemon_proto_init() } @@ -2355,6 +1978,7 @@ func file_proto_daemon_v1_daemon_proto_init() { if File_proto_daemon_v1_daemon_proto != nil { return } + file_proto_daemon_v1_daemon_fabrid_proto_init() if !protoimpl.UnsafeEnabled { file_proto_daemon_v1_daemon_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PathsRequest); i { @@ -2393,66 +2017,6 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_daemon_v1_daemon_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridPolicy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_daemon_v1_daemon_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridKeysRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_daemon_v1_daemon_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridKeyResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_daemon_v1_daemon_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FabridKeysResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_daemon_v1_daemon_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EpicAuths); i { case 0: return &v.state @@ -2464,7 +2028,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PathInterface); i { case 0: return &v.state @@ -2476,7 +2040,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeoCoordinates); i { case 0: return &v.state @@ -2488,7 +2052,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ASRequest); i { case 0: return &v.state @@ -2500,7 +2064,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ASResponse); i { case 0: return &v.state @@ -2512,7 +2076,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InterfacesRequest); i { case 0: return &v.state @@ -2524,7 +2088,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InterfacesResponse); i { case 0: return &v.state @@ -2536,7 +2100,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Interface); i { case 0: return &v.state @@ -2548,7 +2112,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServicesRequest); i { case 0: return &v.state @@ -2560,7 +2124,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServicesResponse); i { case 0: return &v.state @@ -2572,7 +2136,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListService); i { case 0: return &v.state @@ -2584,7 +2148,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Service); i { case 0: return &v.state @@ -2596,7 +2160,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Underlay); i { case 0: return &v.state @@ -2608,7 +2172,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NotifyInterfaceDownRequest); i { case 0: return &v.state @@ -2620,7 +2184,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NotifyInterfaceDownResponse); i { case 0: return &v.state @@ -2632,7 +2196,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PortRangeResponse); i { case 0: return &v.state @@ -2644,7 +2208,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostASRequest); i { case 0: return &v.state @@ -2656,7 +2220,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostASResponse); i { case 0: return &v.state @@ -2668,7 +2232,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyASHostRequest); i { case 0: return &v.state @@ -2680,7 +2244,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyASHostResponse); i { case 0: return &v.state @@ -2692,7 +2256,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostHostRequest); i { case 0: return &v.state @@ -2704,7 +2268,7 @@ func file_proto_daemon_v1_daemon_proto_init() { return nil } } - file_proto_daemon_v1_daemon_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_proto_daemon_v1_daemon_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DRKeyHostHostResponse); i { case 0: return &v.state @@ -2717,15 +2281,13 @@ func file_proto_daemon_v1_daemon_proto_init() { } } } - file_proto_daemon_v1_daemon_proto_msgTypes[5].OneofWrappers = []interface{}{} - file_proto_daemon_v1_daemon_proto_msgTypes[7].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_daemon_v1_daemon_proto_rawDesc, NumEnums: 1, - NumMessages: 32, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/proto/daemon/daemon_fabrid.pb.go b/pkg/proto/daemon/daemon_fabrid.pb.go new file mode 100644 index 0000000000..7c03833634 --- /dev/null +++ b/pkg/proto/daemon/daemon_fabrid.pb.go @@ -0,0 +1,531 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.10 +// source: proto/daemon/v1/daemon_fabrid.proto + +package daemon + +import ( + experimental "github.com/scionproto/scion/pkg/proto/control_plane/experimental" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FabridInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Digest []byte `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"` + Policies []*FabridPolicy `protobuf:"bytes,3,rep,name=policies,proto3" json:"policies,omitempty"` + Detached bool `protobuf:"varint,4,opt,name=detached,proto3" json:"detached,omitempty"` +} + +func (x *FabridInfo) Reset() { + *x = FabridInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridInfo) ProtoMessage() {} + +func (x *FabridInfo) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridInfo.ProtoReflect.Descriptor instead. +func (*FabridInfo) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP(), []int{0} +} + +func (x *FabridInfo) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *FabridInfo) GetDigest() []byte { + if x != nil { + return x.Digest + } + return nil +} + +func (x *FabridInfo) GetPolicies() []*FabridPolicy { + if x != nil { + return x.Policies + } + return nil +} + +func (x *FabridInfo) GetDetached() bool { + if x != nil { + return x.Detached + } + return false +} + +type FabridPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PolicyIdentifier *experimental.FABRIDPolicyIdentifier `protobuf:"bytes,1,opt,name=policy_identifier,json=policyIdentifier,proto3" json:"policy_identifier,omitempty"` + PolicyIndex uint32 `protobuf:"varint,2,opt,name=policy_index,json=policyIndex,proto3" json:"policy_index,omitempty"` +} + +func (x *FabridPolicy) Reset() { + *x = FabridPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridPolicy) ProtoMessage() {} + +func (x *FabridPolicy) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridPolicy.ProtoReflect.Descriptor instead. +func (*FabridPolicy) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP(), []int{1} +} + +func (x *FabridPolicy) GetPolicyIdentifier() *experimental.FABRIDPolicyIdentifier { + if x != nil { + return x.PolicyIdentifier + } + return nil +} + +func (x *FabridPolicy) GetPolicyIndex() uint32 { + if x != nil { + return x.PolicyIndex + } + return 0 +} + +type FabridKeysRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SrcHost string `protobuf:"bytes,1,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` + DstAs uint64 `protobuf:"varint,2,opt,name=dst_as,json=dstAs,proto3" json:"dst_as,omitempty"` + PathAses []uint64 `protobuf:"varint,3,rep,packed,name=path_ases,json=pathAses,proto3" json:"path_ases,omitempty"` + DstHost *string `protobuf:"bytes,4,opt,name=dst_host,json=dstHost,proto3,oneof" json:"dst_host,omitempty"` +} + +func (x *FabridKeysRequest) Reset() { + *x = FabridKeysRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeysRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeysRequest) ProtoMessage() {} + +func (x *FabridKeysRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeysRequest.ProtoReflect.Descriptor instead. +func (*FabridKeysRequest) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP(), []int{2} +} + +func (x *FabridKeysRequest) GetSrcHost() string { + if x != nil { + return x.SrcHost + } + return "" +} + +func (x *FabridKeysRequest) GetDstAs() uint64 { + if x != nil { + return x.DstAs + } + return 0 +} + +func (x *FabridKeysRequest) GetPathAses() []uint64 { + if x != nil { + return x.PathAses + } + return nil +} + +func (x *FabridKeysRequest) GetDstHost() string { + if x != nil && x.DstHost != nil { + return *x.DstHost + } + return "" +} + +type FabridKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *FabridKeyResponse) Reset() { + *x = FabridKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeyResponse) ProtoMessage() {} + +func (x *FabridKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeyResponse.ProtoReflect.Descriptor instead. +func (*FabridKeyResponse) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP(), []int{3} +} + +func (x *FabridKeyResponse) GetEpochBegin() *timestamppb.Timestamp { + if x != nil { + return x.EpochBegin + } + return nil +} + +func (x *FabridKeyResponse) GetEpochEnd() *timestamppb.Timestamp { + if x != nil { + return x.EpochEnd + } + return nil +} + +func (x *FabridKeyResponse) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +type FabridKeysResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AsHostKeys []*FabridKeyResponse `protobuf:"bytes,1,rep,name=as_host_keys,json=asHostKeys,proto3" json:"as_host_keys,omitempty"` + HostHostKey *FabridKeyResponse `protobuf:"bytes,2,opt,name=host_host_key,json=hostHostKey,proto3,oneof" json:"host_host_key,omitempty"` +} + +func (x *FabridKeysResponse) Reset() { + *x = FabridKeysResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FabridKeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FabridKeysResponse) ProtoMessage() {} + +func (x *FabridKeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FabridKeysResponse.ProtoReflect.Descriptor instead. +func (*FabridKeysResponse) Descriptor() ([]byte, []int) { + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP(), []int{4} +} + +func (x *FabridKeysResponse) GetAsHostKeys() []*FabridKeyResponse { + if x != nil { + return x.AsHostKeys + } + return nil +} + +func (x *FabridKeysResponse) GetHostHostKey() *FabridKeyResponse { + if x != nil { + return x.HostHostKey + } + return nil +} + +var File_proto_daemon_v1_daemon_fabrid_proto protoreflect.FileDescriptor + +var file_proto_daemon_v1_daemon_fabrid_proto_rawDesc = []byte{ + 0x0a, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, + 0x31, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x62, 0x72, 0x69, 0x64, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x65, 0x78, 0x70, + 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x62, + 0x72, 0x69, 0x64, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x0a, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, + 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x22, 0x9b, 0x01, 0x0a, + 0x0c, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x68, 0x0a, + 0x11, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x65, + 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x46, + 0x41, 0x42, 0x52, 0x49, 0x44, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x10, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x8f, 0x01, 0x0a, 0x11, 0x46, + 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x64, + 0x73, 0x74, 0x5f, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, + 0x41, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x41, 0x73, 0x65, 0x73, 0x12, + 0x1e, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x88, 0x01, 0x01, 0x42, + 0x0b, 0x0a, 0x09, 0x5f, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x22, 0x9b, 0x01, 0x0a, + 0x11, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, + 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xb9, 0x01, 0x0a, 0x12, 0x46, + 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x61, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x61, 0x73, 0x48, + 0x6f, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x46, 0x61, 0x62, 0x72, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x68, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x4b, 0x65, + 0x79, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_daemon_v1_daemon_fabrid_proto_rawDescOnce sync.Once + file_proto_daemon_v1_daemon_fabrid_proto_rawDescData = file_proto_daemon_v1_daemon_fabrid_proto_rawDesc +) + +func file_proto_daemon_v1_daemon_fabrid_proto_rawDescGZIP() []byte { + file_proto_daemon_v1_daemon_fabrid_proto_rawDescOnce.Do(func() { + file_proto_daemon_v1_daemon_fabrid_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_daemon_v1_daemon_fabrid_proto_rawDescData) + }) + return file_proto_daemon_v1_daemon_fabrid_proto_rawDescData +} + +var file_proto_daemon_v1_daemon_fabrid_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_proto_daemon_v1_daemon_fabrid_proto_goTypes = []interface{}{ + (*FabridInfo)(nil), // 0: proto.daemon.v1.FabridInfo + (*FabridPolicy)(nil), // 1: proto.daemon.v1.FabridPolicy + (*FabridKeysRequest)(nil), // 2: proto.daemon.v1.FabridKeysRequest + (*FabridKeyResponse)(nil), // 3: proto.daemon.v1.FabridKeyResponse + (*FabridKeysResponse)(nil), // 4: proto.daemon.v1.FabridKeysResponse + (*experimental.FABRIDPolicyIdentifier)(nil), // 5: proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp +} +var file_proto_daemon_v1_daemon_fabrid_proto_depIdxs = []int32{ + 1, // 0: proto.daemon.v1.FabridInfo.policies:type_name -> proto.daemon.v1.FabridPolicy + 5, // 1: proto.daemon.v1.FabridPolicy.policy_identifier:type_name -> proto.control_plane.experimental.v1.FABRIDPolicyIdentifier + 6, // 2: proto.daemon.v1.FabridKeyResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 6, // 3: proto.daemon.v1.FabridKeyResponse.epoch_end:type_name -> google.protobuf.Timestamp + 3, // 4: proto.daemon.v1.FabridKeysResponse.as_host_keys:type_name -> proto.daemon.v1.FabridKeyResponse + 3, // 5: proto.daemon.v1.FabridKeysResponse.host_host_key:type_name -> proto.daemon.v1.FabridKeyResponse + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_proto_daemon_v1_daemon_fabrid_proto_init() } +func file_proto_daemon_v1_daemon_fabrid_proto_init() { + if File_proto_daemon_v1_daemon_fabrid_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FabridInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FabridPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FabridKeysRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FabridKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FabridKeysResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_proto_daemon_v1_daemon_fabrid_proto_msgTypes[4].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_daemon_v1_daemon_fabrid_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_daemon_v1_daemon_fabrid_proto_goTypes, + DependencyIndexes: file_proto_daemon_v1_daemon_fabrid_proto_depIdxs, + MessageInfos: file_proto_daemon_v1_daemon_fabrid_proto_msgTypes, + }.Build() + File_proto_daemon_v1_daemon_fabrid_proto = out.File + file_proto_daemon_v1_daemon_fabrid_proto_rawDesc = nil + file_proto_daemon_v1_daemon_fabrid_proto_goTypes = nil + file_proto_daemon_v1_daemon_fabrid_proto_depIdxs = nil +} diff --git a/pkg/snet/BUILD.bazel b/pkg/snet/BUILD.bazel index c8ea9c18a9..6d5e1e103e 100644 --- a/pkg/snet/BUILD.bazel +++ b/pkg/snet/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "packet.go", "packet_conn.go", "path.go", + "path_fabrid.go", "reader.go", "reply_pather.go", "router.go", diff --git a/pkg/snet/path.go b/pkg/snet/path.go index f0a54797d4..db851bbb2c 100644 --- a/pkg/snet/path.go +++ b/pkg/snet/path.go @@ -86,20 +86,6 @@ func (iface PathInterface) String() string { return fmt.Sprintf("%s#%d", iface.IA, iface.ID) } -// HopInterface represents a single hop on the path -type HopInterface struct { - // IgIf represents the ingress interface ID for a hop in the path. - IgIf common.IFIDType - // EgIf represents the ingress interface ID for a hop in the path. - EgIf common.IFIDType - // IA is the ISD AS identifier of the hop. - IA addr.IA - // FabridEnabled indicates whether FABRID is enabled on this hop. - FabridEnabled bool - // Policies are the FABRID Policies that are supported by this hop. - Policies []*fabrid.Policy -} - // EpicAuths is a container for the EPIC hop authenticators. type EpicAuths struct { // AuthPHVF is the authenticator for the penultimate hop. @@ -112,20 +98,6 @@ func (ea *EpicAuths) SupportsEpic() bool { return (len(ea.AuthPHVF) == 16 && len(ea.AuthLHVF) == 16) } -type FabridInfo struct { - // Enabled contains a boolean indicating whether the hop supports FABRID. - Enabled bool - // Policies Contains the policy identifiers that can be used on this hop - Policies []*fabrid.Policy - // Digest contains the FABRID digest for the AS. This is used when the - // FABRID extension is detached. - Digest []byte - // Detached indicates whether the FABRID maps have been detached from the PCB for this hop. - // This can happen as the PCB is propagated, or when the AS does not add the detachable FABRID - // extension. - Detached bool -} - // PathMetadata contains supplementary information about a path. // // The information about MTU, Latency, Bandwidth etc. are based solely on data @@ -187,42 +159,6 @@ type PathMetadata struct { FabridInfo []FabridInfo } -func (pm *PathMetadata) Hops() []HopInterface { - ifaces := pm.Interfaces - fabrid := pm.FabridInfo - switch { - case len(ifaces)%2 != 0 || (len(fabrid) != len(ifaces)/2+1): - return []HopInterface{} - case len(ifaces) == 0 || len(fabrid) == 0: - return []HopInterface{} - default: - hops := make([]HopInterface, 0, len(ifaces)/2+1) - hops = append(hops, HopInterface{ - IA: ifaces[0].IA, - IgIf: 0, - EgIf: ifaces[0].ID, - FabridEnabled: fabrid[0].Enabled, - Policies: fabrid[0].Policies}) - for i := 1; i < len(ifaces)-1; i += 2 { - hops = append(hops, HopInterface{ - IA: ifaces[i].IA, - IgIf: ifaces[i].ID, - EgIf: ifaces[i+1].ID, - FabridEnabled: fabrid[(i+1)/2].Enabled, - Policies: fabrid[(i+1)/2].Policies, - }) - } - hops = append(hops, HopInterface{ - IA: ifaces[len(ifaces)-1].IA, - IgIf: ifaces[len(ifaces)-1].ID, - EgIf: 0, - FabridEnabled: fabrid[len(ifaces)/2].Enabled, - Policies: fabrid[len(ifaces)/2].Policies, - }) - return hops - } -} - func (pm *PathMetadata) Copy() *PathMetadata { if pm == nil { return nil diff --git a/pkg/snet/path/BUILD.bazel b/pkg/snet/path/BUILD.bazel index 4f9c63b3a6..4a0a2fdcdb 100644 --- a/pkg/snet/path/BUILD.bazel +++ b/pkg/snet/path/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "fabrid.go", "onehop.go", "path.go", + "path_ext.go", "scion.go", ], importpath = "github.com/scionproto/scion/pkg/snet/path", diff --git a/pkg/snet/path/empty.go b/pkg/snet/path/empty.go index c1be3f997b..f0e7c60864 100644 --- a/pkg/snet/path/empty.go +++ b/pkg/snet/path/empty.go @@ -17,7 +17,6 @@ package path import ( "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path/empty" - "github.com/scionproto/scion/pkg/snet" ) type Empty struct{} @@ -26,7 +25,3 @@ func (e Empty) SetPath(s *slayers.SCION) error { s.Path, s.PathType = empty.Path{}, empty.PathType return nil } - -func (e Empty) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { - return nil -} diff --git a/pkg/snet/path/epic.go b/pkg/snet/path/epic.go index ef064dfc97..a3e44bb585 100644 --- a/pkg/snet/path/epic.go +++ b/pkg/snet/path/epic.go @@ -94,7 +94,3 @@ func (e *EPIC) SetPath(s *slayers.SCION) error { s.Path, s.PathType = ep, ep.Type() return nil } - -func (e *EPIC) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { - return nil -} diff --git a/pkg/snet/path/onehop.go b/pkg/snet/path/onehop.go index 255f911fde..6c6bcf0c56 100644 --- a/pkg/snet/path/onehop.go +++ b/pkg/snet/path/onehop.go @@ -24,7 +24,6 @@ import ( "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/onehop" - "github.com/scionproto/scion/pkg/snet" ) type OneHop struct { @@ -43,10 +42,6 @@ func (p OneHop) SetPath(s *slayers.SCION) error { return nil } -func (p OneHop) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { - return nil -} - // NewOneHop creates a onehop path that has the first hopfield initialized. func NewOneHop( egress uint16, diff --git a/pkg/snet/path/path_ext.go b/pkg/snet/path/path_ext.go new file mode 100644 index 0000000000..eb5ef860c4 --- /dev/null +++ b/pkg/snet/path/path_ext.go @@ -0,0 +1,36 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package path + +import ( + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/snet" +) + +func (e Empty) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { + return nil +} + +func (e *EPIC) SetExtensions(s *slayers.SCION, p *snet.PacketInfo) error { + return nil +} + +func (p OneHop) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { + return nil +} + +func (p SCION) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { + return nil +} diff --git a/pkg/snet/path/scion.go b/pkg/snet/path/scion.go index a9b6a3ee68..a146e4a7ee 100644 --- a/pkg/snet/path/scion.go +++ b/pkg/snet/path/scion.go @@ -18,7 +18,6 @@ import ( "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/slayers" "github.com/scionproto/scion/pkg/slayers/path/scion" - "github.com/scionproto/scion/pkg/snet" ) type SCION struct { @@ -44,7 +43,3 @@ func (p SCION) SetPath(s *slayers.SCION) error { s.Path, s.PathType = &sp, sp.Type() return nil } - -func (p SCION) SetExtensions(s *slayers.SCION, pi *snet.PacketInfo) error { - return nil -} diff --git a/pkg/snet/path_fabrid.go b/pkg/snet/path_fabrid.go new file mode 100644 index 0000000000..d479c3e0e1 --- /dev/null +++ b/pkg/snet/path_fabrid.go @@ -0,0 +1,85 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package snet + +import ( + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/experimental/fabrid" + "github.com/scionproto/scion/pkg/private/common" +) + +// HopInterface represents a single hop on the path +type HopInterface struct { + // IgIf represents the ingress interface ID for a hop in the path. + IgIf common.IFIDType + // EgIf represents the ingress interface ID for a hop in the path. + EgIf common.IFIDType + // IA is the ISD AS identifier of the hop. + IA addr.IA + // FabridEnabled indicates whether FABRID is enabled on this hop. + FabridEnabled bool + // Policies are the FABRID Policies that are supported by this hop. + Policies []*fabrid.Policy +} + +type FabridInfo struct { + // Enabled contains a boolean indicating whether the hop supports FABRID. + Enabled bool + // Policies Contains the policy identifiers that can be used on this hop + Policies []*fabrid.Policy + // Digest contains the FABRID digest for the AS. This is used when the + // FABRID extension is detached. + Digest []byte + // Detached indicates whether the FABRID maps have been detached from the PCB for this hop. + // This can happen as the PCB is propagated, or when the AS does not add the detachable FABRID + // extension. + Detached bool +} + +func (pm *PathMetadata) Hops() []HopInterface { + ifaces := pm.Interfaces + fabrid := pm.FabridInfo + switch { + case len(ifaces)%2 != 0 || (len(fabrid) != len(ifaces)/2+1): + return []HopInterface{} + case len(ifaces) == 0 || len(fabrid) == 0: + return []HopInterface{} + default: + hops := make([]HopInterface, 0, len(ifaces)/2+1) + hops = append(hops, HopInterface{ + IA: ifaces[0].IA, + IgIf: 0, + EgIf: ifaces[0].ID, + FabridEnabled: fabrid[0].Enabled, + Policies: fabrid[0].Policies}) + for i := 1; i < len(ifaces)-1; i += 2 { + hops = append(hops, HopInterface{ + IA: ifaces[i].IA, + IgIf: ifaces[i].ID, + EgIf: ifaces[i+1].ID, + FabridEnabled: fabrid[(i+1)/2].Enabled, + Policies: fabrid[(i+1)/2].Policies, + }) + } + hops = append(hops, HopInterface{ + IA: ifaces[len(ifaces)-1].IA, + IgIf: ifaces[len(ifaces)-1].ID, + EgIf: 0, + FabridEnabled: fabrid[len(ifaces)/2].Enabled, + Policies: fabrid[len(ifaces)/2].Policies, + }) + return hops + } +} diff --git a/proto/control_plane/experimental/v1/BUILD.bazel b/proto/control_plane/experimental/v1/BUILD.bazel index 0ce5267386..14793ddbbc 100644 --- a/proto/control_plane/experimental/v1/BUILD.bazel +++ b/proto/control_plane/experimental/v1/BUILD.bazel @@ -6,6 +6,7 @@ proto_library( "fabrid.proto", "fabrid_extensions.proto", "seg_detached_extensions.proto", + "seg_detached_extensions_fabrid.proto", ], visibility = ["//visibility:public"], deps = [ diff --git a/proto/control_plane/experimental/v1/seg_detached_extensions.proto b/proto/control_plane/experimental/v1/seg_detached_extensions.proto index bba43d9e92..0d26c5fb16 100644 --- a/proto/control_plane/experimental/v1/seg_detached_extensions.proto +++ b/proto/control_plane/experimental/v1/seg_detached_extensions.proto @@ -18,18 +18,9 @@ option go_package = "github.com/scionproto/scion/pkg/proto/control_plane/experim package proto.control_plane.experimental.v1; -import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; - - message EPICDetachedExtension { // Remaining bytes of the full MAC in the hop entry. bytes auth_hop_entry = 1; // Remaining bytes of the full MAC in the peer entries. repeated bytes auth_peer_entries = 2; } - - -message FABRIDDetachedExtension { - // The I and D-map of FABRID - proto.control_plane.experimental.v1.FABRIDDetachableMaps maps = 1; -} diff --git a/proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto b/proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto new file mode 100644 index 0000000000..35145e44d3 --- /dev/null +++ b/proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto @@ -0,0 +1,26 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option go_package = "github.com/scionproto/scion/pkg/proto/control_plane/experimental"; + +package proto.control_plane.experimental.v1; + +import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; + +message FABRIDDetachedExtension { + // The I and D-map of FABRID + proto.control_plane.experimental.v1.FABRIDDetachableMaps maps = 1; +} \ No newline at end of file diff --git a/proto/control_plane/v1/seg_extensions.proto b/proto/control_plane/v1/seg_extensions.proto index a4984089da..7ff907cc9d 100644 --- a/proto/control_plane/v1/seg_extensions.proto +++ b/proto/control_plane/v1/seg_extensions.proto @@ -19,6 +19,7 @@ option go_package = "github.com/scionproto/scion/pkg/proto/control_plane"; package proto.control_plane.v1; import "proto/control_plane/experimental/v1/seg_detached_extensions.proto"; +import "proto/control_plane/experimental/v1/seg_detached_extensions_fabrid.proto"; message PathSegmentExtensions { // Optional static info extension. diff --git a/proto/daemon/v1/BUILD.bazel b/proto/daemon/v1/BUILD.bazel index a0dc5e5afa..005e42f1fa 100644 --- a/proto/daemon/v1/BUILD.bazel +++ b/proto/daemon/v1/BUILD.bazel @@ -4,6 +4,7 @@ proto_library( name = "daemon", srcs = [ "daemon.proto", + "daemon_fabrid.proto", ], visibility = ["//visibility:public"], deps = [ diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index 5438bc7fdc..2f95f791b2 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -22,7 +22,7 @@ import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/empty.proto"; import "proto/drkey/v1/drkey.proto"; -import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; +import "proto/daemon/v1/daemon_fabrid.proto"; service DaemonService { // Return a set of paths to the requested destination. @@ -46,7 +46,7 @@ service DaemonService { // DRKeyHostHost returns a key that matches the request. rpc DRKeyHostHost (DRKeyHostHostRequest) returns (DRKeyHostHostResponse) {} // FabridKeys returns the DRKeys for FABRID - rpc FabridKeys (FabridKeysRequest) returns (FabridKeysResponse) {} + rpc FabridKeys (proto.daemon.v1.FabridKeysRequest) returns (proto.daemon.v1.FabridKeysResponse) {} } message PathsRequest { @@ -124,52 +124,7 @@ message Path { // whether the AS in the hop supports FABRID, the possible policies, and whether the AS's FABRID // maps were detached during beaconing (requiring manual fetching by the end host to fill the // missing policies list). - repeated FabridInfo fabrid_info = 14; -} - -message FabridInfo { - // Enabled describes whether the hop supports Fabrid. - bool enabled = 1; - // Digest contains the digest for the FABRID map of this hop. - bytes digest = 2; - // Policies contains the fabrid policy identifiers that are supported for this hop. - repeated FabridPolicy policies = 3; - // Detached indicates whether the FABRID map has been detached for this hop. - bool detached = 4; -} - -message FabridPolicy { - // The identifier for the policy, either local or global: - proto.control_plane.experimental.v1.FABRIDPolicyIdentifier policy_identifier = 1; - // The local index, this may differ between similar policy identifiers, as it is specific to a hop. - uint32 policy_index = 2; -} - -message FabridKeysRequest { - // The source host - string src_host = 1; - // The destination AS - uint64 dst_as = 2; - // A list of ASes for which the AS-Host Key should be fetched - repeated uint64 path_ases = 3; - // The destination host. Only required if the path key should be fetched too - optional string dst_host = 4; -} - -message FabridKeyResponse { - // Begin of validity period of DRKey. - google.protobuf.Timestamp epoch_begin = 1; - // End of validity period of DRKey. - google.protobuf.Timestamp epoch_end = 2; - // Level2 key. - bytes key = 3; -} - -message FabridKeysResponse { - // The FABRID AS-Host DRKeys - repeated FabridKeyResponse as_host_keys = 1; - // The FABRID path key - optional FabridKeyResponse host_host_key = 2; + repeated proto.daemon.v1.FabridInfo fabrid_info = 14; } message EpicAuths { diff --git a/proto/daemon/v1/daemon_fabrid.proto b/proto/daemon/v1/daemon_fabrid.proto new file mode 100644 index 0000000000..e84670158b --- /dev/null +++ b/proto/daemon/v1/daemon_fabrid.proto @@ -0,0 +1,67 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option go_package = "github.com/scionproto/scion/pkg/proto/daemon"; + +package proto.daemon.v1; + +import "google/protobuf/timestamp.proto"; +import "proto/control_plane/experimental/v1/fabrid_extensions.proto"; + +message FabridInfo { + // Enabled describes whether the hop supports Fabrid. + bool enabled = 1; + // Digest contains the digest for the FABRID map of this hop. + bytes digest = 2; + // Policies contains the fabrid policy identifiers that are supported for this hop. + repeated FabridPolicy policies = 3; + // Detached indicates whether the FABRID map has been detached for this hop. + bool detached = 4; +} + +message FabridPolicy { + // The identifier for the policy, either local or global: + proto.control_plane.experimental.v1.FABRIDPolicyIdentifier policy_identifier = 1; + // The local index, this may differ between similar policy identifiers, as it is specific to a hop. + uint32 policy_index = 2; +} + +message FabridKeysRequest { + // The source host + string src_host = 1; + // The destination AS + uint64 dst_as = 2; + // A list of ASes for which the AS-Host Key should be fetched + repeated uint64 path_ases = 3; + // The destination host. Only required if the path key should be fetched too + optional string dst_host = 4; +} + +message FabridKeyResponse { + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Level2 key. + bytes key = 3; +} + +message FabridKeysResponse { + // The FABRID AS-Host DRKeys + repeated FabridKeyResponse as_host_keys = 1; + // The FABRID path key + optional FabridKeyResponse host_host_key = 2; +} \ No newline at end of file diff --git a/router/BUILD.bazel b/router/BUILD.bazel index 13da7a1347..c25ff8798a 100644 --- a/router/BUILD.bazel +++ b/router/BUILD.bazel @@ -4,7 +4,9 @@ go_library( name = "go_default_library", srcs = [ "connector.go", + "connector_fabrid.go", "dataplane.go", + "dataplane_fabrid.go", "fnv1aCheap.go", "metrics.go", "svc.go", @@ -47,6 +49,7 @@ go_library( go_test( name = "go_default_test", srcs = [ + "dataplane_internal_fabrid_test.go", "dataplane_internal_test.go", "dataplane_test.go", "export_test.go", diff --git a/router/connector.go b/router/connector.go index 5476848cfe..e3d205287f 100644 --- a/router/connector.go +++ b/router/connector.go @@ -163,19 +163,6 @@ func (c *Connector) DelSvc(ia addr.IA, svc addr.SVC, a *net.UDPAddr) error { return c.DataPlane.DelSvc(svc, a) } -func (c *Connector) AddDRKeySecret(protocolID int32, sv control.SecretValue) error { - c.mtx.Lock() - defer c.mtx.Unlock() - return c.DataPlane.DRKeyProvider.AddSecret(protocolID, sv) -} - -func (c *Connector) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, - interfacePolicies map[uint64]uint32) error { - c.mtx.Lock() - defer c.mtx.Unlock() - return c.DataPlane.UpdateFabridPolicies(ipRangePolicies, interfacePolicies) -} - // SetKey sets the key for the given ISD-AS at the given index. func (c *Connector) SetKey(ia addr.IA, index int, key []byte) error { c.mtx.Lock() diff --git a/router/connector_fabrid.go b/router/connector_fabrid.go new file mode 100644 index 0000000000..ea72442c30 --- /dev/null +++ b/router/connector_fabrid.go @@ -0,0 +1,30 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import "github.com/scionproto/scion/router/control" + +func (c *Connector) AddDRKeySecret(protocolID int32, sv control.SecretValue) error { + c.mtx.Lock() + defer c.mtx.Unlock() + return c.DataPlane.DRKeyProvider.AddSecret(protocolID, sv) +} + +func (c *Connector) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, + interfacePolicies map[uint64]uint32) error { + c.mtx.Lock() + defer c.mtx.Unlock() + return c.DataPlane.UpdateFabridPolicies(ipRangePolicies, interfacePolicies) +} diff --git a/router/dataplane.go b/router/dataplane.go index 55bb04aa0c..53f986d771 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -490,17 +490,6 @@ func (d *DataPlane) addNextHopBFD(ifID uint16, src, dst *net.UDPAddr, cfg contro return d.addBFDController(ifID, s, cfg, m) } -func (d *DataPlane) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, - interfacePolicies map[uint64]uint32) error { - d.mtx.Lock() - defer d.mtx.Unlock() - // TODO(rohrerj): check for concurrency issues - // when an update happens during reading - d.fabridPolicyIPRangeMap = ipRangePolicies - d.fabridPolicyInterfaceMap = interfacePolicies - return nil -} - func max(a int, b int) int { if a > b { return a @@ -1077,110 +1066,6 @@ func (p *scionPacketProcessor) reset() error { return nil } -func (p *scionPacketProcessor) processFabrid(egressIF uint16) error { - meta := p.fabrid.HopfieldMetadata[0] - src, err := p.scionLayer.SrcAddr() - if err != nil { - return err - } - var key [16]byte - if p.fabrid.HopfieldMetadata[0].ASLevelKey { - key, err = p.d.DRKeyProvider.DeriveASASKey(int32(drkey.FABRID), p.identifier.Timestamp, - p.scionLayer.SrcIA) - } else { - key, err = p.d.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), p.identifier.Timestamp, - p.scionLayer.SrcIA, src.String()) - } - if err != nil { - return err - } - policyID, err := crypto.ComputePolicyID(meta, p.identifier, key[:]) - if err != nil { - return err - } - err = crypto.VerifyAndUpdate(meta, p.identifier, &p.scionLayer, p.fabridInputBuffer, key[:], - p.ingressID, egressIF) - if err != nil { - return err - } - // Check / set MPLS label only if policy ID != 0 - // and only if the packet will be sent within the AS or to another router of the local AS - if policyID != 0 { - var mplsLabel uint32 - switch p.transitType { - case ingressEgressDifferentRouter: - mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), - uint32(policyID), uint32(egressIF)) - case internalTraffic: - mplsLabel, err = p.d.getFabridMplsLabel(uint32(p.ingressID), uint32(policyID), - p.nextHop.IP) - if err != nil { - mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), - uint32(policyID), 0) - } - case ingressEgressSameRouter: - return nil - } - if err != nil { - return err - } - p.mplsLabel = mplsLabel - } - return nil -} - -func (d *DataPlane) getFabridMplsLabelForInterface(ingressID uint32, policyIndex uint32, - egressID uint32) (uint32, error) { - - policyMapKey := uint64(ingressID)<<24 + uint64(egressID)<<8 + uint64(policyIndex) - mplsLabel, found := d.fabridPolicyInterfaceMap[policyMapKey] - if !found { - //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): - policyMapKey = 1<<63 + uint64(egressID)<<8 + uint64(policyIndex) - mplsLabel, found = d.fabridPolicyInterfaceMap[policyMapKey] - if !found { - return 0, serrors.New("Provided policyID is invalid", - "ingress", ingressID, "index", policyIndex, "egress", egressID) - } - } - return mplsLabel, nil -} - -func (d *DataPlane) getFabridMplsLabel(ingressID uint32, policyIndex uint32, - nextHopIP net.IP) (uint32, error) { - - policyMapKey := ingressID<<8 + policyIndex - ipRanges, found := d.fabridPolicyIPRangeMap[policyMapKey] - if !found { - //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): - policyMapKey = 1<<31 + policyIndex - ipRanges, found = d.fabridPolicyIPRangeMap[policyMapKey] - if !found { - return 0, serrors.New("Provided policyID is invalid", - "ingress", ingressID, "index", policyIndex) - } - } - var bestRange *control.PolicyIPRange - for _, r := range ipRanges { - if r.IPPrefix.Contains(nextHopIP) { - if bestRange == nil { - bestRange = r - } else { - bestPrefixLength, _ := bestRange.IPPrefix.Mask.Size() - currentPrefixLength, _ := r.IPPrefix.Mask.Size() - if currentPrefixLength > bestPrefixLength { - bestRange = r - } - } - } - } - if bestRange == nil { - return 0, serrors.New("Provided policy index is not valid for nexthop.", - "index", policyIndex, "next hop IP", nextHopIP) - } - return bestRange.MPLSLabel, nil -} - func (p *scionPacketProcessor) processHbhOptions(egressIF uint16) error { var err error for _, opt := range p.hbhLayer.Options { @@ -1448,8 +1333,6 @@ type scionPacketProcessor struct { transitType transitType } -type transitType int - const ( ingressEgressSameRouter transitType = iota ingressEgressDifferentRouter diff --git a/router/dataplane_fabrid.go b/router/dataplane_fabrid.go new file mode 100644 index 0000000000..be9d8ca65d --- /dev/null +++ b/router/dataplane_fabrid.go @@ -0,0 +1,141 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "net" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/router/control" +) + +type transitType int + +func (d *DataPlane) UpdateFabridPolicies(ipRangePolicies map[uint32][]*control.PolicyIPRange, + interfacePolicies map[uint64]uint32) error { + d.mtx.Lock() + defer d.mtx.Unlock() + // TODO(rohrerj): check for concurrency issues + // when an update happens during reading + d.fabridPolicyIPRangeMap = ipRangePolicies + d.fabridPolicyInterfaceMap = interfacePolicies + return nil +} + +func (p *scionPacketProcessor) processFabrid(egressIF uint16) error { + meta := p.fabrid.HopfieldMetadata[0] + src, err := p.scionLayer.SrcAddr() + if err != nil { + return err + } + var key [16]byte + if p.fabrid.HopfieldMetadata[0].ASLevelKey { + key, err = p.d.DRKeyProvider.DeriveASASKey(int32(drkey.FABRID), p.identifier.Timestamp, + p.scionLayer.SrcIA) + } else { + key, err = p.d.DRKeyProvider.DeriveASHostKey(int32(drkey.FABRID), p.identifier.Timestamp, + p.scionLayer.SrcIA, src.String()) + } + if err != nil { + return err + } + policyID, err := crypto.ComputePolicyID(meta, p.identifier, key[:]) + if err != nil { + return err + } + err = crypto.VerifyAndUpdate(meta, p.identifier, &p.scionLayer, p.fabridInputBuffer, key[:], + p.ingressID, egressIF) + if err != nil { + return err + } + // Check / set MPLS label only if policy ID != 0 + // and only if the packet will be sent within the AS or to another router of the local AS + if policyID != 0 { + var mplsLabel uint32 + switch p.transitType { + case ingressEgressDifferentRouter: + mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), + uint32(policyID), uint32(egressIF)) + case internalTraffic: + mplsLabel, err = p.d.getFabridMplsLabel(uint32(p.ingressID), uint32(policyID), + p.nextHop.IP) + if err != nil { + mplsLabel, err = p.d.getFabridMplsLabelForInterface(uint32(p.ingressID), + uint32(policyID), 0) + } + case ingressEgressSameRouter: + return nil + } + if err != nil { + return err + } + p.mplsLabel = mplsLabel + } + return nil +} + +func (d *DataPlane) getFabridMplsLabelForInterface(ingressID uint32, policyIndex uint32, + egressID uint32) (uint32, error) { + + policyMapKey := uint64(ingressID)<<24 + uint64(egressID)<<8 + uint64(policyIndex) + mplsLabel, found := d.fabridPolicyInterfaceMap[policyMapKey] + if !found { + //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): + policyMapKey = 1<<63 + uint64(egressID)<<8 + uint64(policyIndex) + mplsLabel, found = d.fabridPolicyInterfaceMap[policyMapKey] + if !found { + return 0, serrors.New("Provided policyID is invalid", + "ingress", ingressID, "index", policyIndex, "egress", egressID) + } + } + return mplsLabel, nil +} + +func (d *DataPlane) getFabridMplsLabel(ingressID uint32, policyIndex uint32, + nextHopIP net.IP) (uint32, error) { + + policyMapKey := ingressID<<8 + policyIndex + ipRanges, found := d.fabridPolicyIPRangeMap[policyMapKey] + if !found { + //lookup default (instead of using the ingressID as part of the key, use a 1 bit as MSB): + policyMapKey = 1<<31 + policyIndex + ipRanges, found = d.fabridPolicyIPRangeMap[policyMapKey] + if !found { + return 0, serrors.New("Provided policyID is invalid", + "ingress", ingressID, "index", policyIndex) + } + } + var bestRange *control.PolicyIPRange + for _, r := range ipRanges { + if r.IPPrefix.Contains(nextHopIP) { + if bestRange == nil { + bestRange = r + } else { + bestPrefixLength, _ := bestRange.IPPrefix.Mask.Size() + currentPrefixLength, _ := r.IPPrefix.Mask.Size() + if currentPrefixLength > bestPrefixLength { + bestRange = r + } + } + } + } + if bestRange == nil { + return 0, serrors.New("Provided policy index is not valid for nexthop.", + "index", policyIndex, "next hop IP", nextHopIP) + } + return bestRange.MPLSLabel, nil +} diff --git a/router/dataplane_internal_fabrid_test.go b/router/dataplane_internal_fabrid_test.go new file mode 100644 index 0000000000..c0e30fe052 --- /dev/null +++ b/router/dataplane_internal_fabrid_test.go @@ -0,0 +1,166 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package router + +import ( + "net" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/scionproto/scion/pkg/private/xtest" + "github.com/scionproto/scion/router/control" +) + +func TestFabridPolicies(t *testing.T) { + type testcase struct { + name string + ipRangePolicies map[uint32][]*control.PolicyIPRange + interfacePolicies map[uint64]uint32 + packetIngress uint32 + packetEgress uint32 + useIPRange bool + packetPolicyIndex uint32 + nextHopIP net.IP + expectedMplsLabel uint32 + expectsError bool + } + testcases := []testcase{ + { + name: "ingress and policyindex tuple exists with single ip range", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 0xa<<8 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + }, + }, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "ingress and policyindex tuple doesn't exist", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{}, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + expectsError: true, + useIPRange: true, + }, + { + name: "ingress and policyindex tuple exists with multiple ip ranges", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 0xa<<8 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + &control.PolicyIPRange{ + MPLSLabel: 2, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/31"), + }, + &control.PolicyIPRange{ + MPLSLabel: 3, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/30"), + }, + &control.PolicyIPRange{ + MPLSLabel: 4, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.2/32"), + }, + }, + }, + expectedMplsLabel: 2, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "ip range only exists for default value", + ipRangePolicies: map[uint32][]*control.PolicyIPRange{ + 1<<31 + 0xf: { + &control.PolicyIPRange{ + MPLSLabel: 1, + IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), + }, + }, + }, + expectedMplsLabel: 1, + packetIngress: 0xa, + packetPolicyIndex: 0xf, + nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), + useIPRange: true, + }, + { + name: "mpls label exists for interface map", + interfacePolicies: map[uint64]uint32{ + 1<<24 + 2<<8 + 0xf: 7, + 1<<63 + 2<<8 + 0xf: 5, // default value + }, + expectedMplsLabel: 7, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + useIPRange: false, + }, + { + name: "mpls label exists for interface map with default value", + interfacePolicies: map[uint64]uint32{ + 1<<63 + 2<<8 + 0xf: 5, // default value + }, + expectedMplsLabel: 5, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + useIPRange: false, + }, + { + name: "mpls label doesnt exist for interface map", + interfacePolicies: map[uint64]uint32{}, + packetIngress: 1, + packetEgress: 2, + packetPolicyIndex: 0xf, + expectsError: true, + useIPRange: false, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + dp := &DataPlane{Metrics: metrics} + err := dp.UpdateFabridPolicies(tc.ipRangePolicies, tc.interfacePolicies) + assert.NoError(t, err) + var mplsLabel uint32 + if tc.useIPRange { + mplsLabel, err = dp.getFabridMplsLabel(tc.packetIngress, tc.packetPolicyIndex, + tc.nextHopIP) + } else { + mplsLabel, err = dp.getFabridMplsLabelForInterface(tc.packetIngress, + tc.packetPolicyIndex, tc.packetEgress) + } + if tc.expectsError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedMplsLabel, mplsLabel) + } + }) + } + +} diff --git a/router/dataplane_internal_test.go b/router/dataplane_internal_test.go index b813777f18..393e289ab7 100644 --- a/router/dataplane_internal_test.go +++ b/router/dataplane_internal_test.go @@ -39,7 +39,6 @@ import ( "github.com/scionproto/scion/pkg/slayers/path" "github.com/scionproto/scion/pkg/slayers/path/scion" underlayconn "github.com/scionproto/scion/private/underlay/conn" - "github.com/scionproto/scion/router/control" "github.com/scionproto/scion/router/mock_router" ) @@ -215,147 +214,6 @@ func TestForwarder(t *testing.T) { } } -func TestFabridPolicies(t *testing.T) { - type testcase struct { - name string - ipRangePolicies map[uint32][]*control.PolicyIPRange - interfacePolicies map[uint64]uint32 - packetIngress uint32 - packetEgress uint32 - useIPRange bool - packetPolicyIndex uint32 - nextHopIP net.IP - expectedMplsLabel uint32 - expectsError bool - } - testcases := []testcase{ - { - name: "ingress and policyindex tuple exists with single ip range", - ipRangePolicies: map[uint32][]*control.PolicyIPRange{ - 0xa<<8 + 0xf: { - &control.PolicyIPRange{ - MPLSLabel: 1, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), - }, - }, - }, - expectedMplsLabel: 1, - packetIngress: 0xa, - packetPolicyIndex: 0xf, - nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), - useIPRange: true, - }, - { - name: "ingress and policyindex tuple doesn't exist", - ipRangePolicies: map[uint32][]*control.PolicyIPRange{}, - expectedMplsLabel: 1, - packetIngress: 0xa, - packetPolicyIndex: 0xf, - nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), - expectsError: true, - useIPRange: true, - }, - { - name: "ingress and policyindex tuple exists with multiple ip ranges", - ipRangePolicies: map[uint32][]*control.PolicyIPRange{ - 0xa<<8 + 0xf: { - &control.PolicyIPRange{ - MPLSLabel: 1, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), - }, - &control.PolicyIPRange{ - MPLSLabel: 2, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/31"), - }, - &control.PolicyIPRange{ - MPLSLabel: 3, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/30"), - }, - &control.PolicyIPRange{ - MPLSLabel: 4, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.2/32"), - }, - }, - }, - expectedMplsLabel: 2, - packetIngress: 0xa, - packetPolicyIndex: 0xf, - nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), - useIPRange: true, - }, - { - name: "ip range only exists for default value", - ipRangePolicies: map[uint32][]*control.PolicyIPRange{ - 1<<31 + 0xf: { - &control.PolicyIPRange{ - MPLSLabel: 1, - IPPrefix: xtest.MustParseCIDR(t, "127.0.0.0/24"), - }, - }, - }, - expectedMplsLabel: 1, - packetIngress: 0xa, - packetPolicyIndex: 0xf, - nextHopIP: xtest.MustParseIP(t, "127.0.0.1"), - useIPRange: true, - }, - { - name: "mpls label exists for interface map", - interfacePolicies: map[uint64]uint32{ - 1<<24 + 2<<8 + 0xf: 7, - 1<<63 + 2<<8 + 0xf: 5, // default value - }, - expectedMplsLabel: 7, - packetIngress: 1, - packetEgress: 2, - packetPolicyIndex: 0xf, - useIPRange: false, - }, - { - name: "mpls label exists for interface map with default value", - interfacePolicies: map[uint64]uint32{ - 1<<63 + 2<<8 + 0xf: 5, // default value - }, - expectedMplsLabel: 5, - packetIngress: 1, - packetEgress: 2, - packetPolicyIndex: 0xf, - useIPRange: false, - }, - { - name: "mpls label doesnt exist for interface map", - interfacePolicies: map[uint64]uint32{}, - packetIngress: 1, - packetEgress: 2, - packetPolicyIndex: 0xf, - expectsError: true, - useIPRange: false, - }, - } - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - dp := &DataPlane{Metrics: metrics} - err := dp.UpdateFabridPolicies(tc.ipRangePolicies, tc.interfacePolicies) - assert.NoError(t, err) - var mplsLabel uint32 - if tc.useIPRange { - mplsLabel, err = dp.getFabridMplsLabel(tc.packetIngress, tc.packetPolicyIndex, - tc.nextHopIP) - } else { - mplsLabel, err = dp.getFabridMplsLabelForInterface(tc.packetIngress, - tc.packetPolicyIndex, tc.packetEgress) - } - if tc.expectsError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.expectedMplsLabel, mplsLabel) - } - }) - } - -} - func TestComputeProcId(t *testing.T) { randomValueBytes := []byte{1, 2, 3, 4} numProcs := 10000 diff --git a/tools/end2end/BUILD.bazel b/tools/end2end/BUILD.bazel index eabd6e2754..5b730c92b5 100644 --- a/tools/end2end/BUILD.bazel +++ b/tools/end2end/BUILD.bazel @@ -3,7 +3,10 @@ load("//:scion.bzl", "scion_go_binary") go_library( name = "go_default_library", - srcs = ["main.go"], + srcs = [ + "fabrid.go", + "main.go", + ], importpath = "github.com/scionproto/scion/tools/end2end", visibility = ["//visibility:private"], deps = [ diff --git a/tools/end2end/fabrid.go b/tools/end2end/fabrid.go new file mode 100644 index 0000000000..b4eff77419 --- /dev/null +++ b/tools/end2end/fabrid.go @@ -0,0 +1,204 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net" + + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" + + "github.com/scionproto/scion/pkg/drkey" + "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/private/common" + "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" + "github.com/scionproto/scion/pkg/slayers/path/scion" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/private/tracing" + integration "github.com/scionproto/scion/tools/integration/integrationlib" +) + +func (s server) handlePingFabrid(conn snet.PacketConn) error { + var p snet.Packet + var ov net.UDPAddr + err := readFromFabrid(conn, &p, &ov) + if err != nil { + return serrors.WrapStr("reading packet", err) + } + + // If the packet is from remote IA, validate the FABRID path + if p.Source.IA != integration.Local.IA { + if p.HbhExtension == nil { + return serrors.New("Missing HBH extension") + } + + // Check extensions for relevant options + var identifierOption *extension.IdentifierOption + var fabridOption *extension.FabridOption + var err error + + for _, opt := range p.HbhExtension.Options { + switch opt.OptType { + case slayers.OptTypeIdentifier: + decoded := scion.Decoded{} + err = decoded.DecodeFromBytes(p.Path.(snet.RawPath).Raw) + if err != nil { + return err + } + baseTimestamp := decoded.InfoFields[0].Timestamp + identifierOption, err = extension.ParseIdentifierOption(opt, baseTimestamp) + if err != nil { + return err + } + case slayers.OptTypeFabrid: + fabridOption, err = extension.ParseFabridOptionFullExtension(opt, + (opt.OptDataLen-4)/4) + if err != nil { + return err + } + } + } + + if identifierOption == nil { + return serrors.New("Missing identifier option") + } + + if fabridOption == nil { + return serrors.New("Missing FABRID option") + } + + meta := drkey.HostHostMeta{ + Validity: identifierOption.Timestamp, + SrcIA: integration.Local.IA, + SrcHost: integration.Local.Host.IP.String(), + DstIA: p.Source.IA, + DstHost: p.Source.Host.IP().String(), + ProtoId: drkey.FABRID, + } + hostHostKey, err := integration.SDConn().DRKeyGetHostHostKey(context.Background(), meta) + if err != nil { + return serrors.WrapStr("getting host key", err) + } + + tmpBuffer := make([]byte, (len(fabridOption.HopfieldMetadata)*3+15)&^15+16) + _, err = crypto.VerifyPathValidator(fabridOption, tmpBuffer, hostHostKey.Key[:]) + if err != nil { + return err + } + } + + udp, ok := p.Payload.(snet.UDPPayload) + if !ok { + return serrors.New("unexpected payload received", + "source", p.Source, + "destination", p.Destination, + "type", common.TypeOf(p.Payload), + ) + } + var pld Ping + if err := json.Unmarshal(udp.Payload, &pld); err != nil { + return serrors.New("invalid payload contents", + "source", p.Source, + "destination", p.Destination, + "data", string(udp.Payload), + ) + } + + spanCtx, err := opentracing.GlobalTracer().Extract( + opentracing.Binary, + bytes.NewReader(pld.Trace), + ) + if err != nil { + return serrors.WrapStr("extracting trace information", err) + } + span, _ := opentracing.StartSpanFromContext( + context.Background(), + "handle_ping", + ext.RPCServerOption(spanCtx), + ) + defer span.Finish() + withTag := func(err error) error { + tracing.Error(span, err) + return err + } + + if pld.Message != ping || !pld.Server.Equal(integration.Local.IA) { + return withTag(serrors.New("unexpected data in payload", + "source", p.Source, + "destination", p.Destination, + "data", pld, + )) + } + log.Info(fmt.Sprintf("Ping received from %s, sending pong.", p.Source)) + raw, err := json.Marshal(Pong{ + Client: p.Source.IA, + Server: integration.Local.IA, + Message: pong, + Trace: pld.Trace, + }) + if err != nil { + return withTag(serrors.WrapStr("packing pong", err)) + } + + p.Destination, p.Source = p.Source, p.Destination + p.Payload = snet.UDPPayload{ + DstPort: udp.SrcPort, + SrcPort: udp.DstPort, + Payload: raw, + } + + // Remove header extension for reverse path + p.HbhExtension = nil + p.E2eExtension = nil + + // reverse path + rpath, ok := p.Path.(snet.RawPath) + if !ok { + return serrors.New("unexpected path", "type", common.TypeOf(p.Path)) + } + replypather := snet.DefaultReplyPather{} + replyPath, err := replypather.ReplyPath(rpath) + if err != nil { + return serrors.WrapStr("creating reply path", err) + } + p.Path = replyPath + // Send pong + if err := conn.WriteTo(&p, &ov); err != nil { + return withTag(serrors.WrapStr("sending reply", err)) + } + log.Info("Sent pong to", "client", p.Destination) + return nil +} + +func readFromFabrid(conn snet.PacketConn, pkt *snet.Packet, ov *net.UDPAddr) error { + err := conn.ReadFrom(pkt, ov) + // Attach more context to error + var opErr *snet.OpError + if !(errors.As(err, &opErr) && opErr.RevInfo() != nil) { + return err + } + return serrors.WithCtx(err, + "isd_as", opErr.RevInfo().IA(), + "interface", opErr.RevInfo().IfID, + ) +} diff --git a/tools/end2end/main.go b/tools/end2end/main.go index 654d5c319d..fe3bbe4431 100644 --- a/tools/end2end/main.go +++ b/tools/end2end/main.go @@ -37,16 +37,11 @@ import ( "github.com/scionproto/scion/pkg/addr" "github.com/scionproto/scion/pkg/daemon" - "github.com/scionproto/scion/pkg/drkey" libfabrid "github.com/scionproto/scion/pkg/experimental/fabrid" - "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" "github.com/scionproto/scion/pkg/log" "github.com/scionproto/scion/pkg/private/common" "github.com/scionproto/scion/pkg/private/serrors" "github.com/scionproto/scion/pkg/private/util" - "github.com/scionproto/scion/pkg/slayers" - "github.com/scionproto/scion/pkg/slayers/extension" - "github.com/scionproto/scion/pkg/slayers/path/scion" "github.com/scionproto/scion/pkg/snet" "github.com/scionproto/scion/pkg/snet/metrics" snetpath "github.com/scionproto/scion/pkg/snet/path" @@ -251,158 +246,6 @@ func (s server) handlePing(conn *snet.Conn) error { return nil } -func (s server) handlePingFabrid(conn snet.PacketConn) error { - var p snet.Packet - var ov net.UDPAddr - err := readFromFabrid(conn, &p, &ov) - if err != nil { - return serrors.WrapStr("reading packet", err) - } - - // If the packet is from remote IA, validate the FABRID path - if p.Source.IA != integration.Local.IA { - if p.HbhExtension == nil { - return serrors.New("Missing HBH extension") - } - - // Check extensions for relevant options - var identifierOption *extension.IdentifierOption - var fabridOption *extension.FabridOption - var err error - - for _, opt := range p.HbhExtension.Options { - switch opt.OptType { - case slayers.OptTypeIdentifier: - decoded := scion.Decoded{} - err = decoded.DecodeFromBytes(p.Path.(snet.RawPath).Raw) - if err != nil { - return err - } - baseTimestamp := decoded.InfoFields[0].Timestamp - identifierOption, err = extension.ParseIdentifierOption(opt, baseTimestamp) - if err != nil { - return err - } - case slayers.OptTypeFabrid: - fabridOption, err = extension.ParseFabridOptionFullExtension(opt, - (opt.OptDataLen-4)/4) - if err != nil { - return err - } - } - } - - if identifierOption == nil { - return serrors.New("Missing identifier option") - } - - if fabridOption == nil { - return serrors.New("Missing FABRID option") - } - - meta := drkey.HostHostMeta{ - Validity: identifierOption.Timestamp, - SrcIA: integration.Local.IA, - SrcHost: integration.Local.Host.IP.String(), - DstIA: p.Source.IA, - DstHost: p.Source.Host.IP().String(), - ProtoId: drkey.FABRID, - } - hostHostKey, err := integration.SDConn().DRKeyGetHostHostKey(context.Background(), meta) - if err != nil { - return serrors.WrapStr("getting host key", err) - } - - tmpBuffer := make([]byte, (len(fabridOption.HopfieldMetadata)*3+15)&^15+16) - _, err = crypto.VerifyPathValidator(fabridOption, tmpBuffer, hostHostKey.Key[:]) - if err != nil { - return err - } - } - - udp, ok := p.Payload.(snet.UDPPayload) - if !ok { - return serrors.New("unexpected payload received", - "source", p.Source, - "destination", p.Destination, - "type", common.TypeOf(p.Payload), - ) - } - var pld Ping - if err := json.Unmarshal(udp.Payload, &pld); err != nil { - return serrors.New("invalid payload contents", - "source", p.Source, - "destination", p.Destination, - "data", string(udp.Payload), - ) - } - - spanCtx, err := opentracing.GlobalTracer().Extract( - opentracing.Binary, - bytes.NewReader(pld.Trace), - ) - if err != nil { - return serrors.WrapStr("extracting trace information", err) - } - span, _ := opentracing.StartSpanFromContext( - context.Background(), - "handle_ping", - ext.RPCServerOption(spanCtx), - ) - defer span.Finish() - withTag := func(err error) error { - tracing.Error(span, err) - return err - } - - if pld.Message != ping || !pld.Server.Equal(integration.Local.IA) { - return withTag(serrors.New("unexpected data in payload", - "source", p.Source, - "destination", p.Destination, - "data", pld, - )) - } - log.Info(fmt.Sprintf("Ping received from %s, sending pong.", p.Source)) - raw, err := json.Marshal(Pong{ - Client: p.Source.IA, - Server: integration.Local.IA, - Message: pong, - Trace: pld.Trace, - }) - if err != nil { - return withTag(serrors.WrapStr("packing pong", err)) - } - - p.Destination, p.Source = p.Source, p.Destination - p.Payload = snet.UDPPayload{ - DstPort: udp.SrcPort, - SrcPort: udp.DstPort, - Payload: raw, - } - - // Remove header extension for reverse path - p.HbhExtension = nil - p.E2eExtension = nil - - // reverse path - rpath, ok := p.Path.(snet.RawPath) - if !ok { - return serrors.New("unexpected path", "type", common.TypeOf(p.Path)) - } - replypather := snet.DefaultReplyPather{} - replyPath, err := replypather.ReplyPath(rpath) - if err != nil { - return serrors.WrapStr("creating reply path", err) - } - p.Path = replyPath - // Send pong - if err := conn.WriteTo(&p, &ov); err != nil { - return withTag(serrors.WrapStr("sending reply", err)) - } - log.Info("Sent pong to", "client", p.Destination) - return nil -} - type client struct { network *snet.SCIONNetwork conn *snet.Conn @@ -644,16 +487,3 @@ func readFrom(conn *snet.Conn, pld []byte) (int, net.Addr, error) { "interface", opErr.RevInfo().IfID, ) } - -func readFromFabrid(conn snet.PacketConn, pkt *snet.Packet, ov *net.UDPAddr) error { - err := conn.ReadFrom(pkt, ov) - // Attach more context to error - var opErr *snet.OpError - if !(errors.As(err, &opErr) && opErr.RevInfo() != nil) { - return err - } - return serrors.WithCtx(err, - "isd_as", opErr.RevInfo().IA(), - "interface", opErr.RevInfo().IfID, - ) -} diff --git a/tools/integration/BUILD.bazel b/tools/integration/BUILD.bazel index cfe67524a7..248052665f 100644 --- a/tools/integration/BUILD.bazel +++ b/tools/integration/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "cmd.go", "docker.go", "done.go", + "endhost_integration.go", "integration.go", "networkalloc.go", ], diff --git a/tools/integration/binary.go b/tools/integration/binary.go index fe05eb9a3b..6d4d8d2cb0 100644 --- a/tools/integration/binary.go +++ b/tools/integration/binary.go @@ -104,24 +104,6 @@ func NewBinaryIntegration(name string, cmd string, clientArgs, serverArgs []stri return dockerize(bi) } -func NewBinaryEndhostIntegration(name string, cmd string, clientArgs, - serverArgs []string) Integration { - logDir := filepath.Join(LogDir(), name) - err := os.Mkdir(logDir, os.ModePerm) - if err != nil && !os.IsExist(err) { - log.Error("Failed to create log folder for testrun", "dir", name, "err", err) - return nil - } - bi := &binaryIntegration{ - name: name, - cmd: cmd, - clientArgs: clientArgs, - serverArgs: serverArgs, - logDir: logDir, - } - return dockerizeEndhost(bi) -} - func (bi *binaryIntegration) Name() string { return bi.name } diff --git a/tools/integration/docker.go b/tools/integration/docker.go index b6da97e50a..0072e1700e 100644 --- a/tools/integration/docker.go +++ b/tools/integration/docker.go @@ -48,10 +48,6 @@ type dockerIntegration struct { *binaryIntegration } -type dockerizedEndhostIntegration struct { - *binaryIntegration -} - func dockerize(bi *binaryIntegration) Integration { if *Docker { return &dockerIntegration{ @@ -61,40 +57,6 @@ func dockerize(bi *binaryIntegration) Integration { return bi } -func dockerizeEndhost(bi *binaryIntegration) Integration { - if *Docker { - return &dockerizedEndhostIntegration{ - binaryIntegration: bi, - } - } - return bi -} - -// StartServer starts a server and blocks until the ReadySignal is received on Stdout. -func (di *dockerizedEndhostIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, - error) { - bi := *di.binaryIntegration - bi.serverArgs = append(dockerArgs, - append([]string{EndhostID(dst), bi.cmd}, bi.serverArgs...)...) - bi.cmd = dockerCmd - log.Debug(fmt.Sprintf("Starting server for %s in a docker container", - addr.FormatIA(dst.IA, addr.WithFileSeparator())), - ) - return bi.StartServer(ctx, dst) -} - -func (di *dockerizedEndhostIntegration) StartClient(ctx context.Context, - src, dst *snet.UDPAddr) (*BinaryWaiter, error) { - bi := *di.binaryIntegration - bi.clientArgs = append(dockerArgs, - append([]string{EndhostID(src), bi.cmd}, bi.clientArgs...)...) - bi.cmd = dockerCmd - log.Debug(fmt.Sprintf("Starting client for %s in a docker container", - addr.FormatIA(src.IA, addr.WithFileSeparator())), - ) - return bi.StartClient(ctx, src, dst) -} - func (di *dockerIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, error) { bi := *di.binaryIntegration bi.serverArgs = append(dockerArgs, append([]string{TesterID(dst), bi.cmd}, bi.serverArgs...)...) @@ -125,12 +87,3 @@ func TesterID(a *snet.UDPAddr) string { } return envID } - -func EndhostID(a *snet.UDPAddr) string { - ia := addr.FormatIA(a.IA, addr.WithFileSeparator()) - envID, ok := os.LookupEnv(fmt.Sprintf("endhost_%s", strings.Replace(ia, "-", "_", -1))) - if !ok { - return fmt.Sprintf("endhost_%s", ia) - } - return envID -} diff --git a/tools/integration/endhost_integration.go b/tools/integration/endhost_integration.go new file mode 100644 index 0000000000..cdaef55c35 --- /dev/null +++ b/tools/integration/endhost_integration.go @@ -0,0 +1,129 @@ +// Copyright 2024 ETH Zurich +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package integration + +import ( + "context" + "fmt" + "net" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/scionproto/scion/pkg/addr" + "github.com/scionproto/scion/pkg/log" + "github.com/scionproto/scion/pkg/snet" + "github.com/scionproto/scion/private/topology" +) + +type dockerizedEndhostIntegration struct { + *binaryIntegration +} + +func NewBinaryEndhostIntegration(name string, cmd string, clientArgs, + serverArgs []string) Integration { + logDir := filepath.Join(LogDir(), name) + err := os.Mkdir(logDir, os.ModePerm) + if err != nil && !os.IsExist(err) { + log.Error("Failed to create log folder for testrun", "dir", name, "err", err) + return nil + } + bi := &binaryIntegration{ + name: name, + cmd: cmd, + clientArgs: clientArgs, + serverArgs: serverArgs, + logDir: logDir, + } + return dockerizeEndhost(bi) +} + +func dockerizeEndhost(bi *binaryIntegration) Integration { + if *Docker { + return &dockerizedEndhostIntegration{ + binaryIntegration: bi, + } + } + return bi +} + +// StartServer starts a server and blocks until the ReadySignal is received on Stdout. +func (di *dockerizedEndhostIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, + error) { + bi := *di.binaryIntegration + bi.serverArgs = append(dockerArgs, + append([]string{EndhostID(dst), bi.cmd}, bi.serverArgs...)...) + bi.cmd = dockerCmd + log.Debug(fmt.Sprintf("Starting server for %s in a docker container", + addr.FormatIA(dst.IA, addr.WithFileSeparator())), + ) + return bi.StartServer(ctx, dst) +} + +func (di *dockerizedEndhostIntegration) StartClient(ctx context.Context, + src, dst *snet.UDPAddr) (*BinaryWaiter, error) { + bi := *di.binaryIntegration + bi.clientArgs = append(dockerArgs, + append([]string{EndhostID(src), bi.cmd}, bi.clientArgs...)...) + bi.cmd = dockerCmd + log.Debug(fmt.Sprintf("Starting client for %s in a docker container", + addr.FormatIA(src.IA, addr.WithFileSeparator())), + ) + return bi.StartClient(ctx, src, dst) +} + +func EndhostID(a *snet.UDPAddr) string { + ia := addr.FormatIA(a.IA, addr.WithFileSeparator()) + envID, ok := os.LookupEnv(fmt.Sprintf("endhost_%s", strings.Replace(ia, "-", "_", -1))) + if !ok { + return fmt.Sprintf("endhost_%s", ia) + } + return envID +} + +// SDAddr reads the endhost (dockerized) or scion daemon (normal) host Addr from the topology +// for the specified IA. If the address cannot be found, the CS address is returned. +var SDAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { + if a := loadAddr(ia); a != nil { + return a + } + var name string + if *Docker { + name = "endhost_" + } else { + name = "sd" + } + if raw, err := os.ReadFile(GenFile("networks.conf")); err == nil { + pattern := fmt.Sprintf("%s%s = (.*)", name, addr.FormatIA(ia, addr.WithFileSeparator())) + matches := regexp.MustCompile(pattern).FindSubmatch(raw) + if len(matches) == 2 { + return &snet.UDPAddr{IA: ia, Host: &net.UDPAddr{IP: net.ParseIP(string(matches[1]))}} + } + } + path := GenFile( + filepath.Join( + addr.FormatAS(ia.AS(), addr.WithDefaultPrefix(), addr.WithFileSeparator()), + "topology.json", + ), + ) + topo, err := topology.RWTopologyFromJSONFile(path) + if err != nil { + log.Error("Error loading topology", "err", err) + os.Exit(1) + } + cs := topo.CS["cs"+addr.FormatIA(ia, addr.WithFileSeparator())+"-1"] + return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress} +} diff --git a/tools/integration/integration.go b/tools/integration/integration.go index 11a18a6be2..2b7edc1a9b 100644 --- a/tools/integration/integration.go +++ b/tools/integration/integration.go @@ -246,40 +246,6 @@ var CSAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress} } -// SDAddr reads the endhost (dockerized) or scion daemon (normal) host Addr from the topology -// for the specified IA. If the address cannot be found, the CS address is returned. -var SDAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { - if a := loadAddr(ia); a != nil { - return a - } - var name string - if *Docker { - name = "endhost_" - } else { - name = "sd" - } - if raw, err := os.ReadFile(GenFile("networks.conf")); err == nil { - pattern := fmt.Sprintf("%s%s = (.*)", name, addr.FormatIA(ia, addr.WithFileSeparator())) - matches := regexp.MustCompile(pattern).FindSubmatch(raw) - if len(matches) == 2 { - return &snet.UDPAddr{IA: ia, Host: &net.UDPAddr{IP: net.ParseIP(string(matches[1]))}} - } - } - path := GenFile( - filepath.Join( - addr.FormatAS(ia.AS(), addr.WithDefaultPrefix(), addr.WithFileSeparator()), - "topology.json", - ), - ) - topo, err := topology.RWTopologyFromJSONFile(path) - if err != nil { - log.Error("Error loading topology", "err", err) - os.Exit(1) - } - cs := topo.CS["cs"+addr.FormatIA(ia, addr.WithFileSeparator())+"-1"] - return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress} -} - var addrs map[addr.IA]*snet.UDPAddr func initAddrs() { diff --git a/tools/topology/endhost.py b/tools/topology/endhost.py new file mode 100644 index 0000000000..5c92d52ccb --- /dev/null +++ b/tools/topology/endhost.py @@ -0,0 +1,28 @@ +# Copyright 2024 ETH Zurich, Anapaya Systems +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Stdlib +from typing import Mapping + +# SCION +from topology.net import NetworkDescription, IPNetwork + + +def endhost_ip(docker, topo_id, + networks: Mapping[IPNetwork, NetworkDescription]): + for net_desc in networks.values(): + for prog, ip_net in net_desc.ip_net.items(): + if prog == 'endhost_%s' % topo_id.file_fmt(): + return ip_net.ip + return None From 03858e701173ea5fca29f5de07c62a7cd1911e7f Mon Sep 17 00:00:00 2001 From: rohrerj <26304001+rohrerj@users.noreply.github.com> Date: Tue, 17 Sep 2024 09:21:16 +0200 Subject: [PATCH 22/26] update github upload artifact version --- .github/workflows/gobra.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gobra.yml b/.github/workflows/gobra.yml index 4dadbab9e8..5d544611d1 100644 --- a/.github/workflows/gobra.yml +++ b/.github/workflows/gobra.yml @@ -33,7 +33,7 @@ jobs: caching: '1' statsFile: ${{ env.statsFile }} - name: Upload the verification report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: verification_stats.json path: ${{ env.statsFile }} From 60b9736b786aeb4ce0318f185ed1b650b36343bd Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Tue, 17 Sep 2024 13:06:13 +0200 Subject: [PATCH 23/26] Delete moved endhost_ip function --- tools/topology/common.py | 9 --------- tools/topology/go.py | 3 ++- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tools/topology/common.py b/tools/topology/common.py index 023e2f52b0..dcbfe8719e 100644 --- a/tools/topology/common.py +++ b/tools/topology/common.py @@ -125,15 +125,6 @@ def sciond_ip(docker, topo_id, return None -def endhost_ip(docker, topo_id, - networks: Mapping[IPNetwork, NetworkDescription]): - for net_desc in networks.values(): - for prog, ip_net in net_desc.ip_net.items(): - if prog == 'endhost_%s' % topo_id.file_fmt(): - return ip_net.ip - return None - - def prom_addr_dispatcher(docker, topo_id, networks: Mapping[IPNetwork, NetworkDescription], port, name): if not docker: diff --git a/tools/topology/go.py b/tools/topology/go.py index 8b5b2964f9..6e7aabf3c7 100644 --- a/tools/topology/go.py +++ b/tools/topology/go.py @@ -30,13 +30,14 @@ prom_addr, prom_addr_dispatcher, sciond_ip, - endhost_ip, sciond_name, translate_features, SD_API_PORT, SD_CONFIG_NAME, ) +from topology.endhost import endhost_ip + from topology.net import socket_address_str, NetworkDescription, IPNetwork from topology.monitoring import ( From f675c9de7c778f69443f1e69d0d66e09c7fc5f8e Mon Sep 17 00:00:00 2001 From: Marc Odermatt Date: Wed, 18 Sep 2024 15:48:51 +0200 Subject: [PATCH 24/26] Undo unneeded formatting changes --- pkg/snet/path/path.go | 2 +- private/path/combinator/graph.go | 1 - proto/daemon/v1/daemon.proto | 2 +- router/dataplane_test.go | 9 +++------ tools/topology/common.py | 7 ++++--- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pkg/snet/path/path.go b/pkg/snet/path/path.go index 1013366a4e..08748964d9 100644 --- a/pkg/snet/path/path.go +++ b/pkg/snet/path/path.go @@ -62,7 +62,7 @@ func (p Path) Destination() addr.IA { } func (p Path) Metadata() *snet.PathMetadata { - return &p.Meta + return p.Meta.Copy() } func (p Path) String() string { diff --git a/private/path/combinator/graph.go b/private/path/combinator/graph.go index 6c34211ac9..07e08efb47 100644 --- a/private/path/combinator/graph.go +++ b/private/path/combinator/graph.go @@ -311,7 +311,6 @@ type pathSolution struct { // Path builds the forwarding path with metadata by extracting it from a path // between source and destination in the DMG. - func (solution *pathSolution) Path() Path { mtu := ^uint16(0) var segments segmentList diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index 2f95f791b2..243ad9ea3e 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -107,7 +107,7 @@ message Path { // Consequently, there are no entries for the first and last ASes, as these // are not traversed completely by the path. repeated uint32 internal_hops = 10; - // Notes contains the notes added by ASes on the path, in the lorder of + // Notes contains the notes added by ASes on the path, in the order of // occurrence. // Entry i is the note of AS i on the path. repeated string notes = 11; diff --git a/router/dataplane_test.go b/router/dataplane_test.go index 1f99c754d2..a0e34e8d5c 100644 --- a/router/dataplane_test.go +++ b/router/dataplane_test.go @@ -1071,8 +1071,7 @@ func TestDataPlaneRun(t *testing.T) { return 0, fmt.Errorf("no valid BFD message") }).MinTimes(1) - mInternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). - AnyTimes() + mInternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() local := &net.UDPAddr{IP: net.ParseIP("10.0.200.100").To4()} _ = ret.SetKey([]byte("randomkeyformacs")) @@ -1172,8 +1171,7 @@ func TestDataPlaneRun(t *testing.T) { done <- struct{}{} return 1, nil }).MinTimes(1) - mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). - AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() local := control.LinkEnd{ IA: xtest.MustParseIA("1-ff00:0:1"), @@ -1251,8 +1249,7 @@ func TestDataPlaneRun(t *testing.T) { } return 0, fmt.Errorf("no valid BFD message") }).MinTimes(1) - mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil). - AnyTimes() + mExternal.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Return(0, nil).AnyTimes() local := control.LinkEnd{ IA: xtest.MustParseIA("1-ff00:0:1"), diff --git a/tools/topology/common.py b/tools/topology/common.py index dcbfe8719e..acdaa17b16 100644 --- a/tools/topology/common.py +++ b/tools/topology/common.py @@ -116,8 +116,8 @@ def join_host_port(host: str, port: int) -> str: return '[{}]:{}'.format(host, port) -def sciond_ip(docker, topo_id, - networks: Mapping[IPNetwork, NetworkDescription]): +def sciond_ip(docker, topo_id, networks: Mapping[IPNetwork, + NetworkDescription]): for net_desc in networks.values(): for prog, ip_net in net_desc.ip_net.items(): if prog == 'sd%s' % topo_id.file_fmt(): @@ -126,7 +126,8 @@ def sciond_ip(docker, topo_id, def prom_addr_dispatcher(docker, topo_id, - networks: Mapping[IPNetwork, NetworkDescription], port, name): + networks: Mapping[IPNetwork, + NetworkDescription], port, name): if not docker: return "[127.0.0.1]:%s" % port target_name = '' From 0eb117ab802f1346b3d31f34da7a4143e179578a Mon Sep 17 00:00:00 2001 From: jelte Date: Fri, 20 Sep 2024 13:44:31 +0200 Subject: [PATCH 25/26] Moved hop by hop processing to separate dataplane_fabrid file. --- router/dataplane.go | 65 ------------------------------------ router/dataplane_fabrid.go | 67 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/router/dataplane.go b/router/dataplane.go index 53f986d771..55b1b2b094 100644 --- a/router/dataplane.go +++ b/router/dataplane.go @@ -1066,71 +1066,6 @@ func (p *scionPacketProcessor) reset() error { return nil } -func (p *scionPacketProcessor) processHbhOptions(egressIF uint16) error { - var err error - for _, opt := range p.hbhLayer.Options { - switch opt.OptType { - case slayers.OptTypeIdentifier: - if p.identifier != nil { - return serrors.New("Identifier HBH option provided multiple times") - } - // TODO(marcodermatt): Find cleaner solution for getting timestamp of first InfoField - baseTimestamp := p.infoField.Timestamp - if p.path.PathMeta.CurrINF > 0 { - firstInfoField, err := p.path.GetInfoField(0) - if err != nil { - return serrors.New("Failed to parse first InfoField") - } - baseTimestamp = firstInfoField.Timestamp - } - p.identifier, err = extension.ParseIdentifierOption(opt, baseTimestamp) - if err != nil { - return err - } - case slayers.OptTypeFabrid: - if p.fabrid != nil { - return serrors.New("FABRID HBH option provided multiple times") - } - if p.identifier == nil { - return serrors.New("Identifier HBH option must be present when using FABRID") - } - - // Calculate FABRID hop index - currHop := p.path.PathMeta.CurrHF - if !p.infoField.Peer { - currHop -= p.path.PathMeta.CurrINF - } - - // Skip if this is an intermediary egress router - if p.ingressID == 0 && currHop != 0 { - return nil - } - - // Calculate number of FABRID hops - numHFs := p.path.NumHops - p.path.NumINF + 1 - if p.infoField.Peer { - numHFs++ - } - fabrid, err := extension.ParseFabridOptionCurrentHop(opt, currHop, uint8(numHFs)) - if err != nil { - return err - } - if fabrid.HopfieldMetadata[0].FabridEnabled { - p.fabrid = fabrid - if err = p.processFabrid(egressIF); err != nil { - return err - } - if err = fabrid.HopfieldMetadata[0].SerializeTo(opt. - OptData[currHop*4:]); err != nil { - return err - } - } - default: - } - } - return err -} - func (p *scionPacketProcessor) processPkt(rawPkt []byte, srcAddr *net.UDPAddr, ingressID uint16) (processResult, error) { diff --git a/router/dataplane_fabrid.go b/router/dataplane_fabrid.go index be9d8ca65d..0d0959ee5f 100644 --- a/router/dataplane_fabrid.go +++ b/router/dataplane_fabrid.go @@ -20,6 +20,8 @@ import ( "github.com/scionproto/scion/pkg/drkey" "github.com/scionproto/scion/pkg/experimental/fabrid/crypto" "github.com/scionproto/scion/pkg/private/serrors" + "github.com/scionproto/scion/pkg/slayers" + "github.com/scionproto/scion/pkg/slayers/extension" "github.com/scionproto/scion/router/control" ) @@ -139,3 +141,68 @@ func (d *DataPlane) getFabridMplsLabel(ingressID uint32, policyIndex uint32, } return bestRange.MPLSLabel, nil } + +func (p *scionPacketProcessor) processHbhOptions(egressIF uint16) error { + var err error + for _, opt := range p.hbhLayer.Options { + switch opt.OptType { + case slayers.OptTypeIdentifier: + if p.identifier != nil { + return serrors.New("Identifier HBH option provided multiple times") + } + // TODO(marcodermatt): Find cleaner solution for getting timestamp of first InfoField + baseTimestamp := p.infoField.Timestamp + if p.path.PathMeta.CurrINF > 0 { + firstInfoField, err := p.path.GetInfoField(0) + if err != nil { + return serrors.New("Failed to parse first InfoField") + } + baseTimestamp = firstInfoField.Timestamp + } + p.identifier, err = extension.ParseIdentifierOption(opt, baseTimestamp) + if err != nil { + return err + } + case slayers.OptTypeFabrid: + if p.fabrid != nil { + return serrors.New("FABRID HBH option provided multiple times") + } + if p.identifier == nil { + return serrors.New("Identifier HBH option must be present when using FABRID") + } + + // Calculate FABRID hop index + currHop := p.path.PathMeta.CurrHF + if !p.infoField.Peer { + currHop -= p.path.PathMeta.CurrINF + } + + // Skip if this is an intermediary egress router + if p.ingressID == 0 && currHop != 0 { + return nil + } + + // Calculate number of FABRID hops + numHFs := p.path.NumHops - p.path.NumINF + 1 + if p.infoField.Peer { + numHFs++ + } + fabrid, err := extension.ParseFabridOptionCurrentHop(opt, currHop, uint8(numHFs)) + if err != nil { + return err + } + if fabrid.HopfieldMetadata[0].FabridEnabled { + p.fabrid = fabrid + if err = p.processFabrid(egressIF); err != nil { + return err + } + if err = fabrid.HopfieldMetadata[0].SerializeTo(opt. + OptData[currHop*4:]); err != nil { + return err + } + } + default: + } + } + return err +} From bf6678297e16f3b49c3585d4137ecac1374af616 Mon Sep 17 00:00:00 2001 From: "Juan A. Garcia Pardo" Date: Fri, 20 Sep 2024 13:56:30 +0200 Subject: [PATCH 26/26] Revert changes happening upstream. --- pkg/addr/isdas.go | 4 ++-- tools/integration/docker.go | 1 + tools/integration/integration.go | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/addr/isdas.go b/pkg/addr/isdas.go index 3391c259df..64e9c50a8b 100644 --- a/pkg/addr/isdas.go +++ b/pkg/addr/isdas.go @@ -67,10 +67,10 @@ type AS uint64 // ParseAS parses an AS from a decimal (in the case of the 32bit BGP AS number // space) or ipv6-style hex (in the case of SCION-only AS numbers) string. func ParseAS(as string) (AS, error) { - return ParseASSep(as, ":") + return parseAS(as, ":") } -func ParseASSep(as string, sep string) (AS, error) { +func parseAS(as string, sep string) (AS, error) { parts := strings.Split(as, sep) if len(parts) == 1 { // Must be a BGP AS, parse as 32-bit decimal number diff --git a/tools/integration/docker.go b/tools/integration/docker.go index 0072e1700e..0b26344a31 100644 --- a/tools/integration/docker.go +++ b/tools/integration/docker.go @@ -57,6 +57,7 @@ func dockerize(bi *binaryIntegration) Integration { return bi } +// StartServer starts a server and blocks until the ReadySignal is received on Stdout. func (di *dockerIntegration) StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, error) { bi := *di.binaryIntegration bi.serverArgs = append(dockerArgs, append([]string{TesterID(dst), bi.cmd}, bi.serverArgs...)...) diff --git a/tools/integration/integration.go b/tools/integration/integration.go index 2b7edc1a9b..518bef3de7 100644 --- a/tools/integration/integration.go +++ b/tools/integration/integration.go @@ -218,8 +218,7 @@ func generateAllSrcDst(hostAddr HostAddr, unique bool) []IAPair { type HostAddr func(ia addr.IA) *snet.UDPAddr -// CSAddr reads the tester host Addr from the topology for the specified IA. -// If the address cannot be found, the CS address is returned. +// CSAddr reads the CS host Addr from the topology for the specified IA. var CSAddr HostAddr = func(ia addr.IA) *snet.UDPAddr { if a := loadAddr(ia); a != nil { return a