diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b7cee059..96101495c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,5 +19,5 @@ jobs: uses: actions/checkout@v3 - name: Test run: | - export PATH=$PATH:$HOME/bin + export PATH=$PATH:$HOME/bin:$HOME/go/bin make github diff --git a/.gitignore b/.gitignore index f9641df70..b85cdee83 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,6 @@ demo/cert/ /pkg/ dist/ *.app -*.hugo_build.lock \ No newline at end of file +*.hugo_build.lock +*~ + diff --git a/Makefile b/Makefile index e8537a966..05a08cc80 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ GORELEASER ?= $(shell which goreleaser) CI_CONSUL_VERSION ?= 1.12.3 CI_VAULT_VERSION ?= 1.11.0 CI_HUGO_VERSION ?= 0.101.0 +CI_GOBGP_VERSION ?= 3.8.0 BETA_OSES = linux darwin @@ -161,8 +162,11 @@ travis-pages: github: wget -q -O ~/consul.zip https://releases.hashicorp.com/consul/$(CI_CONSUL_VERSION)/consul_$(CI_CONSUL_VERSION)_linux_amd64.zip wget -q -O ~/vault.zip https://releases.hashicorp.com/vault/$(CI_VAULT_VERSION)/vault_$(CI_VAULT_VERSION)_linux_amd64.zip + wget -q -O ~/vault.zip https://releases.hashicorp.com/vault/$(CI_VAULT_VERSION)/vault_$(CI_VAULT_VERSION)_linux_amd64.zip + wget -q -O ~/gobgp.tar.gz https://github.com/osrg/gobgp/releases/download/v$(CI_GOBGP_VERSION)/gobgp_$(CI_GOBGP_VERSION)_linux_amd64.tar.gz unzip -o -d ~/bin ~/consul.zip unzip -o -d ~/bin ~/vault.zip + tar xzf ~/gobgp.tar.gz -C ~/bin vault --version consul --version make test diff --git a/bgp/bgp.go b/bgp/bgp.go new file mode 100644 index 000000000..24764bb7e --- /dev/null +++ b/bgp/bgp.go @@ -0,0 +1,413 @@ +package bgp + +import ( + "context" + "errors" + "fmt" + "log" + "net" + "os" + + "github.com/fabiolb/fabio/config" + "github.com/fabiolb/fabio/exit" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/proto" + apb "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/go-multierror" + + api "github.com/osrg/gobgp/v3/api" + bgpconfig "github.com/osrg/gobgp/v3/pkg/config" + "github.com/osrg/gobgp/v3/pkg/server" +) + +var ( + ErrMissingAnycast = errors.New("you must specify at least one anycast address to advertise") + ErrMissingPeers = errors.New("you must specify at least one peer to advertise routes to") + ErrMissingRouterID = errors.New("you must specify the routerID of this host, i.e. a non anycast address") + ErrNoRoutesAdded = errors.New("no routes were successfully added") + ErrNoRoutesDeleted = errors.New("no routes were successfully deleted") + ErrNoPeersAdded = errors.New("no peers were successfully added") +) + +const ( + denyAllNeighbors = "deny-all-neighbors" + matchAnyPeer = "match-any-peer" + globalTable = "global" + rejectAll = "reject-all" +) + +type BGPHandler struct { + server *server.BgpServer + config *config.BGP + routeAttrs []*apb.Any +} + +func NewBGPHandler(config *config.BGP) (*BGPHandler, error) { + // pre-chew some protobuf messages that are part of + // every anycast route we'll be adding. + nextHop := config.RouterID + if len(config.NextHop) > 0 { + nextHop = config.NextHop + } + var messages = []proto.Message{ + &api.OriginAttribute{ + Origin: 0, + }, + &api.NextHopAttribute{ + NextHop: nextHop, + }, + &api.AsPathAttribute{ + Segments: []*api.AsSegment{ + { + Type: api.AsSegment_AS_SEQUENCE, + Numbers: []uint32{uint32(config.Asn)}, + }, + }, + }, + } + attributes := make([]*apb.Any, 0, len(messages)) + for _, p := range messages { + attr, err := apb.New(p) + if err != nil { + // should never happen + panic(err) + } + attributes = append(attributes, attr) + } + + var opts = []server.ServerOption{server.LoggerOption(bgpLogger{})} + if config.EnableGRPC { + maxSize := 256 << 20 + grpcOpts := []grpc.ServerOption{grpc.MaxRecvMsgSize(maxSize), grpc.MaxSendMsgSize(maxSize)} + if config.GRPCTLS { + creds, err := credentials.NewServerTLSFromFile(config.CertFile, config.KeyFile) + if err != nil { + // shouldn't get here if validate was called first. + return nil, fmt.Errorf("error parsing bgp TLS credentials: %s", err) + } + grpcOpts = append(grpcOpts, grpc.Creds(creds)) + } + opts = append(opts, + server.GrpcOption(grpcOpts), + server.GrpcListenAddress(config.GRPCListenAddress), + ) + } + return &BGPHandler{ + server: server.NewBgpServer(opts...), + config: config, + routeAttrs: attributes, + }, nil +} + +func (bgph *BGPHandler) Start() error { + s := bgph.server + go s.Serve() + + if len(bgph.config.GOBGPDCfgFile) > 0 { + initialCfg, err := bgpconfig.ReadConfigFile(bgph.config.GOBGPDCfgFile, "toml") + if err != nil { + // shouldn't happen if we called validate first. + return err + } + _, err = bgpconfig.InitialConfig(context.Background(), s, initialCfg, false) + if err != nil { + return fmt.Errorf("bgp: error initializing from gobgp config: %w", err) + } + } else { + // If we weren't passed a gobgp config file, configure using the values passed from the fabio + // config, and make sure we have a sane policy where we export our routes to peers but don't + // import from any peers. + err := bgph.startBGP(context.Background()) + if err != nil { + return fmt.Errorf("bgp: error starting: %w", err) + } + + err = bgph.setPolicies() + if err != nil { + return fmt.Errorf("bgp error setting policy: %w", err) + } + + } + + errCh := make(chan error, 1) + exit.Listen(func(sig os.Signal) { + log.Printf("[INFO] Stopping BGP") + err := s.StopBgp(context.Background(), &api.StopBgpRequest{}) + errCh <- err + }) + + // monitor the change of the peer state + if err := s.WatchEvent(context.Background(), &api.WatchEventRequest{Peer: &api.WatchEventRequest_Peer{}}, func(r *api.WatchEventResponse) { + if p := r.GetPeer(); p != nil && p.Type == api.WatchEventResponse_PeerEvent_STATE { + log.Printf("[DEBUG] bgp event: %#v", p) + } + }); err != nil { + log.Printf("[ERROR] bgp watcher failed: %s", err) + } + if len(bgph.config.GOBGPDCfgFile) == 0 || len(bgph.config.Peers) > 0 { + // add peers + err := bgph.addNeighbors(context.Background(), bgph.config.Peers) + if err != nil { + return fmt.Errorf("bgp error adding neighbors: %w", err) + } + } + if len(bgph.config.AnycastAddresses) > 0 { + err := bgph.AddRoutes(context.Background(), bgph.config.AnycastAddresses) + if err != nil { + return fmt.Errorf("bgp error adding anycastaddresses: %w", err) + } + } + // hang until exit handler completes above. + return <-errCh +} + +func (bgph *BGPHandler) startBGP(ctx context.Context) error { + return bgph.server.StartBgp(ctx, &api.StartBgpRequest{ + Global: &api.Global{ + Asn: uint32(bgph.config.Asn), + RouterId: bgph.config.RouterID, + ListenPort: int32(bgph.config.ListenPort), + ListenAddresses: bgph.config.ListenAddresses, + }, + }) +} + +func (bgph *BGPHandler) setPolicies() error { + // Create a policy that denies all routes from any neighbor. + err := bgph.server.SetPolicies(context.Background(), &api.SetPoliciesRequest{ + DefinedSets: []*api.DefinedSet{ + { + DefinedType: api.DefinedType_NEIGHBOR, + Name: matchAnyPeer, + List: []string{"0.0.0.0/0", "::/0"}, + }, + }, + Policies: []*api.Policy{ + { + Name: denyAllNeighbors, + Statements: []*api.Statement{ + { + Name: rejectAll, + Conditions: &api.Conditions{ + NeighborSet: &api.MatchSet{ + Name: matchAnyPeer, + }, + }, + Actions: &api.Actions{ + RouteAction: api.RouteAction_REJECT, + }, + }, + }, + }, + }, + }) + if err != nil { + return err + } + + // Assign the above to the global policy + return bgph.server.SetPolicyAssignment(context.Background(), &api.SetPolicyAssignmentRequest{ + Assignment: &api.PolicyAssignment{ + Name: globalTable, // this is the global rib + Direction: api.PolicyDirection_IMPORT, + Policies: []*api.Policy{ + { + Name: denyAllNeighbors, + }, + }, + // Need to set default action to accept here because otherwise + // even routes added via API calls get rejected. + DefaultAction: api.RouteAction_ACCEPT, + }, + }) +} + +func (bgph *BGPHandler) addNeighbors(ctx context.Context, peers []config.BGPPeer) error { + var result error + peerCount := 0 + for _, peer := range peers { + var hop *api.EbgpMultihop + if peer.MultiHop { + hop = &api.EbgpMultihop{ + Enabled: true, + MultihopTtl: uint32(peer.MultiHopLength), + } + } + var trans *api.Transport + if peer.NeighborPort > 0 { + trans = &api.Transport{ + LocalAddress: bgph.config.RouterID, + MtuDiscovery: false, + PassiveMode: false, + RemoteAddress: peer.NeighborAddress, + RemotePort: uint32(peer.NeighborPort), + TcpMss: 0, + BindInterface: "", + } + } + err := bgph.server.AddPeer(ctx, &api.AddPeerRequest{ + Peer: &api.Peer{ + Conf: &api.PeerConf{ + AuthPassword: peer.Password, + NeighborAddress: peer.NeighborAddress, + PeerAsn: uint32(peer.Asn), + }, + EbgpMultihop: hop, + Transport: trans, + }, + }) + if err != nil { + result = multierror.Append(result, err) + continue + } + peerCount++ + } + if peerCount == 0 { + result = multierror.Append(result, ErrNoPeersAdded) + } + return result +} + +func (bgph *BGPHandler) AddRoutes(ctx context.Context, routes []string) error { + var result error + // Add our Anycast routes + + routesAdded := 0 + + for _, addr := range routes { + _, ipnet, err := net.ParseCIDR(addr) + if err != nil { + result = multierror.Append(result, err) + continue + } + prefixLen, _ := ipnet.Mask.Size() + af := api.Family_AFI_IP + if ipnet.IP.To4() == nil { + af = api.Family_AFI_IP6 + } + nlri, _ := apb.New(&api.IPAddressPrefix{ + PrefixLen: uint32(prefixLen), + Prefix: ipnet.IP.String(), + }) + _, err = bgph.server.AddPath(ctx, &api.AddPathRequest{ + Path: &api.Path{ + Nlri: nlri, + Pattrs: bgph.routeAttrs, + Family: &api.Family{ + Afi: af, + Safi: api.Family_SAFI_UNICAST, + }, + }, + }) + if err != nil { + log.Printf("[ERROR] bgp error adding path for %s: %s", addr, err) + result = multierror.Append(result, fmt.Errorf("error adding %s: %w", addr, err)) + } else { + log.Printf("[INFO] bgp successfully added path for %s", addr) + routesAdded++ + } + } + if routesAdded == 0 { + result = multierror.Append(result, ErrNoRoutesAdded) + } + return result +} + +func (bgph *BGPHandler) DeleteRoutes(ctx context.Context, routes []string) error { + var result error + delCount := 0 + for _, addr := range routes { + _, ipnet, err := net.ParseCIDR(addr) + if err != nil { + result = multierror.Append(result, err) + continue + } + prefixLen, _ := ipnet.Mask.Size() + af := api.Family_AFI_IP + if ipnet.IP.To4() == nil { + af = api.Family_AFI_IP6 + } + nlri, _ := apb.New(&api.IPAddressPrefix{ + PrefixLen: uint32(prefixLen), + Prefix: ipnet.IP.String(), + }) + err = bgph.server.DeletePath(ctx, &api.DeletePathRequest{ + TableType: api.TableType_GLOBAL, + Path: &api.Path{ + Nlri: nlri, + Family: &api.Family{ + Afi: af, + Safi: api.Family_SAFI_UNICAST, + }, + Pattrs: bgph.routeAttrs, + }, + }) + if err != nil { + result = multierror.Append(result, err) + continue + } + delCount++ + } + if delCount == 0 { + result = multierror.Append(result, ErrNoRoutesDeleted) + } + return result +} + +func ValidateConfig(config *config.BGP) error { + if config.BGPEnabled == false { + return nil + } + + for _, addr := range config.AnycastAddresses { + _, _, err := net.ParseCIDR(addr) + if err != nil { + return fmt.Errorf("could not parse cidr for anycast address %s: %w", addr, err) + } + } + + if config.EnableGRPC && config.GRPCTLS { + _, err := credentials.NewServerTLSFromFile(config.CertFile, config.KeyFile) + if err != nil { + return fmt.Errorf("could not parse bgp tls credentials: %w", err) + } + } + + for _, peer := range config.Peers { + if net.ParseIP(peer.NeighborAddress) == nil { + return fmt.Errorf("peer address %s is not a valid IP", peer.NeighborAddress) + } + } + + if len(config.GOBGPDCfgFile) > 0 { + _, err := bgpconfig.ReadConfigFile(config.GOBGPDCfgFile, "toml") + if err != nil { + return fmt.Errorf("could not open %s: %w", config.GOBGPDCfgFile, err) + } + // otherwise we skip the rest of these checks, hopefully the provided bobgpd config is sane. + return nil + } + + if len(config.AnycastAddresses) == 0 { + return ErrMissingAnycast + } + if len(config.Peers) == 0 { + return ErrMissingPeers + } + + if len(config.RouterID) == 0 { + return ErrMissingRouterID + } + if net.ParseIP(config.RouterID) == nil { + return fmt.Errorf("router ID %s is not a valid ID", config.RouterID) + } + if len(config.NextHop) > 0 { + if ip := net.ParseIP(config.NextHop); ip == nil { + return fmt.Errorf("invalid NextHop: %s", config.NextHop) + } + } + return nil +} diff --git a/bgp/bgp_test.go b/bgp/bgp_test.go new file mode 100644 index 000000000..1ad937a83 --- /dev/null +++ b/bgp/bgp_test.go @@ -0,0 +1,186 @@ +package bgp + +import ( + "context" + "encoding/json" + "github.com/fabiolb/fabio/config" + api "github.com/osrg/gobgp/v3/api" + "os" + "os/exec" + "path/filepath" + "testing" + "time" +) + +func TestBGPHandler(t *testing.T) { + serverCmd := &gobgpserver{ + cmdPath: "gobgpd", + } + err := serverCmd.start() + if err != nil { + t.Logf("error calling gobgpd command, probably not installed. skipping: %s", err) + t.SkipNow() + } + defer serverCmd.stop() + cfg := &config.BGP{ + BGPEnabled: true, + Asn: 65000, + AnycastAddresses: []string{"1.2.3.4/32"}, + RouterID: "127.0.0.2", + ListenPort: 1790, + ListenAddresses: []string{"127.0.0.2"}, + Peers: []config.BGPPeer{ + { + NeighborAddress: "127.0.0.3", + NeighborPort: 1790, + Asn: 65001, + MultiHop: false, + }, + }, + EnableGRPC: true, + GRPCListenAddress: "127.0.0.2:50051", + NextHop: "1.2.3.4", + } + bh, err := NewBGPHandler(cfg) + if err != nil { + t.Fatal(err) + } + go bh.server.Serve() + defer bh.server.Stop() + err = bh.startBGP(context.Background()) + if err != nil { + t.Fatalf("error starting BGP: %s", err) + } + err = bh.addNeighbors(context.Background(), cfg.Peers) + if err != nil { + t.Fatalf("error adding neighbors: %s", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*60) + defer cancel() + if err := bh.server.WatchEvent(context.Background(), &api.WatchEventRequest{Peer: &api.WatchEventRequest_Peer{}}, func(r *api.WatchEventResponse) { + if p := r.GetPeer(); p != nil && p.Type == api.WatchEventResponse_PeerEvent_STATE { + t.Logf("EVENT RECEIVED %#v", p.Peer) + if p.Peer.State.SessionState == api.PeerState_ESTABLISHED { + cancel() + } + } + }); err != nil { + t.Fatal(err) + } + + <-ctx.Done() + if ctx.Err() == context.DeadlineExceeded { + t.Fatal("context deadline exceeded") + } + + gc := gobpgclient{ + cmdPath: "gobgp", + hostAddr: "127.0.0.3", + } + + // now start a test table + + for _, tst := range []struct { + name string + cmd func() error + routeKeys []string + }{ + { + name: "test add route", + cmd: func() error { + return bh.AddRoutes(context.Background(), cfg.AnycastAddresses) + }, + routeKeys: []string{"1.2.3.4/32"}, + }, + { + name: "test delete route", + cmd: func() error { + return bh.DeleteRoutes(context.Background(), []string{"1.2.3.4/32"}) + }, + routeKeys: nil, + }, + } { + t.Run(tst.name, func(t *testing.T) { + err := tst.cmd() + if err != nil { + t.Fatal(err) + } + routes, err := gc.globalRib(t) + if err != nil { + t.Fatal(err) + } + if len(routes) != len(tst.routeKeys) { + t.Fatalf("routes don't match, have %d want %d", + len(routes), len(tst.routeKeys)) + } + for _, r := range tst.routeKeys { + if _, ok := routes[r]; !ok { + t.Fatalf("route %s not found", r) + } + } + }) + } + +} + +type ribEntry struct { + Nlri struct { + Prefix string `json:"prefix"` + } `json:"nlri"` + Age int `json:"age"` + Best bool `json:"best"` + Attrs []struct { + Type int `json:"type"` + Value int `json:"value,omitempty"` + AsPaths []struct { + SegmentType int `json:"segment_type"` + Num int `json:"num"` + Asns []int `json:"asns"` + } `json:"as_paths,omitempty"` + Nexthop string `json:"nexthop,omitempty"` + } `json:"attrs"` + Stale bool `json:"stale"` +} + +type gobpgclient struct { + cmdPath string + hostAddr string +} + +func (gc *gobpgclient) globalRib(t *testing.T) (map[string][]ribEntry, error) { + out, err := exec.Command(gc.cmdPath, "-u", gc.hostAddr, "-j", "global", "rib").Output() + if err != nil { + return nil, err + } + var rv map[string][]ribEntry + err = json.Unmarshal(out, &rv) + if err != nil { + t.Logf("raw: %s\n", out) + return nil, err + } + return rv, nil +} + +type gobgpserver struct { + cmdPath string + cmd *exec.Cmd +} + +func (gs *gobgpserver) start() error { + gs.cmd = exec.Command(gs.cmdPath, + "-p", + "-f", filepath.Join("test_data", "bgp.toml"), + "--api-hosts", "127.0.0.3:50051", + "-l", "info") + gs.cmd.Stdout = os.Stdout + gs.cmd.Stderr = os.Stderr + return gs.cmd.Start() +} + +func (gs *gobgpserver) stop() error { + if gs.cmd.Process != nil { + return gs.cmd.Process.Kill() + } + return nil +} diff --git a/bgp/logger.go b/bgp/logger.go new file mode 100644 index 000000000..703845ee3 --- /dev/null +++ b/bgp/logger.go @@ -0,0 +1,77 @@ +package bgp + +import ( + "fmt" + "log" + "strings" + + "github.com/fabiolb/fabio/exit" + "github.com/fabiolb/fabio/logger" + + bgplog "github.com/osrg/gobgp/v3/pkg/log" +) + +type bgpLogger struct{} + +func (l bgpLogger) Panic(msg string, fields bgplog.Fields) { + exit.Fatal(convertMsgFields("FATAL", msg, fields)) +} + +func (l bgpLogger) Fatal(msg string, fields bgplog.Fields) { + exit.Fatal(convertMsgFields("FATAL", msg, fields)) +} + +func (l bgpLogger) Error(msg string, fields bgplog.Fields) { + log.Printf(convertMsgFields("ERROR", msg, fields)) +} + +func (l bgpLogger) Warn(msg string, fields bgplog.Fields) { + log.Printf(convertMsgFields("WARN", msg, fields)) + +} + +func (l bgpLogger) Info(msg string, fields bgplog.Fields) { + log.Printf(convertMsgFields("INFO", msg, fields)) +} + +func (l bgpLogger) Debug(msg string, fields bgplog.Fields) { + log.Printf(convertMsgFields("DEBUG", msg, fields)) + +} + +func (l bgpLogger) SetLevel(level bgplog.LogLevel) { + // noop +} + +func (l bgpLogger) GetLevel() bgplog.LogLevel { + lw, ok := log.Writer().(*logger.LevelWriter) + if !ok { + return bgplog.InfoLevel + } + + switch lw.Level() { + case "TRACE": + return bgplog.TraceLevel + case "DEBUG": + return bgplog.DebugLevel + case "INFO": + return bgplog.InfoLevel + case "WARN": + return bgplog.WarnLevel + case "ERROR": + return bgplog.ErrorLevel + case "FATAL": + return bgplog.FatalLevel + default: + return bgplog.InfoLevel + } +} + +func convertMsgFields(level, msg string, fields bgplog.Fields) string { + var b strings.Builder + fmt.Fprintf(&b, "[%s] gobgpd %s", level, msg) + for k, v := range fields { + fmt.Fprintf(&b, " %s=>%v", k, v) + } + return b.String() +} diff --git a/bgp/test_data/bgp.toml b/bgp/test_data/bgp.toml new file mode 100644 index 000000000..85fc137c1 --- /dev/null +++ b/bgp/test_data/bgp.toml @@ -0,0 +1,15 @@ +[[neighbors]] + [neighbors.config] + neighbor-address = "127.0.0.2" + peer-as = 65000 + [neighbors.transport.config] + remote-port = 1790 + passive-mode = false + local-address = "127.0.0.3" + +[global.config] + as = 65001 + router-id = "127.0.0.3" + port = 1790 + #port = 179 + local-address-list = [ "127.0.0.3" ] diff --git a/config/config.go b/config/config.go index 484af7293..edeaee5b7 100644 --- a/config/config.go +++ b/config/config.go @@ -20,6 +20,7 @@ type Config struct { Insecure bool GlobMatchingDisabled bool GlobCacheSize int + BGP BGP } type CertSource struct { @@ -229,3 +230,29 @@ type ConsulTlS struct { CAPath string InsecureSkipVerify bool } + +type BGP struct { + BGPEnabled bool + Asn uint + AnycastAddresses []string + RouterID string + ListenPort int + ListenAddresses []string + Peers []BGPPeer + EnableGRPC bool + GRPCListenAddress string + GRPCTLS bool + CertFile string + KeyFile string + GOBGPDCfgFile string + NextHop string +} + +type BGPPeer struct { + NeighborAddress string + NeighborPort uint + Asn uint + MultiHop bool + MultiHopLength uint + Password string +} diff --git a/config/default.go b/config/default.go index de9f00594..4487dea44 100644 --- a/config/default.go +++ b/config/default.go @@ -15,6 +15,7 @@ var defaultValues = struct { IdleTimeout time.Duration UIListenerValue string GZIPContentTypesValue string + BGPPeersValue string }{ ListenerValue: ":9999", UIListenerValue: ":9998", @@ -122,4 +123,20 @@ var defaultConfig = &Config{ }, GlobCacheSize: 1000, + + BGP: BGP{ + BGPEnabled: false, + Asn: 65000, + AnycastAddresses: nil, + RouterID: "", + ListenPort: 179, + ListenAddresses: []string{"0.0.0.0"}, + Peers: nil, + EnableGRPC: false, + GRPCListenAddress: "127.0.0.1:50051", + }, +} + +var defaultBGPPeer = &BGPPeer{ + MultiHopLength: 2, } diff --git a/config/load.go b/config/load.go index f0e38397a..cccd982eb 100644 --- a/config/load.go +++ b/config/load.go @@ -132,6 +132,8 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c var obsoleteStr string + var bgpPeersValue string + f.BoolVar(&cfg.Insecure, "insecure", defaultConfig.Insecure, "allow fabio to run as root when set to true") f.IntVar(&cfg.Proxy.MaxConn, "proxy.maxconn", defaultConfig.Proxy.MaxConn, "maximum number of cached connections") f.StringVar(&cfg.Proxy.Strategy, "proxy.strategy", defaultConfig.Proxy.Strategy, "load balancing strategy") @@ -250,6 +252,17 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c f.StringVar(&cfg.Registry.Custom.Path, "registry.custom.path", defaultConfig.Registry.Custom.Path, "custom back end path in the URL") f.StringVar(&cfg.Registry.Custom.QueryParams, "registry.custom.queryparams", defaultConfig.Registry.Custom.QueryParams, "custom back end query parameters in the URL") + f.BoolVar(&cfg.BGP.BGPEnabled, "bgp.enabled", defaultConfig.BGP.BGPEnabled, "enabled bgp announcements") + f.UintVar(&cfg.BGP.Asn, "bgp.asn", defaultConfig.BGP.Asn, "our BGP asn") + f.StringSliceVar(&cfg.BGP.AnycastAddresses, "bgp.anycastaddresses", defaultConfig.BGP.AnycastAddresses, "comma separated list of CIDRs to broadcast - required if bgp is enabled") + f.StringVar(&cfg.BGP.RouterID, "bgp.routerid", defaultConfig.BGP.RouterID, "our router ID - required if bgp is enabled") + f.IntVar(&cfg.BGP.ListenPort, "bgp.listenport", defaultConfig.BGP.ListenPort, "bgp listen port. -1 means disabled") + f.StringSliceVar(&cfg.BGP.ListenAddresses, "bgp.listenaddresses", defaultConfig.BGP.ListenAddresses, "bgp listen address") + f.StringVar(&bgpPeersValue, "bgp.peers", defaultValues.BGPPeersValue, "bgp peers. comma separated list of neighboraddress=1.2.3.4;asn=65001") + f.BoolVar(&cfg.BGP.EnableGRPC, "bgp.enablegrpc", defaultConfig.BGP.EnableGRPC, "enable bgp grpc listener for use with gobgp cli") + f.StringVar(&cfg.BGP.GRPCListenAddress, "bgp.grpclistenaddress", defaultConfig.BGP.GRPCListenAddress, "bgp grpc cli listen address") + f.StringVar(&cfg.BGP.NextHop, "bgp.nexthop", defaultConfig.BGP.NextHop, "specify the next-hop. defaults to bgp.routerid") + f.StringVar(&cfg.BGP.GOBGPDCfgFile, "bgp.gobgpdcfgfile", defaultConfig.BGP.GOBGPDCfgFile, "specify path to gobgpd config file. overrides settings") // deprecated flags var proxyLogRoutes string f.StringVar(&proxyLogRoutes, "proxy.log.routes", "", "deprecated. use log.routes.format instead") @@ -367,6 +380,11 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c cfg.Log.RoutesFormat = proxyLogRoutes } + cfg.BGP.Peers, err = parseBGPPeers(bgpPeersValue) + if err != nil { + return nil, err + } + return cfg, nil } @@ -705,3 +723,57 @@ func parseAuthScheme(cfg map[string]string) (a AuthScheme, err error) { return } + +func parseBGPPeers(cfgs string) ([]BGPPeer, error) { + kvs, err := parseKVSlice(cfgs) + if err != nil { + return nil, err + } + var peers []BGPPeer + for _, cfg := range kvs { + peer, err := parseBGPPeer(cfg) + if err != nil { + return nil, err + } + peers = append(peers, peer) + } + return peers, nil +} + +func parseBGPPeer(cfg map[string]string) (BGPPeer, error) { + var peer = *defaultBGPPeer + for k, v := range cfg { + switch k { + case "address": + peer.NeighborAddress = v + case "port": + u, err := strconv.ParseUint(v, 10, 32) + if err != nil { + return peer, err + } + peer.NeighborPort = uint(u) + case "asn": + u, err := strconv.ParseUint(v, 10, 32) + if err != nil { + return peer, err + } + peer.Asn = uint(u) + case "multihop": + b, err := strconv.ParseBool(v) + if err != nil { + return peer, err + } + peer.MultiHop = b + case "multihoplength": + u, err := strconv.ParseUint(v, 10, 32) + if err != nil { + return peer, err + } + peer.MultiHopLength = uint(u) + case "password": + peer.Password = v + } + + } + return peer, nil +} diff --git a/config/load_test.go b/config/load_test.go index 0dadd8aa8..747d74215 100644 --- a/config/load_test.go +++ b/config/load_test.go @@ -1141,6 +1141,24 @@ func TestLoad(t *testing.T) { cfg: func(cfg *Config) *Config { return nil }, err: errInvalidConfig, }, + { + desc: "valid bgp peers", + args: []string{"-bgp.peers", "address=127.0.0.3;port=1179;asn=65000;" + + "multihop=true;multihoplength=5;password=hunter2"}, + cfg: func(cfg *Config) *Config { + cfg.BGP.Peers = []BGPPeer{ + { + NeighborAddress: "127.0.0.3", + NeighborPort: 1179, + Asn: 65000, + MultiHop: true, + MultiHopLength: 5, + Password: "hunter2", + }, + } + return cfg + }, + }, } for _, tt := range tests { diff --git a/docs/content/feature/_index.md b/docs/content/feature/_index.md index eeb8e503f..f6bf9a8a1 100644 --- a/docs/content/feature/_index.md +++ b/docs/content/feature/_index.md @@ -25,3 +25,4 @@ The following list provides a list of features supported by fabio. * [Traffic Shaping](/feature/traffic-shaping/) - forward N% of traffic upstream without knowing the number of instances * [Web UI](/feature/web-ui/) - web ui to examine the current routing table * [Websocket Support](/feature/websockets/) - websocket support + * [BGP Support](/feature/bgp) - bgp support diff --git a/docs/content/feature/bgp.md b/docs/content/feature/bgp.md new file mode 100644 index 000000000..0e9651748 --- /dev/null +++ b/docs/content/feature/bgp.md @@ -0,0 +1,60 @@ +--- +title: "BGP" +since: "1.6.3" +--- + +This feature integrates the functionality of [gobgpd](https://github.com/osrg/gobgp) +with fabio. This is particularly useful in the scenario where we are using +anycast IP addresses and want to dynamically advertise to upstream routers +when we're ready to receive traffic. In the past, we've used external router +packages such as quagga or frr to handle this for us, but it's potentially +messy to make sure that the route advertisement stops if fabio goes down, +and the bgp daemon is started back up once fabio is running again. +By integrating the bgp advertisement with the proxy server, we've made +sure that when fabio goes down, the route is no longer advertised and +traffic can be sent to other fabio instances accordingly. When fabio is back up, +the route is advertised again. + +Further, the gobgp [command line client](https://github.com/osrg/gobgp/blob/master/docs/sources/cli-command-syntax.md) +is fully supported by enabling +the [bgp.enablegrpc](/ref/bgp.enablegrpc/) option. + +[Multihop](/ref/bgp.multihop/) is supported, where fabio may not be +on the same subnet as neighbor. + +To enable BGP, you must at a minimum: +* Set up an anycast interface on the host with a /32 address. On linux, the dummy interface type is a good option + since it's supported using network manager. Another option is hanging this address off of loopback. +* Configure the neighbor / peer / upstream router to allow us to peer, and to allow our anycast as a prefix it will + accept +* Set [bgp.enabled](/ref/bgp.enabled/)=true +* Configure the [bgp.asn](/ref/bgp.asn/) to be our router's Asn - probably use a private ASN here +* Configure the [bgp.routerid](/ref/bgp.routerid/) to be our router's IP address (i.e., not the anycast address, + something unique). This will be the default nexthop of all routes we publish. +* Configure the [bgp.peers](/ref/bgp.peers/) for at least one nieghbor. +* Configure the [bgp.anycastaddresses](/ref/bgp.anycastaddresses) for at least one anycast address. + +This will embed a gobgpd instance inside of fabio on startup and it will publish the configure anycast addresses. +It will also configure a [gobgpd policy](https://github.com/osrg/gobgp/blob/master/docs/sources/policy.md) +that will reject all incoming prefixes from neighbors. + +Alternatively, for more advanced use cases, you can reference an [external gobgpd config file](/ref/bgp.gobgpdcfgfile/) +that will override many of the options set in the fabio config, including the policy +blocking us from accepting prefixes from neighbors. You still need to specify the bgp.grpc +options from the fabio config since there is no analog in the gobgpd config file. +You may still specify bgp anycastaddresses or bgp.peers from +the fabio config, but we ignore anything +that would be specified in the global section of the gobgpd config file, including router ID and +the ASN. Even If the bgp.gobgpdcfgfile value is set, fabio will still honor any values +configured for bgp.anycastaddresses or bgp.peers. These will be processed after the config +file is processed. + + +### Note +For situations where multiple fabio instances are running with the same anycast address +in the same datacenter, or in any other situation where the path distance +is the same and load balancing across multiple fabio instances is desired, +the details of ECMP configuration is outside the scope of +this document as configuration would vary greatly depending on the +details of the upstream router. + diff --git a/docs/content/ref/bgp.anycastaddresses.md b/docs/content/ref/bgp.anycastaddresses.md new file mode 100644 index 000000000..65f37a419 --- /dev/null +++ b/docs/content/ref/bgp.anycastaddresses.md @@ -0,0 +1,14 @@ +--- +title: "bgp.anycastaddresses" +--- + +`bgp.anycastaddresses` sets the anycast addresses we will advertise, +separated by comma. Technically this will advertise any route prefix. +These should already be configured on the host probably hung off loopback. + For example, 192.168.5.3/32. + +The default value is + + bgp.anycastaddresses = + +If bgp is enabled, this must be defined. diff --git a/docs/content/ref/bgp.asn.md b/docs/content/ref/bgp.asn.md new file mode 100644 index 000000000..574fa5bbb --- /dev/null +++ b/docs/content/ref/bgp.asn.md @@ -0,0 +1,9 @@ +--- +title: "bgp.asn" +--- + +`bgp.asn` sets the asn ID of our router + +The default value is + + bgp.asn = 65000 diff --git a/docs/content/ref/bgp.certfile.md b/docs/content/ref/bgp.certfile.md new file mode 100644 index 000000000..3c7ec1245 --- /dev/null +++ b/docs/content/ref/bgp.certfile.md @@ -0,0 +1,11 @@ +--- +title: "bgp.certfile" +--- + +`bgp.certfile` is the file path of the certificate, and is required if bgp.grpctls is set to true. + + +The default value is + + bgp.certfile = + diff --git a/docs/content/ref/bgp.enabled.md b/docs/content/ref/bgp.enabled.md new file mode 100644 index 000000000..001e52d76 --- /dev/null +++ b/docs/content/ref/bgp.enabled.md @@ -0,0 +1,9 @@ +--- +title: "bgp.enabled" +--- + +`bgp.enabled` enables the embedded gobgpd daemon + +The default value is + + bgp.enabled = false diff --git a/docs/content/ref/bgp.enablegrpc.md b/docs/content/ref/bgp.enablegrpc.md new file mode 100644 index 000000000..7837f5b41 --- /dev/null +++ b/docs/content/ref/bgp.enablegrpc.md @@ -0,0 +1,13 @@ +--- +title: "bgp.enablegrpc" +--- + +`bgp.enablegrpc` enables the gobgp grpc interface. +To be used with the gobgp command line client. + + + +The default value is + + bgp.enablegrpc = false + diff --git a/docs/content/ref/bgp.gobgpdcfgfile.md b/docs/content/ref/bgp.gobgpdcfgfile.md new file mode 100644 index 000000000..c01dccc14 --- /dev/null +++ b/docs/content/ref/bgp.gobgpdcfgfile.md @@ -0,0 +1,17 @@ +--- +title: "bgp.gobgpdcfgfile" +--- + +`bgp.gobgpdcfgfile` is the optional file path to a +gobgpd [config file](https://github.com/osrg/gobgp/blob/master/docs/sources/configuration.md). +This overrides the global config +items, such as bgp.routerid, bgp.asn etc. This also skips automatically adding gobgpd +[policies](https://github.com/osrg/gobgp/blob/master/docs/sources/policy.md) +that restrict / disallow accepting prefixes from neighbors. Only use +this if you know what you're doing, this is to allow +for more flexibility than we expose directly with fabio. + +The default value is + + bgp.gobgpdcfgfile = + diff --git a/docs/content/ref/bgp.grpclistenaddress.md b/docs/content/ref/bgp.grpclistenaddress.md new file mode 100644 index 000000000..7e0189f1a --- /dev/null +++ b/docs/content/ref/bgp.grpclistenaddress.md @@ -0,0 +1,12 @@ +--- +title: "bgp.grpclistenaddress" +--- + +`bgp.grpclistenaddress` is the listen interface and port if bgp.enablegrpc is set to true. + + + +The default value is + + bgp.grpclistenaddress = 127.0.0.1:50051 + diff --git a/docs/content/ref/bgp.grpctls.md b/docs/content/ref/bgp.grpctls.md new file mode 100644 index 000000000..9ddb197a8 --- /dev/null +++ b/docs/content/ref/bgp.grpctls.md @@ -0,0 +1,11 @@ +--- +title: "bgp.grpctls" +--- + +`bgp.grpctls` is whether to enable TLS on the bgp grpc interface. + + +The default value is + + bgp.grpctls = false + diff --git a/docs/content/ref/bgp.keyfile.md b/docs/content/ref/bgp.keyfile.md new file mode 100644 index 000000000..d2fcd693f --- /dev/null +++ b/docs/content/ref/bgp.keyfile.md @@ -0,0 +1,11 @@ +--- +title: "bgp.keyfile" +--- + +`bgp.keyfile` is the file path of the key file, and is required if bgp.grpctls is set to true. + + +The default value is + + bgp.keyfile = + diff --git a/docs/content/ref/bgp.listenaddresses.md b/docs/content/ref/bgp.listenaddresses.md new file mode 100644 index 000000000..03a2395c1 --- /dev/null +++ b/docs/content/ref/bgp.listenaddresses.md @@ -0,0 +1,11 @@ +--- +title: "bgp.listenaddresses" +--- + +`bgp.listenaddresses` sets the listen addresses for bgp, separated by comma. + +The default value is + + bgp.listenaddresses = 0.0.0.0 + +which listens on all interfaces. diff --git a/docs/content/ref/bgp.listenport.md b/docs/content/ref/bgp.listenport.md new file mode 100644 index 000000000..b37bfc78d --- /dev/null +++ b/docs/content/ref/bgp.listenport.md @@ -0,0 +1,11 @@ +--- +title: "bgp.listenport" +--- + +`bgp.listenport` sets the listen ports for bgp communication from other routers. + +The default value is + + bgp.listenport = 179 + +The default bgp port is 179. diff --git a/docs/content/ref/bgp.nexthop.md b/docs/content/ref/bgp.nexthop.md new file mode 100644 index 000000000..c0cb68c6a --- /dev/null +++ b/docs/content/ref/bgp.nexthop.md @@ -0,0 +1,11 @@ +--- +title: "bgp.nexthop" +--- + +`bgp.nexthop` sets the next hop address. +If not set, it uses the [bgp.routerid](/ref/bgp.routerid/) instead. + +The default value is + + bgp.nexthop = + diff --git a/docs/content/ref/bgp.peers.md b/docs/content/ref/bgp.peers.md new file mode 100644 index 000000000..d761ba535 --- /dev/null +++ b/docs/content/ref/bgp.peers.md @@ -0,0 +1,22 @@ +--- +title: "bgp.peers" +--- + +`bgp.peers` sets the bgp peers we will advertise routes to. This is required if bgp is enabled. +bgp.peers is specified as a comma separated list of neighboraddress and asn pairs, i.e. + + bgp.peers = address=1.2.3.4;asn=65001,address=5.6.7.8;asn=65002 + +valid parameters for peers are: + + address - required + port - optional, defaults to 179 + asn - required + multihop - optional, defaults to false + multihoplength - optional, defaults to 2 + password - optional + +The default value is + + bgp.peers = + diff --git a/docs/content/ref/bgp.routerid.md b/docs/content/ref/bgp.routerid.md new file mode 100644 index 000000000..6f5981e79 --- /dev/null +++ b/docs/content/ref/bgp.routerid.md @@ -0,0 +1,13 @@ +--- +title: "bgp.routerid" +--- + +`bgp.routerid` is the router id (ip address) of this router. +This is required if bgp is enabled. This should be the unique IP +address, not any anycast. This will also be used as +the default nexthop address unless [bgp.nexthop](/ref/bgp.nexthop/) +is specified. + +The default value is + + bgp.routerid = diff --git a/fabio.iml b/fabio.iml index 8021953ed..49df094a9 100644 --- a/fabio.iml +++ b/fabio.iml @@ -1,5 +1,6 @@ + diff --git a/fabio.properties b/fabio.properties index 74a0cb1a2..814b42132 100644 --- a/fabio.properties +++ b/fabio.properties @@ -1455,3 +1455,94 @@ # # The default is # tracing.SpanHost = localhost:9998 + +# BGP Anycast configuration +# Experimental. Leopards will eat your face. + +# bgp.enabled enables the embedded gobgpd daemon. +# The default is + +# bgp.enabled = false + +# bgp.asn sets the asn ID of our router +# The default is: +# bgp.asn = 65000 + +# bgp.anycastaddresses sets the anycast addresses we will advertise, separated by comma. Technically this +# will advertise any route prefix. These should already be configured on the host probably hung off loopback. +# for example, 192.168.5.3/32. The default value is: + +# bgp.anycastaddresses = +# +# If bgp is enabled, this must be defined. + +# bgp.routerid is the router id (ip address) of this router. This is required if bgp is enabled. +# the default value is: + +# bgp.routerid = + +# +# bgp.listenport sets the listen ports for bgp communication from other routers. +# default vaule is : + +# bgp.listenport = 179 + +# bgp.listenaddresses sets the listen addresses for bgp, separated by comma. The default is + +# bgp.listenaddresses = 0.0.0.0 + +# which listens on all interfaces. + +# bgp.nexthop sets the next hop address. If not set, it uses the bgp.routerid instead. +# default value: + +# bgp.nexthop = + +# bgp.peers sets the bgp peers we will advertise routes to. This is required if bgp is enabled. +# bgp.peers is specified as a comma separated list of neighboraddress and asn pairs, i.e. +# bgp.peers = address=1.2.3.4;asn=65001,address=5.6.7.8;asn=65002 +# valid parameters for peers are: +# address - required +# port - optional, defaults to 179 +# asn - required +# multihop - optional, defaults to false +# multihoplength - optional, defaults to 2 +# password - optional + +# default value +# bgp.peers = + +# bgp.enablegrpc enables the gobgp grpc interface. To be used with the gobgp command line client. +# default value is: + +# bgp.enablegrpc=false + +# bgp.grpclistenaddress is the listen interface and port if bgp.enablegrpc is set to true. defaults to: + +# bgp.grpclistenaddress = 127.0.0.1:50051 + +# bgp.grpctls is whether to enable TLS on the bgp grpc interface. default value is: + +# bgp.grpctls = false + +# bgp.certfile is the file path of the certificate, and is required if bgp.grpctls is set to true. Default value is: + +# bgp.certfile = + +# bgp.keyfile is the file path of the key file, and is required if bgp.grpctls is set to true. Default value is: + +# bgp.keyfile = + +# bgp.nexthop explicitly sets the value of the nexthop for all routes we publish. If not set, this uses the +# bgp.routerid value, which is what makes sense in most cases. Default value is: + +# bgp.nexthop = + +# bgp.gobgpdcfgfile is the optional file path to a gobgpd config file. This overrides the global config +# items above, such as bgp.routerid, bgp.asn etc. This also skips +# # automatically adding gobgpd policies that prevent us from accepting prefixes from neighbors. only +# use this if you know what you're doing, this is to allow for more flexibility than we expose directly +# with fabio. + +# default value is: +# bgp.gobgpdcfgfile = diff --git a/go.mod b/go.mod index dcecb0e0f..abadb15ab 100644 --- a/go.mod +++ b/go.mod @@ -5,40 +5,30 @@ require ( github.com/Shopify/toxiproxy v2.1.4+incompatible // indirect github.com/VividCortex/gohistogram v1.0.0 // indirect github.com/apache/thrift v0.13.0 // indirect - github.com/armon/go-metrics v0.3.4 // indirect github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f github.com/circonus-labs/circonus-gometrics/v3 v3.2.0 github.com/circonus-labs/go-apiclient v0.7.9 // indirect github.com/eapache/go-resiliency v1.1.0 // indirect github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect - github.com/eapache/queue v1.1.0 // indirect github.com/frankban/quicktest v1.11.1 // indirect github.com/go-kit/kit v0.9.0 github.com/go-logfmt/logfmt v0.5.0 // indirect github.com/gobwas/glob v0.0.0-20180208211842-19c076cdf202 - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.4.3 // indirect - github.com/golang/snappy v0.0.2 // indirect - github.com/google/btree v1.0.0 // indirect - github.com/hashicorp/consul/api v1.7.0 + github.com/hashicorp/consul/api v1.12.0 github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-hclog v0.14.1 // indirect - github.com/hashicorp/go-immutable-radix v1.3.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.6.7 // indirect github.com/hashicorp/go-sockaddr v1.0.2 - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/serf v0.9.5 // indirect github.com/hashicorp/vault/api v1.0.4 github.com/hashicorp/vault/sdk v0.1.13 github.com/inetaf/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252 - github.com/magiconair/properties v1.8.4 - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mitchellh/mapstructure v1.3.3 // indirect + github.com/magiconair/properties v1.8.5 github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76 github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect github.com/opentracing/opentracing-go v1.2.0 github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5 + github.com/osrg/gobgp/v3 v3.8.0 github.com/pascaldekloe/goe v0.1.0 github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pkg/profile v1.5.0 @@ -47,15 +37,13 @@ require ( github.com/rogpeppe/fastuuid v1.2.0 github.com/sergi/go-diff v1.2.0 github.com/tg123/go-htpasswd v1.0.0 - golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect - golang.org/x/net v0.0.0-20201021035429-f5854403a974 - golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 + golang.org/x/net v0.0.0-20220225172249-27dd8689420f + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 // indirect golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect - google.golang.org/grpc v1.33.0 - google.golang.org/protobuf v1.25.0 // indirect + google.golang.org/grpc v1.50.1 + google.golang.org/protobuf v1.28.1 gopkg.in/square/go-jose.v2 v2.5.1 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect ) go 1.16 diff --git a/go.sum b/go.sum index 293ee8310..91c770b61 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,55 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= @@ -11,12 +60,13 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.4 h1:Xqf+7f2Vhl9tsqDYmXhnXInUdcrtgpRNpIA15/uldSc= -github.com/armon/go-metrics v0.3.4/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f h1:SaJ6yqg936TshyeFZqQE+N+9hYkIeL9AMr7S4voCl10= github.com/armon/go-proxyproto v0.0.0-20180202201750-5b7edb60ff5f/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -27,8 +77,15 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonus-gometrics/v3 v3.2.0 h1:i50XamqTYFi/bFFZGiREXehet8DPsaa/XExTmXTjjMc= @@ -41,9 +98,26 @@ github.com/circonus-labs/go-apiclient v0.7.9 h1:OYDi4XeO8RLPW22RDKb0vIfd2mZUj4Hv github.com/circonus-labs/go-apiclient v0.7.9/go.mod h1:7PoP39q4+O82aWOsd0/3bMvBon6HCBwrs7g+/DXczNc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k= +github.com/eapache/channels v1.1.0/go.mod h1:jMm2qB5Ubtg9zLd+inMZd2/NUvXgzmWXsDaLyQIGfH0= github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw= @@ -53,13 +127,28 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/frankban/quicktest v1.11.1 h1:stwUsXhUGliQs9t0ZS39BWCltFdOHgABiIlihop8AD4= github.com/frankban/quicktest v1.11.1/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -71,28 +160,49 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobwas/glob v0.0.0-20180208211842-19c076cdf202 h1:XcHVP1KCiY3CQI5oi8+7pRPD/5dC2NbhGZLn5CFGO74= github.com/gobwas/glob v0.0.0-20180208211842-19c076cdf202/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -100,36 +210,71 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/consul/api v1.7.0 h1:tGs8Oep67r8CcA2Ycmb/8BLBcJ70St44mF2X10a/qPg= -github.com/hashicorp/consul/api v1.7.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= -github.com/hashicorp/consul/sdk v0.6.0 h1:FfhMEkwvQl57CildXJyGHnwGGM4HMODGyfjGwNM1Vdw= -github.com/hashicorp/consul/sdk v0.6.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.12.0 h1:k3y1FYv6nuKyNTqj6w9gXOx5r5CfLj/k/euUeBXj1OY= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0 h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= -github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -154,52 +299,68 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.3/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU= github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inetaf/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252 h1:jeqlfkFa5h+Ak/I33QpU4p01nFhw0G5IFm/Rsenne2Y= github.com/inetaf/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252/go.mod h1:R6mExYS3O0XXjOZye3GtXfbuGF4hWQnF45CFWoj7O6g= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/k-sone/critbitgo v1.4.0 h1:l71cTyBGeh6X5ATh6Fibgw3+rtNT80BA0uNNWgkPrbE= +github.com/k-sone/critbitgo v1.4.0/go.mod h1:7E6pyoyADnFxlUBEKcnfS49b7SUAQGMK+OAp/UQvo0s= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= -github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -211,13 +372,14 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76 h1:0xuRacu/Zr+jX+KyLLPPktbwXqyOvnOPUQmMLzX1jxU= github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= @@ -228,9 +390,13 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5 h1:82Tnq9OJpn+h5xgGpss5/mOv3KXdjtkdorFSOUusjM8= github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI= +github.com/osrg/gobgp/v3 v3.8.0 h1:JY/i0TTm99p58o6TQduVyCcYuSD0LNPNBNzPhQsTeTU= +github.com/osrg/gobgp/v3 v3.8.0/go.mod h1:fKQPuk7+4qMiDT5viZTXT/aSEn8yYDkEs5p3NjmU2bw= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -240,6 +406,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -264,125 +431,477 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= +github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tg123/go-htpasswd v1.0.0 h1:Ze/pZsz73JiCwXIyJBPvNs75asKBgfodCf8iTEkgkXs= github.com/tg123/go-htpasswd v1.0.0/go.mod h1:eQTgl67UrNKQvEPKrDLGBssjVwYQClFZjALVLhIv8C0= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA852UkGH42H+Oee69djmxS3ANzl2b/JtT1YiA= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM= golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.0 h1:IBKSUNL2uBS2DkJBncPP+TwT0sp9tgA8A75NjHt6umg= -google.golang.org/grpc v1.33.0/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -391,22 +910,43 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index 8d3caba59..034825df9 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "encoding/json" "fmt" + "github.com/fabiolb/fabio/bgp" "github.com/fabiolb/fabio/transport" gkm "github.com/go-kit/kit/metrics" "io" @@ -112,6 +113,13 @@ func main() { log.Printf("[INFO] Profile path %q", cfg.ProfilePath) } + if cfg.BGP.BGPEnabled { + err = bgp.ValidateConfig(&cfg.BGP) + if err != nil { + log.Fatalf("[FATAL] BGP configuration invalid: %s", err) + } + } + exit.Listen(func(s os.Signal) { atomic.StoreInt32(&shuttingDown, 1) if registry.Default != nil { @@ -149,7 +157,9 @@ func main() { // warn again so that it is visible in the terminal WarnIfRunAsRoot(cfg.Insecure) - + if cfg.BGP.BGPEnabled { + startBGP(&cfg.BGP) + } exit.Wait() log.Print("[INFO] Down") } @@ -498,6 +508,18 @@ func startServers(cfg *config.Config, stats metrics.Provider) { } } +func startBGP(cfg *config.BGP) { + h, err := bgp.NewBGPHandler(cfg) + if err != nil { + exit.Fatal("[FATAL] ", err) + } + go func() { + if err := h.Start(); err != nil { + exit.Fatal("[FATAL] ", err) + } + }() +} + func initRuntime(cfg *config.Config) { if os.Getenv("GOGC") == "" { log.Print("[INFO] Setting GOGC=", cfg.Runtime.GOGC) diff --git a/vendor/github.com/armon/go-metrics/inmem.go b/vendor/github.com/armon/go-metrics/inmem.go index e8206daab..7c427aca9 100644 --- a/vendor/github.com/armon/go-metrics/inmem.go +++ b/vendor/github.com/armon/go-metrics/inmem.go @@ -55,6 +55,10 @@ type IntervalMetrics struct { // Samples maps the key to an AggregateSample, // which has the rolled up view of a sample Samples map[string]SampledValue + + // done is closed when this interval has ended, and a new IntervalMetrics + // has been created to receive any future metrics. + done chan struct{} } // NewIntervalMetrics creates a new IntervalMetrics for a given interval @@ -65,6 +69,7 @@ func NewIntervalMetrics(intv time.Time) *IntervalMetrics { Points: make(map[string][]float32), Counters: make(map[string]SampledValue), Samples: make(map[string]SampledValue), + done: make(chan struct{}), } } @@ -245,6 +250,8 @@ func (i *InmemSink) Data() []*IntervalMetrics { copyCurrent := intervals[n-1] current.RLock() *copyCurrent = *current + // RWMutex is not safe to copy, so create a new instance on the copy + copyCurrent.RWMutex = sync.RWMutex{} copyCurrent.Gauges = make(map[string]GaugeValue, len(current.Gauges)) for k, v := range current.Gauges { @@ -268,33 +275,39 @@ func (i *InmemSink) Data() []*IntervalMetrics { return intervals } -func (i *InmemSink) getExistingInterval(intv time.Time) *IntervalMetrics { - i.intervalLock.RLock() - defer i.intervalLock.RUnlock() +// getInterval returns the current interval. A new interval is created if no +// previous interval exists, or if the current time is beyond the window for the +// current interval. +func (i *InmemSink) getInterval() *IntervalMetrics { + intv := time.Now().Truncate(i.interval) + // Attempt to return the existing interval first, because it only requires + // a read lock. + i.intervalLock.RLock() n := len(i.intervals) if n > 0 && i.intervals[n-1].Interval == intv { + defer i.intervalLock.RUnlock() return i.intervals[n-1] } - return nil -} + i.intervalLock.RUnlock() -func (i *InmemSink) createInterval(intv time.Time) *IntervalMetrics { i.intervalLock.Lock() defer i.intervalLock.Unlock() - // Check for an existing interval - n := len(i.intervals) + // Re-check for an existing interval now that the lock is re-acquired. + n = len(i.intervals) if n > 0 && i.intervals[n-1].Interval == intv { return i.intervals[n-1] } - // Add the current interval current := NewIntervalMetrics(intv) i.intervals = append(i.intervals, current) - n++ + if n > 0 { + close(i.intervals[n-1].done) + } - // Truncate the intervals if they are too long + n++ + // Prune old intervals if the count exceeds the max. if n >= i.maxIntervals { copy(i.intervals[0:], i.intervals[n-i.maxIntervals:]) i.intervals = i.intervals[:i.maxIntervals] @@ -302,15 +315,6 @@ func (i *InmemSink) createInterval(intv time.Time) *IntervalMetrics { return current } -// getInterval returns the current interval to write to -func (i *InmemSink) getInterval() *IntervalMetrics { - intv := time.Now().Truncate(i.interval) - if m := i.getExistingInterval(intv); m != nil { - return m - } - return i.createInterval(intv) -} - // Flattens the key for formatting, removes spaces func (i *InmemSink) flattenKey(parts []string) string { buf := &bytes.Buffer{} diff --git a/vendor/github.com/armon/go-metrics/inmem_endpoint.go b/vendor/github.com/armon/go-metrics/inmem_endpoint.go index 5fac958d9..24eefa963 100644 --- a/vendor/github.com/armon/go-metrics/inmem_endpoint.go +++ b/vendor/github.com/armon/go-metrics/inmem_endpoint.go @@ -1,6 +1,7 @@ package metrics import ( + "context" "fmt" "net/http" "sort" @@ -68,6 +69,10 @@ func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request) interval = data[n-2] } + return newMetricSummaryFromInterval(interval), nil +} + +func newMetricSummaryFromInterval(interval *IntervalMetrics) MetricsSummary { interval.RLock() defer interval.RUnlock() @@ -103,7 +108,7 @@ func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request) summary.Counters = formatSamples(interval.Counters) summary.Samples = formatSamples(interval.Samples) - return summary, nil + return summary } func formatSamples(source map[string]SampledValue) []SampledValue { @@ -129,3 +134,29 @@ func formatSamples(source map[string]SampledValue) []SampledValue { return output } + +type Encoder interface { + Encode(interface{}) error +} + +// Stream writes metrics using encoder.Encode each time an interval ends. Runs +// until the request context is cancelled, or the encoder returns an error. +// The caller is responsible for logging any errors from encoder. +func (i *InmemSink) Stream(ctx context.Context, encoder Encoder) { + interval := i.getInterval() + + for { + select { + case <-interval.done: + summary := newMetricSummaryFromInterval(interval) + if err := encoder.Encode(summary); err != nil { + return + } + + // update interval to the next one + interval = i.getInterval() + case <-ctx.Done(): + return + } + } +} diff --git a/vendor/github.com/armon/go-metrics/metrics.go b/vendor/github.com/armon/go-metrics/metrics.go index 457b74bb5..6753b13bb 100644 --- a/vendor/github.com/armon/go-metrics/metrics.go +++ b/vendor/github.com/armon/go-metrics/metrics.go @@ -228,12 +228,12 @@ func (m *Metrics) allowMetric(key []string, labels []Label) (bool, []Label) { func (m *Metrics) collectStats() { for { time.Sleep(m.ProfileInterval) - m.emitRuntimeStats() + m.EmitRuntimeStats() } } // Emits various runtime statsitics -func (m *Metrics) emitRuntimeStats() { +func (m *Metrics) EmitRuntimeStats() { // Export number of Goroutines numRoutines := runtime.NumGoroutine() m.SetGauge([]string{"runtime", "num_goroutines"}, float32(numRoutines)) diff --git a/vendor/github.com/armon/go-metrics/start.go b/vendor/github.com/armon/go-metrics/start.go index 32a28c483..6aa0bd389 100644 --- a/vendor/github.com/armon/go-metrics/start.go +++ b/vendor/github.com/armon/go-metrics/start.go @@ -6,7 +6,7 @@ import ( "sync/atomic" "time" - "github.com/hashicorp/go-immutable-radix" + iradix "github.com/hashicorp/go-immutable-radix" ) // Config is used to configure metrics settings @@ -48,6 +48,11 @@ func init() { globalMetrics.Store(&Metrics{sink: &BlackholeSink{}}) } +// Default returns the shared global metrics instance. +func Default() *Metrics { + return globalMetrics.Load().(*Metrics) +} + // DefaultConfig provides a sane default configuration func DefaultConfig(serviceName string) *Config { c := &Config{ diff --git a/vendor/github.com/cespare/xxhash/v2/.travis.yml b/vendor/github.com/cespare/xxhash/v2/.travis.yml deleted file mode 100644 index c516ea88d..000000000 --- a/vendor/github.com/cespare/xxhash/v2/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: go -go: - - "1.x" - - master -env: - - TAGS="" - - TAGS="-tags purego" -script: go test $TAGS -v ./... diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md index 2fd8693c2..792b4a60b 100644 --- a/vendor/github.com/cespare/xxhash/v2/README.md +++ b/vendor/github.com/cespare/xxhash/v2/README.md @@ -1,7 +1,7 @@ # xxhash -[![GoDoc](https://godoc.org/github.com/cespare/xxhash?status.svg)](https://godoc.org/github.com/cespare/xxhash) -[![Build Status](https://travis-ci.org/cespare/xxhash.svg?branch=master)](https://travis-ci.org/cespare/xxhash) +[![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) +[![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) xxhash is a Go implementation of the 64-bit [xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a @@ -64,4 +64,6 @@ $ go test -benchtime 10s -bench '/xxhash,direct,bytes' - [InfluxDB](https://github.com/influxdata/influxdb) - [Prometheus](https://github.com/prometheus/prometheus) +- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) - [FreeCache](https://github.com/coocood/freecache) +- [FastCache](https://github.com/VictoriaMetrics/fastcache) diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go index db0b35fbe..15c835d54 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go @@ -193,7 +193,6 @@ func (d *Digest) UnmarshalBinary(b []byte) error { b, d.v4 = consumeUint64(b) b, d.total = consumeUint64(b) copy(d.mem[:], b) - b = b[len(d.mem):] d.n = int(d.total % uint64(len(d.mem))) return nil } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s index d580e32ae..be8db5bf7 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s @@ -6,7 +6,7 @@ // Register allocation: // AX h -// CX pointer to advance through b +// SI pointer to advance through b // DX n // BX loop end // R8 v1, k1 @@ -16,39 +16,39 @@ // R12 tmp // R13 prime1v // R14 prime2v -// R15 prime4v +// DI prime4v -// round reads from and advances the buffer pointer in CX. +// round reads from and advances the buffer pointer in SI. // It assumes that R13 has prime1v and R14 has prime2v. #define round(r) \ - MOVQ (CX), R12 \ - ADDQ $8, CX \ + MOVQ (SI), R12 \ + ADDQ $8, SI \ IMULQ R14, R12 \ ADDQ R12, r \ ROLQ $31, r \ IMULQ R13, r // mergeRound applies a merge round on the two registers acc and val. -// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v. +// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v. #define mergeRound(acc, val) \ IMULQ R14, val \ ROLQ $31, val \ IMULQ R13, val \ XORQ val, acc \ IMULQ R13, acc \ - ADDQ R15, acc + ADDQ DI, acc // func Sum64(b []byte) uint64 TEXT ·Sum64(SB), NOSPLIT, $0-32 // Load fixed primes. MOVQ ·prime1v(SB), R13 MOVQ ·prime2v(SB), R14 - MOVQ ·prime4v(SB), R15 + MOVQ ·prime4v(SB), DI // Load slice. - MOVQ b_base+0(FP), CX + MOVQ b_base+0(FP), SI MOVQ b_len+8(FP), DX - LEAQ (CX)(DX*1), BX + LEAQ (SI)(DX*1), BX // The first loop limit will be len(b)-32. SUBQ $32, BX @@ -65,14 +65,14 @@ TEXT ·Sum64(SB), NOSPLIT, $0-32 XORQ R11, R11 SUBQ R13, R11 - // Loop until CX > BX. + // Loop until SI > BX. blockLoop: round(R8) round(R9) round(R10) round(R11) - CMPQ CX, BX + CMPQ SI, BX JLE blockLoop MOVQ R8, AX @@ -100,16 +100,16 @@ noBlocks: afterBlocks: ADDQ DX, AX - // Right now BX has len(b)-32, and we want to loop until CX > len(b)-8. + // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8. ADDQ $24, BX - CMPQ CX, BX + CMPQ SI, BX JG fourByte wordLoop: // Calculate k1. - MOVQ (CX), R8 - ADDQ $8, CX + MOVQ (SI), R8 + ADDQ $8, SI IMULQ R14, R8 ROLQ $31, R8 IMULQ R13, R8 @@ -117,18 +117,18 @@ wordLoop: XORQ R8, AX ROLQ $27, AX IMULQ R13, AX - ADDQ R15, AX + ADDQ DI, AX - CMPQ CX, BX + CMPQ SI, BX JLE wordLoop fourByte: ADDQ $4, BX - CMPQ CX, BX + CMPQ SI, BX JG singles - MOVL (CX), R8 - ADDQ $4, CX + MOVL (SI), R8 + ADDQ $4, SI IMULQ R13, R8 XORQ R8, AX @@ -138,19 +138,19 @@ fourByte: singles: ADDQ $4, BX - CMPQ CX, BX + CMPQ SI, BX JGE finalize singlesLoop: - MOVBQZX (CX), R12 - ADDQ $1, CX + MOVBQZX (SI), R12 + ADDQ $1, SI IMULQ ·prime5v(SB), R12 XORQ R12, AX ROLQ $11, AX IMULQ R13, AX - CMPQ CX, BX + CMPQ SI, BX JL singlesLoop finalize: @@ -179,9 +179,9 @@ TEXT ·writeBlocks(SB), NOSPLIT, $0-40 MOVQ ·prime2v(SB), R14 // Load slice. - MOVQ b_base+8(FP), CX + MOVQ b_base+8(FP), SI MOVQ b_len+16(FP), DX - LEAQ (CX)(DX*1), BX + LEAQ (SI)(DX*1), BX SUBQ $32, BX // Load vN from d. @@ -199,7 +199,7 @@ blockLoop: round(R10) round(R11) - CMPQ CX, BX + CMPQ SI, BX JLE blockLoop // Copy vN back to d. @@ -208,8 +208,8 @@ blockLoop: MOVQ R10, 16(AX) MOVQ R11, 24(AX) - // The number of bytes written is CX minus the old base pointer. - SUBQ b_base+8(FP), CX - MOVQ CX, ret+32(FP) + // The number of bytes written is SI minus the old base pointer. + SUBQ b_base+8(FP), SI + MOVQ SI, ret+32(FP) RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go index 53bf76efb..376e0ca2e 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go @@ -6,41 +6,52 @@ package xxhash import ( - "reflect" "unsafe" ) -// Notes: +// In the future it's possible that compiler optimizations will make these +// XxxString functions unnecessary by realizing that calls such as +// Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205. +// If that happens, even if we keep these functions they can be replaced with +// the trivial safe code. + +// NOTE: The usual way of doing an unsafe string-to-[]byte conversion is: // -// See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ -// for some discussion about these unsafe conversions. +// var b []byte +// bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) +// bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data +// bh.Len = len(s) +// bh.Cap = len(s) // -// In the future it's possible that compiler optimizations will make these -// unsafe operations unnecessary: https://golang.org/issue/2205. +// Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough +// weight to this sequence of expressions that any function that uses it will +// not be inlined. Instead, the functions below use a different unsafe +// conversion designed to minimize the inliner weight and allow both to be +// inlined. There is also a test (TestInlining) which verifies that these are +// inlined. // -// Both of these wrapper functions still incur function call overhead since they -// will not be inlined. We could write Go/asm copies of Sum64 and Digest.Write -// for strings to squeeze out a bit more speed. Mid-stack inlining should -// eventually fix this. +// See https://github.com/golang/go/issues/42739 for discussion. // Sum64String computes the 64-bit xxHash digest of s. // It may be faster than Sum64([]byte(s)) by avoiding a copy. func Sum64String(s string) uint64 { - var b []byte - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data - bh.Len = len(s) - bh.Cap = len(s) + b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})) return Sum64(b) } // WriteString adds more data to d. It always returns len(s), nil. // It may be faster than Write([]byte(s)) by avoiding a copy. func (d *Digest) WriteString(s string) (n int, err error) { - var b []byte - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data - bh.Len = len(s) - bh.Cap = len(s) - return d.Write(b) + d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))) + // d.Write always returns len(s), nil. + // Ignoring the return output and returning these fixed values buys a + // savings of 6 in the inliner's cost model. + return len(s), nil +} + +// sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout +// of the first two words is the same as the layout of a string. +type sliceHeader struct { + s string + cap int } diff --git a/vendor/github.com/dgryski/go-farm/.gitignore b/vendor/github.com/dgryski/go-farm/.gitignore new file mode 100644 index 000000000..36029ab5e --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +*.exe +*.test +*.prof + +target diff --git a/vendor/github.com/dgryski/go-farm/.travis.yml b/vendor/github.com/dgryski/go-farm/.travis.yml new file mode 100644 index 000000000..a6422d3ff --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/.travis.yml @@ -0,0 +1,39 @@ +language: go + +sudo: false + +branches: + except: + - release + +branches: + only: + - master + - develop + - travis + +go: + - 1.12.x + - 1.13.x + - tip + +matrix: + allow_failures: + - go: tip + +before_install: + - if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi; + - if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi; + - go get github.com/mattn/goveralls + +before_script: + - make deps + +script: + - make qa + +after_failure: + - cat ./target/test/report.xml + +after_success: + - if [ "$TRAVIS_GO_VERSION" = "1.9" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi; diff --git a/vendor/github.com/dgryski/go-farm/LICENSE b/vendor/github.com/dgryski/go-farm/LICENSE new file mode 100644 index 000000000..0f1884857 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2014-2017 Damian Gryski +Copyright (c) 2016-2017 Nicola Asuni - Tecnick.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/github.com/dgryski/go-farm/Makefile b/vendor/github.com/dgryski/go-farm/Makefile new file mode 100644 index 000000000..7592736ef --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/Makefile @@ -0,0 +1,187 @@ +# MAKEFILE +# +# @author Nicola Asuni +# @link https://github.com/dgryski/go-farm +# +# This file is intended to be executed in a Linux-compatible system. +# It also assumes that the project has been cloned in the right path under GOPATH: +# $GOPATH/src/github.com/dgryski/go-farm +# +# ------------------------------------------------------------------------------ + +# List special make targets that are not associated with files +.PHONY: help all test format fmtcheck vet lint coverage cyclo misspell errcheck staticcheck astscan qa deps clean nuke + +# Use bash as shell (Note: Ubuntu now uses dash which doesn't support PIPESTATUS). +SHELL=/bin/bash + +# CVS path (path to the parent dir containing the project) +CVSPATH=github.com/dgryski + +# Project owner +OWNER=dgryski + +# Project vendor +VENDOR=dgryski + +# Project name +PROJECT=go-farm + +# Project version +VERSION=$(shell cat VERSION) + +# Name of RPM or DEB package +PKGNAME=${VENDOR}-${PROJECT} + +# Current directory +CURRENTDIR=$(shell pwd) + +# GO lang path +ifneq ($(GOPATH),) + ifeq ($(findstring $(GOPATH),$(CURRENTDIR)),) + # the defined GOPATH is not valid + GOPATH= + endif +endif +ifeq ($(GOPATH),) + # extract the GOPATH + GOPATH=$(firstword $(subst /src/, ,$(CURRENTDIR))) +endif + +# --- MAKE TARGETS --- + +# Display general help about this command +help: + @echo "" + @echo "$(PROJECT) Makefile." + @echo "GOPATH=$(GOPATH)" + @echo "The following commands are available:" + @echo "" + @echo " make qa : Run all the tests" + @echo " make test : Run the unit tests" + @echo "" + @echo " make format : Format the source code" + @echo " make fmtcheck : Check if the source code has been formatted" + @echo " make vet : Check for suspicious constructs" + @echo " make lint : Check for style errors" + @echo " make coverage : Generate the coverage report" + @echo " make cyclo : Generate the cyclomatic complexity report" + @echo " make misspell : Detect commonly misspelled words in source files" + @echo " make staticcheck : Run staticcheck + @echo " make errcheck : Check that error return values are used" + @echo " make astscan : GO AST scanner" + @echo "" + @echo " make docs : Generate source code documentation" + @echo "" + @echo " make deps : Get the dependencies" + @echo " make clean : Remove any build artifact" + @echo " make nuke : Deletes any intermediate file" + @echo "" + + +# Alias for help target +all: help + +# Run the unit tests +test: + @mkdir -p target/test + @mkdir -p target/report + GOPATH=$(GOPATH) \ + go test \ + -covermode=atomic \ + -bench=. \ + -race \ + -cpuprofile=target/report/cpu.out \ + -memprofile=target/report/mem.out \ + -mutexprofile=target/report/mutex.out \ + -coverprofile=target/report/coverage.out \ + -v ./... | \ + tee >(PATH=$(GOPATH)/bin:$(PATH) go-junit-report > target/test/report.xml); \ + test $${PIPESTATUS[0]} -eq 0 + +# Format the source code +format: + @find . -type f -name "*.go" -exec gofmt -s -w {} \; + +# Check if the source code has been formatted +fmtcheck: + @mkdir -p target + @find . -type f -name "*.go" -exec gofmt -s -d {} \; | tee target/format.diff + @test ! -s target/format.diff || { echo "ERROR: the source code has not been formatted - please use 'make format' or 'gofmt'"; exit 1; } + +# Check for syntax errors +vet: + GOPATH=$(GOPATH) go vet . + +# Check for style errors +lint: + GOPATH=$(GOPATH) PATH=$(GOPATH)/bin:$(PATH) golint . + +# Generate the coverage report +coverage: + @mkdir -p target/report + GOPATH=$(GOPATH) \ + go tool cover -html=target/report/coverage.out -o target/report/coverage.html + +# Report cyclomatic complexity +cyclo: + @mkdir -p target/report + GOPATH=$(GOPATH) gocyclo -avg ./ | tee target/report/cyclo.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Detect commonly misspelled words in source files +misspell: + @mkdir -p target/report + GOPATH=$(GOPATH) misspell -error ./ | tee target/report/misspell.txt ; test $${PIPESTATUS[0]} -eq 0 + +# Check that error return values are used +errcheck: + @mkdir -p target/report + GOPATH=$(GOPATH) errcheck ./ | tee target/report/errcheck.txt + + +# staticcheck +staticcheck: + @mkdir -p target/report + GOPATH=$(GOPATH) staticcheck ./... | tee target/report/staticcheck.txt + + +# AST scanner +astscan: + @mkdir -p target/report + GOPATH=$(GOPATH) gas .//*.go | tee target/report/astscan.txt + +# Generate source docs +docs: + @mkdir -p target/docs + nohup sh -c 'GOPATH=$(GOPATH) godoc -http=127.0.0.1:6060' > target/godoc_server.log 2>&1 & + wget --directory-prefix=target/docs/ --execute robots=off --retry-connrefused --recursive --no-parent --adjust-extension --page-requisites --convert-links http://127.0.0.1:6060/pkg/github.com/${VENDOR}/${PROJECT}/ ; kill -9 `lsof -ti :6060` + @echo ''${PKGNAME}' Documentation ...' > target/docs/index.html + +# Alias to run all quality-assurance checks +qa: fmtcheck test vet lint coverage cyclo misspell errcheck astscan + +# --- INSTALL --- + +# Get the dependencies +deps: + GOPATH=$(GOPATH) go get ./... + GOPATH=$(GOPATH) go get golang.org/x/lint/golint + GOPATH=$(GOPATH) go get github.com/jstemmer/go-junit-report + GOPATH=$(GOPATH) go get github.com/axw/gocov/gocov + GOPATH=$(GOPATH) go get github.com/fzipp/gocyclo + GOPATH=$(GOPATH) go get github.com/gordonklaus/ineffassign + GOPATH=$(GOPATH) go get github.com/client9/misspell/cmd/misspell + GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/structcheck + GOPATH=$(GOPATH) go get github.com/opennota/check/cmd/varcheck + GOPATH=$(GOPATH) go get github.com/kisielk/errcheck + GOPATH=$(GOPATH) go get honnef.co/go/tools/cmd/staticcheck + GOPATH=$(GOPATH) go get github.com/GoASTScanner/gas + +# Remove any build artifact +clean: + GOPATH=$(GOPATH) go clean ./... + +# Deletes any intermediate file +nuke: + rm -rf ./target + GOPATH=$(GOPATH) go clean -i ./... diff --git a/vendor/github.com/dgryski/go-farm/README.md b/vendor/github.com/dgryski/go-farm/README.md new file mode 100644 index 000000000..0784f90fc --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/README.md @@ -0,0 +1,46 @@ +# go-farm + +*Google's FarmHash hash functions implemented in Go* + +[![Master Branch](https://img.shields.io/badge/-master:-gray.svg)](https://github.com/dgryski/go-farm/tree/master) +[![Master Build Status](https://secure.travis-ci.org/dgryski/go-farm.png?branch=master)](https://travis-ci.org/dgryski/go-farm?branch=master) +[![Master Coverage Status](https://coveralls.io/repos/dgryski/go-farm/badge.svg?branch=master&service=github)](https://coveralls.io/github/dgryski/go-farm?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/dgryski/go-farm)](https://goreportcard.com/report/github.com/dgryski/go-farm) +[![GoDoc](https://godoc.org/github.com/dgryski/go-farm?status.svg)](http://godoc.org/github.com/dgryski/go-farm) + +## Description + +FarmHash, a family of hash functions. + +This is a (mechanical) translation of the non-SSE4/non-AESNI hash functions from Google's FarmHash (https://github.com/google/farmhash). + + +FarmHash provides hash functions for strings and other data. +The functions mix the input bits thoroughly but are not suitable for cryptography. + +All members of the FarmHash family were designed with heavy reliance on previous work by Jyrki Alakuijala, Austin Appleby, Bob Jenkins, and others. + +For more information please consult https://github.com/google/farmhash + + +## Getting started + +This application is written in Go language, please refer to the guides in https://golang.org for getting started. + +This project include a Makefile that allows you to test and build the project with simple commands. +To see all available options: +```bash +make help +``` + +## Running all tests + +Before committing the code, please check if it passes all tests using +```bash +make qa +``` + +## License + +As this is a highly derivative work, I have placed it under the same license as the original implementation. See the +LICENSE file for details. diff --git a/vendor/github.com/dgryski/go-farm/VERSION b/vendor/github.com/dgryski/go-farm/VERSION new file mode 100644 index 000000000..38f77a65b --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/VERSION @@ -0,0 +1 @@ +2.0.1 diff --git a/vendor/github.com/dgryski/go-farm/basics.go b/vendor/github.com/dgryski/go-farm/basics.go new file mode 100644 index 000000000..ec7076c03 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/basics.go @@ -0,0 +1,32 @@ +package farm + +import "math/bits" + +// Some primes between 2^63 and 2^64 for various uses. +const k0 uint64 = 0xc3a5c85c97cb3127 +const k1 uint64 = 0xb492b66fbe98f273 +const k2 uint64 = 0x9ae16a3b2f90404f + +// Magic numbers for 32-bit hashing. Copied from Murmur3. +const c1 uint32 = 0xcc9e2d51 +const c2 uint32 = 0x1b873593 + +// A 32-bit to 32-bit integer hash copied from Murmur3. +func fmix(h uint32) uint32 { + h ^= h >> 16 + h *= 0x85ebca6b + h ^= h >> 13 + h *= 0xc2b2ae35 + h ^= h >> 16 + return h +} + +func mur(a, h uint32) uint32 { + // Helper from Murmur3 for combining two 32-bit values. + a *= c1 + a = bits.RotateLeft32(a, -17) + a *= c2 + h ^= a + h = bits.RotateLeft32(h, -19) + return h*5 + 0xe6546b64 +} diff --git a/vendor/github.com/dgryski/go-farm/farmhashcc.go b/vendor/github.com/dgryski/go-farm/farmhashcc.go new file mode 100644 index 000000000..3e68ae3a3 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/farmhashcc.go @@ -0,0 +1,194 @@ +package farm + +import ( + "encoding/binary" + "math/bits" +) + +// This file provides a 32-bit hash equivalent to CityHash32 (v1.1.1) +// and a 128-bit hash equivalent to CityHash128 (v1.1.1). It also provides +// a seeded 32-bit hash function similar to CityHash32. + +func hash32Len13to24Seed(s []byte, seed uint32) uint32 { + slen := len(s) + a := binary.LittleEndian.Uint32(s[-4+(slen>>1) : -4+(slen>>1)+4]) + b := binary.LittleEndian.Uint32(s[4 : 4+4]) + c := binary.LittleEndian.Uint32(s[slen-8 : slen-8+4]) + d := binary.LittleEndian.Uint32(s[(slen >> 1) : (slen>>1)+4]) + e := binary.LittleEndian.Uint32(s[0 : 0+4]) + f := binary.LittleEndian.Uint32(s[slen-4 : slen-4+4]) + h := d*c1 + uint32(slen) + seed + a = bits.RotateLeft32(a, -12) + f + h = mur(c, h) + a + a = bits.RotateLeft32(a, -3) + c + h = mur(e, h) + a + a = bits.RotateLeft32(a+f, -12) + d + h = mur(b^seed, h) + a + return fmix(h) +} + +func hash32Len0to4(s []byte, seed uint32) uint32 { + slen := len(s) + b := seed + c := uint32(9) + for i := 0; i < slen; i++ { + v := int8(s[i]) + b = (b * c1) + uint32(v) + c ^= b + } + return fmix(mur(b, mur(uint32(slen), c))) +} + +func hash128to64(x uint128) uint64 { + // Murmur-inspired hashing. + const mul uint64 = 0x9ddfea08eb382d69 + a := (x.lo ^ x.hi) * mul + a ^= (a >> 47) + b := (x.hi ^ a) * mul + b ^= (b >> 47) + b *= mul + return b +} + +type uint128 struct { + lo uint64 + hi uint64 +} + +// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings +// of any length representable in signed long. Based on City and Murmur. +func cityMurmur(s []byte, seed uint128) uint128 { + slen := len(s) + a := seed.lo + b := seed.hi + var c uint64 + var d uint64 + l := slen - 16 + if l <= 0 { // len <= 16 + a = shiftMix(a*k1) * k1 + c = b*k1 + hashLen0to16(s) + if slen >= 8 { + d = shiftMix(a + binary.LittleEndian.Uint64(s[0:0+8])) + } else { + d = shiftMix(a + c) + } + } else { // len > 16 + c = hashLen16(binary.LittleEndian.Uint64(s[slen-8:slen-8+8])+k1, a) + d = hashLen16(b+uint64(slen), c+binary.LittleEndian.Uint64(s[slen-16:slen-16+8])) + a += d + for { + a ^= shiftMix(binary.LittleEndian.Uint64(s[0:0+8])*k1) * k1 + a *= k1 + b ^= a + c ^= shiftMix(binary.LittleEndian.Uint64(s[8:8+8])*k1) * k1 + c *= k1 + d ^= c + s = s[16:] + l -= 16 + if l <= 0 { + break + } + } + } + a = hashLen16(a, c) + b = hashLen16(d, b) + return uint128{a ^ b, hashLen16(b, a)} +} + +func cityHash128WithSeed(s []byte, seed uint128) uint128 { + slen := len(s) + if slen < 128 { + return cityMurmur(s, seed) + } + + endIdx := ((slen - 1) / 128) * 128 + lastBlockIdx := endIdx + ((slen - 1) & 127) - 127 + last := s[lastBlockIdx:] + + // We expect len >= 128 to be the common case. Keep 56 bytes of state: + // v, w, x, y, and z. + var v1, v2 uint64 + var w1, w2 uint64 + x := seed.lo + y := seed.hi + z := uint64(slen) * k1 + v1 = bits.RotateLeft64(y^k1, -49)*k1 + binary.LittleEndian.Uint64(s[0:0+8]) + v2 = bits.RotateLeft64(v1, -42)*k1 + binary.LittleEndian.Uint64(s[8:8+8]) + w1 = bits.RotateLeft64(y+z, -35)*k1 + x + w2 = bits.RotateLeft64(x+binary.LittleEndian.Uint64(s[88:88+8]), -53) * k1 + + // This is the same inner loop as CityHash64(), manually unrolled. + for { + x = bits.RotateLeft64(x+y+v1+binary.LittleEndian.Uint64(s[8:8+8]), -37) * k1 + y = bits.RotateLeft64(y+v2+binary.LittleEndian.Uint64(s[48:48+8]), -42) * k1 + x ^= w2 + y += v1 + binary.LittleEndian.Uint64(s[40:40+8]) + z = bits.RotateLeft64(z+w1, -33) * k1 + v1, v2 = weakHashLen32WithSeeds(s, v2*k1, x+w1) + w1, w2 = weakHashLen32WithSeeds(s[32:], z+w2, y+binary.LittleEndian.Uint64(s[16:16+8])) + z, x = x, z + s = s[64:] + x = bits.RotateLeft64(x+y+v1+binary.LittleEndian.Uint64(s[8:8+8]), -37) * k1 + y = bits.RotateLeft64(y+v2+binary.LittleEndian.Uint64(s[48:48+8]), -42) * k1 + x ^= w2 + y += v1 + binary.LittleEndian.Uint64(s[40:40+8]) + z = bits.RotateLeft64(z+w1, -33) * k1 + v1, v2 = weakHashLen32WithSeeds(s, v2*k1, x+w1) + w1, w2 = weakHashLen32WithSeeds(s[32:], z+w2, y+binary.LittleEndian.Uint64(s[16:16+8])) + z, x = x, z + s = s[64:] + slen -= 128 + if slen < 128 { + break + } + } + x += bits.RotateLeft64(v1+z, -49) * k0 + y = y*k0 + bits.RotateLeft64(w2, -37) + z = z*k0 + bits.RotateLeft64(w1, -27) + w1 *= 9 + v1 *= k0 + // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s. + for tailDone := 0; tailDone < slen; { + tailDone += 32 + y = bits.RotateLeft64(x+y, -42)*k0 + v2 + w1 += binary.LittleEndian.Uint64(last[128-tailDone+16 : 128-tailDone+16+8]) + x = x*k0 + w1 + z += w2 + binary.LittleEndian.Uint64(last[128-tailDone:128-tailDone+8]) + w2 += v1 + v1, v2 = weakHashLen32WithSeeds(last[128-tailDone:], v1+z, v2) + v1 *= k0 + } + + // At this point our 56 bytes of state should contain more than + // enough information for a strong 128-bit hash. We use two + // different 56-byte-to-8-byte hashes to get a 16-byte final result. + x = hashLen16(x, v1) + y = hashLen16(y+z, w1) + return uint128{hashLen16(x+v2, w2) + y, + hashLen16(x+w2, y+v2)} +} + +func cityHash128(s []byte) uint128 { + slen := len(s) + if slen >= 16 { + return cityHash128WithSeed(s[16:], uint128{binary.LittleEndian.Uint64(s[0 : 0+8]), binary.LittleEndian.Uint64(s[8:8+8]) + k0}) + } + return cityHash128WithSeed(s, uint128{k0, k1}) +} + +// Fingerprint128 is a 128-bit fingerprint function for byte-slices +func Fingerprint128(s []byte) (lo, hi uint64) { + h := cityHash128(s) + return h.lo, h.hi +} + +// Hash128 is a 128-bit hash function for byte-slices +func Hash128(s []byte) (lo, hi uint64) { + return Fingerprint128(s) +} + +// Hash128WithSeed is a 128-bit hash function for byte-slices and a 128-bit seed +func Hash128WithSeed(s []byte, seed0, seed1 uint64) (lo, hi uint64) { + h := cityHash128WithSeed(s, uint128{seed0, seed1}) + return h.lo, h.hi +} diff --git a/vendor/github.com/dgryski/go-farm/farmhashmk.go b/vendor/github.com/dgryski/go-farm/farmhashmk.go new file mode 100644 index 000000000..8e4c7428b --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/farmhashmk.go @@ -0,0 +1,102 @@ +package farm + +import ( + "encoding/binary" + "math/bits" +) + +func hash32Len5to12(s []byte, seed uint32) uint32 { + slen := len(s) + a := uint32(len(s)) + b := uint32(len(s) * 5) + c := uint32(9) + d := b + seed + a += binary.LittleEndian.Uint32(s[0 : 0+4]) + b += binary.LittleEndian.Uint32(s[slen-4 : slen-4+4]) + c += binary.LittleEndian.Uint32(s[((slen >> 1) & 4) : ((slen>>1)&4)+4]) + return fmix(seed ^ mur(c, mur(b, mur(a, d)))) +} + +// Hash32 hashes a byte slice and returns a uint32 hash value +func Hash32(s []byte) uint32 { + + slen := len(s) + + if slen <= 24 { + if slen <= 12 { + if slen <= 4 { + return hash32Len0to4(s, 0) + } + return hash32Len5to12(s, 0) + } + return hash32Len13to24Seed(s, 0) + } + + // len > 24 + h := uint32(slen) + g := c1 * uint32(slen) + f := g + a0 := bits.RotateLeft32(binary.LittleEndian.Uint32(s[slen-4:slen-4+4])*c1, -17) * c2 + a1 := bits.RotateLeft32(binary.LittleEndian.Uint32(s[slen-8:slen-8+4])*c1, -17) * c2 + a2 := bits.RotateLeft32(binary.LittleEndian.Uint32(s[slen-16:slen-16+4])*c1, -17) * c2 + a3 := bits.RotateLeft32(binary.LittleEndian.Uint32(s[slen-12:slen-12+4])*c1, -17) * c2 + a4 := bits.RotateLeft32(binary.LittleEndian.Uint32(s[slen-20:slen-20+4])*c1, -17) * c2 + h ^= a0 + h = bits.RotateLeft32(h, -19) + h = h*5 + 0xe6546b64 + h ^= a2 + h = bits.RotateLeft32(h, -19) + h = h*5 + 0xe6546b64 + g ^= a1 + g = bits.RotateLeft32(g, -19) + g = g*5 + 0xe6546b64 + g ^= a3 + g = bits.RotateLeft32(g, -19) + g = g*5 + 0xe6546b64 + f += a4 + f = bits.RotateLeft32(f, -19) + 113 + for len(s) > 20 { + a := binary.LittleEndian.Uint32(s[0 : 0+4]) + b := binary.LittleEndian.Uint32(s[4 : 4+4]) + c := binary.LittleEndian.Uint32(s[8 : 8+4]) + d := binary.LittleEndian.Uint32(s[12 : 12+4]) + e := binary.LittleEndian.Uint32(s[16 : 16+4]) + h += a + g += b + f += c + h = mur(d, h) + e + g = mur(c, g) + a + f = mur(b+e*c1, f) + d + f += g + g += f + s = s[20:] + } + g = bits.RotateLeft32(g, -11) * c1 + g = bits.RotateLeft32(g, -17) * c1 + f = bits.RotateLeft32(f, -11) * c1 + f = bits.RotateLeft32(f, -17) * c1 + h = bits.RotateLeft32(h+g, -19) + h = h*5 + 0xe6546b64 + h = bits.RotateLeft32(h, -17) * c1 + h = bits.RotateLeft32(h+f, -19) + h = h*5 + 0xe6546b64 + h = bits.RotateLeft32(h, -17) * c1 + return h +} + +// Hash32WithSeed hashes a byte slice and a uint32 seed and returns a uint32 hash value +func Hash32WithSeed(s []byte, seed uint32) uint32 { + slen := len(s) + + if slen <= 24 { + if slen >= 13 { + return hash32Len13to24Seed(s, seed*c1) + } + if slen >= 5 { + return hash32Len5to12(s, seed) + } + return hash32Len0to4(s, seed) + } + h := hash32Len13to24Seed(s[:24], seed^uint32(slen)) + return mur(Hash32(s[24:])+seed, h) +} diff --git a/vendor/github.com/dgryski/go-farm/farmhashna.go b/vendor/github.com/dgryski/go-farm/farmhashna.go new file mode 100644 index 000000000..ac62edd3b --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/farmhashna.go @@ -0,0 +1,161 @@ +package farm + +import ( + "encoding/binary" + "math/bits" +) + +func shiftMix(val uint64) uint64 { + return val ^ (val >> 47) +} + +func hashLen16(u, v uint64) uint64 { + return hash128to64(uint128{u, v}) +} + +func hashLen16Mul(u, v, mul uint64) uint64 { + // Murmur-inspired hashing. + a := (u ^ v) * mul + a ^= (a >> 47) + b := (v ^ a) * mul + b ^= (b >> 47) + b *= mul + return b +} + +func hashLen0to16(s []byte) uint64 { + slen := uint64(len(s)) + if slen >= 8 { + mul := k2 + slen*2 + a := binary.LittleEndian.Uint64(s[0:0+8]) + k2 + b := binary.LittleEndian.Uint64(s[int(slen-8) : int(slen-8)+8]) + c := bits.RotateLeft64(b, -37)*mul + a + d := (bits.RotateLeft64(a, -25) + b) * mul + return hashLen16Mul(c, d, mul) + } + + if slen >= 4 { + mul := k2 + slen*2 + a := binary.LittleEndian.Uint32(s[0 : 0+4]) + return hashLen16Mul(slen+(uint64(a)<<3), uint64(binary.LittleEndian.Uint32(s[int(slen-4):int(slen-4)+4])), mul) + } + if slen > 0 { + a := s[0] + b := s[slen>>1] + c := s[slen-1] + y := uint32(a) + (uint32(b) << 8) + z := uint32(slen) + (uint32(c) << 2) + return shiftMix(uint64(y)*k2^uint64(z)*k0) * k2 + } + return k2 +} + +// This probably works well for 16-byte strings as well, but it may be overkill +// in that case. +func hashLen17to32(s []byte) uint64 { + slen := len(s) + mul := k2 + uint64(slen*2) + a := binary.LittleEndian.Uint64(s[0:0+8]) * k1 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + return hashLen16Mul(bits.RotateLeft64(a+b, -43)+bits.RotateLeft64(c, -30)+d, a+bits.RotateLeft64(b+k2, -18)+c, mul) +} + +// Return a 16-byte hash for 48 bytes. Quick and dirty. +// Callers do best to use "random-looking" values for a and b. +func weakHashLen32WithSeedsWords(w, x, y, z, a, b uint64) (uint64, uint64) { + a += w + b = bits.RotateLeft64(b+a+z, -21) + c := a + a += x + a += y + b += bits.RotateLeft64(a, -44) + return a + z, b + c +} + +// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. +func weakHashLen32WithSeeds(s []byte, a, b uint64) (uint64, uint64) { + return weakHashLen32WithSeedsWords(binary.LittleEndian.Uint64(s[0:0+8]), + binary.LittleEndian.Uint64(s[8:8+8]), + binary.LittleEndian.Uint64(s[16:16+8]), + binary.LittleEndian.Uint64(s[24:24+8]), + a, + b) +} + +// Return an 8-byte hash for 33 to 64 bytes. +func hashLen33to64(s []byte) uint64 { + slen := len(s) + mul := k2 + uint64(slen)*2 + a := binary.LittleEndian.Uint64(s[0:0+8]) * k2 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + y := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + z := hashLen16Mul(y, a+bits.RotateLeft64(b+k2, -18)+c, mul) + e := binary.LittleEndian.Uint64(s[16:16+8]) * mul + f := binary.LittleEndian.Uint64(s[24 : 24+8]) + g := (y + binary.LittleEndian.Uint64(s[slen-32:slen-32+8])) * mul + h := (z + binary.LittleEndian.Uint64(s[slen-24:slen-24+8])) * mul + return hashLen16Mul(bits.RotateLeft64(e+f, -43)+bits.RotateLeft64(g, -30)+h, e+bits.RotateLeft64(f+a, -18)+g, mul) +} + +func naHash64(s []byte) uint64 { + slen := len(s) + var seed uint64 = 81 + if slen <= 32 { + if slen <= 16 { + return hashLen0to16(s) + } + return hashLen17to32(s) + } + if slen <= 64 { + return hashLen33to64(s) + } + // For strings over 64 bytes we loop. + // Internal state consists of 56 bytes: v, w, x, y, and z. + v := uint128{0, 0} + w := uint128{0, 0} + x := seed*k2 + binary.LittleEndian.Uint64(s[0:0+8]) + y := seed*k1 + 113 + z := shiftMix(y*k2+113) * k2 + // Set end so that after the loop we have 1 to 64 bytes left to process. + endIdx := ((slen - 1) / 64) * 64 + last64Idx := endIdx + ((slen - 1) & 63) - 63 + last64 := s[last64Idx:] + for len(s) > 64 { + x = bits.RotateLeft64(x+y+v.lo+binary.LittleEndian.Uint64(s[8:8+8]), -37) * k1 + y = bits.RotateLeft64(y+v.hi+binary.LittleEndian.Uint64(s[48:48+8]), -42) * k1 + x ^= w.hi + y += v.lo + binary.LittleEndian.Uint64(s[40:40+8]) + z = bits.RotateLeft64(z+w.lo, -33) * k1 + v.lo, v.hi = weakHashLen32WithSeeds(s, v.hi*k1, x+w.lo) + w.lo, w.hi = weakHashLen32WithSeeds(s[32:], z+w.hi, y+binary.LittleEndian.Uint64(s[16:16+8])) + x, z = z, x + s = s[64:] + } + mul := k1 + ((z & 0xff) << 1) + // Make s point to the last 64 bytes of input. + s = last64 + w.lo += (uint64(slen-1) & 63) + v.lo += w.lo + w.lo += v.lo + x = bits.RotateLeft64(x+y+v.lo+binary.LittleEndian.Uint64(s[8:8+8]), -37) * mul + y = bits.RotateLeft64(y+v.hi+binary.LittleEndian.Uint64(s[48:48+8]), -42) * mul + x ^= w.hi * 9 + y += v.lo*9 + binary.LittleEndian.Uint64(s[40:40+8]) + z = bits.RotateLeft64(z+w.lo, -33) * mul + v.lo, v.hi = weakHashLen32WithSeeds(s, v.hi*mul, x+w.lo) + w.lo, w.hi = weakHashLen32WithSeeds(s[32:], z+w.hi, y+binary.LittleEndian.Uint64(s[16:16+8])) + x, z = z, x + return hashLen16Mul(hashLen16Mul(v.lo, w.lo, mul)+shiftMix(y)*k0+z, hashLen16Mul(v.hi, w.hi, mul)+x, mul) +} + +func naHash64WithSeed(s []byte, seed uint64) uint64 { + return naHash64WithSeeds(s, k2, seed) +} + +func naHash64WithSeeds(s []byte, seed0, seed1 uint64) uint64 { + return hashLen16(naHash64(s)-seed0, seed1) +} diff --git a/vendor/github.com/dgryski/go-farm/farmhashuo.go b/vendor/github.com/dgryski/go-farm/farmhashuo.go new file mode 100644 index 000000000..7328fc705 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/farmhashuo.go @@ -0,0 +1,122 @@ +package farm + +import ( + "encoding/binary" + "math/bits" +) + +func uoH(x, y, mul uint64, r uint) uint64 { + a := (x ^ y) * mul + a ^= (a >> 47) + b := (y ^ a) * mul + return bits.RotateLeft64(b, -int(r)) * mul +} + +// Hash64WithSeeds hashes a byte slice and two uint64 seeds and returns a uint64 hash value +func Hash64WithSeeds(s []byte, seed0, seed1 uint64) uint64 { + slen := len(s) + if slen <= 64 { + return naHash64WithSeeds(s, seed0, seed1) + } + + // For strings over 64 bytes we loop. + // Internal state consists of 64 bytes: u, v, w, x, y, and z. + x := seed0 + y := seed1*k2 + 113 + z := shiftMix(y*k2) * k2 + v := uint128{seed0, seed1} + var w uint128 + u := x - z + x *= k2 + mul := k2 + (u & 0x82) + + // Set end so that after the loop we have 1 to 64 bytes left to process. + endIdx := ((slen - 1) / 64) * 64 + last64Idx := endIdx + ((slen - 1) & 63) - 63 + last64 := s[last64Idx:] + + for len(s) > 64 { + a0 := binary.LittleEndian.Uint64(s[0 : 0+8]) + a1 := binary.LittleEndian.Uint64(s[8 : 8+8]) + a2 := binary.LittleEndian.Uint64(s[16 : 16+8]) + a3 := binary.LittleEndian.Uint64(s[24 : 24+8]) + a4 := binary.LittleEndian.Uint64(s[32 : 32+8]) + a5 := binary.LittleEndian.Uint64(s[40 : 40+8]) + a6 := binary.LittleEndian.Uint64(s[48 : 48+8]) + a7 := binary.LittleEndian.Uint64(s[56 : 56+8]) + x += a0 + a1 + y += a2 + z += a3 + v.lo += a4 + v.hi += a5 + a1 + w.lo += a6 + w.hi += a7 + + x = bits.RotateLeft64(x, -26) + x *= 9 + y = bits.RotateLeft64(y, -29) + z *= mul + v.lo = bits.RotateLeft64(v.lo, -33) + v.hi = bits.RotateLeft64(v.hi, -30) + w.lo ^= x + w.lo *= 9 + z = bits.RotateLeft64(z, -32) + z += w.hi + w.hi += z + z *= 9 + u, y = y, u + + z += a0 + a6 + v.lo += a2 + v.hi += a3 + w.lo += a4 + w.hi += a5 + a6 + x += a1 + y += a7 + + y += v.lo + v.lo += x - y + v.hi += w.lo + w.lo += v.hi + w.hi += x - y + x += w.hi + w.hi = bits.RotateLeft64(w.hi, -34) + u, z = z, u + s = s[64:] + } + // Make s point to the last 64 bytes of input. + s = last64 + u *= 9 + v.hi = bits.RotateLeft64(v.hi, -28) + v.lo = bits.RotateLeft64(v.lo, -20) + w.lo += (uint64(slen-1) & 63) + u += y + y += u + x = bits.RotateLeft64(y-x+v.lo+binary.LittleEndian.Uint64(s[8:8+8]), -37) * mul + y = bits.RotateLeft64(y^v.hi^binary.LittleEndian.Uint64(s[48:48+8]), -42) * mul + x ^= w.hi * 9 + y += v.lo + binary.LittleEndian.Uint64(s[40:40+8]) + z = bits.RotateLeft64(z+w.lo, -33) * mul + v.lo, v.hi = weakHashLen32WithSeeds(s, v.hi*mul, x+w.lo) + w.lo, w.hi = weakHashLen32WithSeeds(s[32:], z+w.hi, y+binary.LittleEndian.Uint64(s[16:16+8])) + return uoH(hashLen16Mul(v.lo+x, w.lo^y, mul)+z-u, + uoH(v.hi+y, w.hi+z, k2, 30)^x, + k2, + 31) +} + +// Hash64WithSeed hashes a byte slice and a uint64 seed and returns a uint64 hash value +func Hash64WithSeed(s []byte, seed uint64) uint64 { + if len(s) <= 64 { + return naHash64WithSeed(s, seed) + } + return Hash64WithSeeds(s, 0, seed) +} + +// Hash64 hashes a byte slice and returns a uint64 hash value +func uoHash64(s []byte) uint64 { + if len(s) <= 64 { + return naHash64(s) + } + return Hash64WithSeeds(s, 81, 0) +} diff --git a/vendor/github.com/dgryski/go-farm/farmhashxo.go b/vendor/github.com/dgryski/go-farm/farmhashxo.go new file mode 100644 index 000000000..9234212ab --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/farmhashxo.go @@ -0,0 +1,104 @@ +package farm + +import ( + "encoding/binary" + "math/bits" +) + +func h32(s []byte, mul uint64) uint64 { + slen := len(s) + a := binary.LittleEndian.Uint64(s[0:0+8]) * k1 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + v := a + bits.RotateLeft64(b+k2, -18) + c + a = shiftMix((u ^ v) * mul) + b = shiftMix((v ^ a) * mul) + return b +} + +func h32Seeds(s []byte, mul, seed0, seed1 uint64) uint64 { + slen := len(s) + a := binary.LittleEndian.Uint64(s[0:0+8]) * k1 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + seed0 + v := a + bits.RotateLeft64(b+k2, -18) + c + seed1 + a = shiftMix((u ^ v) * mul) + b = shiftMix((v ^ a) * mul) + return b +} + +func xohashLen33to64(s []byte) uint64 { + slen := len(s) + mul0 := k2 - 30 + mul1 := k2 - 30 + 2*uint64(slen) + + var h0 uint64 + { + s := s[0:32] + mul := mul0 + slen := len(s) + a := binary.LittleEndian.Uint64(s[0:0+8]) * k1 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + v := a + bits.RotateLeft64(b+k2, -18) + c + a = shiftMix((u ^ v) * mul) + b = shiftMix((v ^ a) * mul) + h0 = b + } + + var h1 uint64 + { + s := s[slen-32:] + mul := mul1 + slen := len(s) + a := binary.LittleEndian.Uint64(s[0:0+8]) * k1 + b := binary.LittleEndian.Uint64(s[8 : 8+8]) + c := binary.LittleEndian.Uint64(s[slen-8:slen-8+8]) * mul + d := binary.LittleEndian.Uint64(s[slen-16:slen-16+8]) * k2 + u := bits.RotateLeft64(a+b, -43) + bits.RotateLeft64(c, -30) + d + v := a + bits.RotateLeft64(b+k2, -18) + c + a = shiftMix((u ^ v) * mul) + b = shiftMix((v ^ a) * mul) + h1 = b + } + + r := ((h1 * mul1) + h0) * mul1 + return r +} + +func xohashLen65to96(s []byte) uint64 { + slen := len(s) + + mul0 := k2 - 114 + mul1 := k2 - 114 + 2*uint64(slen) + h0 := h32(s[:32], mul0) + h1 := h32(s[32:64], mul1) + h2 := h32Seeds(s[slen-32:], mul1, h0, h1) + return (h2*9 + (h0 >> 17) + (h1 >> 21)) * mul1 +} + +func Hash64(s []byte) uint64 { + slen := len(s) + + if slen <= 32 { + if slen <= 16 { + return hashLen0to16(s) + } else { + return hashLen17to32(s) + } + } else if slen <= 64 { + return xohashLen33to64(s) + } else if slen <= 96 { + return xohashLen65to96(s) + } else if slen <= 256 { + return naHash64(s) + } else { + return uoHash64(s) + } +} diff --git a/vendor/github.com/dgryski/go-farm/fp_amd64.s b/vendor/github.com/dgryski/go-farm/fp_amd64.s new file mode 100644 index 000000000..2b8fa3247 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/fp_amd64.s @@ -0,0 +1,951 @@ +// Code generated by command: go run asm.go -out=fp_amd64.s -go111=false. DO NOT EDIT. + +// +build amd64,!purego + +#include "textflag.h" + +// func Fingerprint64(s []byte) uint64 +TEXT ·Fingerprint64(SB), NOSPLIT, $0-32 + MOVQ s_base+0(FP), CX + MOVQ s_len+8(FP), AX + CMPQ AX, $0x10 + JG check32 + CMPQ AX, $0x08 + JL check4 + MOVQ (CX), DX + MOVQ AX, BX + SUBQ $0x08, BX + ADDQ CX, BX + MOVQ (BX), BX + MOVQ $0x9ae16a3b2f90404f, BP + ADDQ BP, DX + SHLQ $0x01, AX + ADDQ BP, AX + MOVQ BX, BP + RORQ $0x25, BP + IMULQ AX, BP + ADDQ DX, BP + RORQ $0x19, DX + ADDQ BX, DX + IMULQ AX, DX + XORQ DX, BP + IMULQ AX, BP + MOVQ BP, BX + SHRQ $0x2f, BX + XORQ BP, BX + XORQ BX, DX + IMULQ AX, DX + MOVQ DX, BX + SHRQ $0x2f, BX + XORQ DX, BX + IMULQ AX, BX + MOVQ BX, ret+24(FP) + RET + +check4: + CMPQ AX, $0x04 + JL check0 + MOVQ $0x9ae16a3b2f90404f, DX + MOVQ AX, BX + SHLQ $0x01, BX + ADDQ DX, BX + MOVL (CX), SI + SHLQ $0x03, SI + ADDQ AX, SI + SUBQ $0x04, AX + ADDQ AX, CX + MOVL (CX), DI + XORQ DI, SI + IMULQ BX, SI + MOVQ SI, DX + SHRQ $0x2f, DX + XORQ SI, DX + XORQ DX, DI + IMULQ BX, DI + MOVQ DI, DX + SHRQ $0x2f, DX + XORQ DI, DX + IMULQ BX, DX + MOVQ DX, ret+24(FP) + RET + +check0: + TESTQ AX, AX + JZ empty + MOVBQZX (CX), DX + MOVQ AX, BX + SHRQ $0x01, BX + ADDQ CX, BX + MOVBQZX (BX), BP + MOVQ AX, BX + SUBQ $0x01, BX + ADDQ CX, BX + MOVBQZX (BX), BX + SHLQ $0x08, BP + ADDQ BP, DX + SHLQ $0x02, BX + ADDQ BX, AX + MOVQ $0xc3a5c85c97cb3127, BX + IMULQ BX, AX + MOVQ $0x9ae16a3b2f90404f, BX + IMULQ BX, DX + XORQ DX, AX + MOVQ AX, DX + SHRQ $0x2f, DX + XORQ AX, DX + IMULQ BX, DX + MOVQ DX, ret+24(FP) + RET + +empty: + MOVQ $0x9ae16a3b2f90404f, DX + MOVQ DX, ret+24(FP) + RET + +check32: + CMPQ AX, $0x20 + JG check64 + MOVQ AX, DX + SHLQ $0x01, DX + MOVQ $0x9ae16a3b2f90404f, BX + ADDQ BX, DX + MOVQ (CX), BP + MOVQ $0xb492b66fbe98f273, SI + IMULQ SI, BP + MOVQ 8(CX), SI + MOVQ AX, DI + SUBQ $0x10, DI + ADDQ CX, DI + MOVQ 8(DI), R12 + IMULQ DX, R12 + MOVQ (DI), DI + IMULQ BX, DI + MOVQ BP, R13 + ADDQ SI, R13 + RORQ $0x2b, R13 + ADDQ DI, R13 + MOVQ R12, DI + RORQ $0x1e, DI + ADDQ DI, R13 + ADDQ R12, BP + ADDQ BX, SI + RORQ $0x12, SI + ADDQ SI, BP + XORQ BP, R13 + IMULQ DX, R13 + MOVQ R13, BX + SHRQ $0x2f, BX + XORQ R13, BX + XORQ BX, BP + IMULQ DX, BP + MOVQ BP, BX + SHRQ $0x2f, BX + XORQ BP, BX + IMULQ DX, BX + MOVQ BX, ret+24(FP) + RET + +check64: + CMPQ AX, $0x40 + JG long + MOVQ AX, DX + SHLQ $0x01, DX + MOVQ $0x9ae16a3b2f90404f, BX + ADDQ BX, DX + MOVQ (CX), BP + IMULQ BX, BP + MOVQ 8(CX), SI + MOVQ AX, DI + SUBQ $0x10, DI + ADDQ CX, DI + MOVQ 8(DI), R12 + IMULQ DX, R12 + MOVQ (DI), DI + IMULQ BX, DI + MOVQ BP, R13 + ADDQ SI, R13 + RORQ $0x2b, R13 + ADDQ DI, R13 + MOVQ R12, DI + RORQ $0x1e, DI + ADDQ DI, R13 + ADDQ BP, R12 + ADDQ BX, SI + RORQ $0x12, SI + ADDQ SI, R12 + MOVQ R13, BX + XORQ R12, BX + IMULQ DX, BX + MOVQ BX, SI + SHRQ $0x2f, SI + XORQ BX, SI + XORQ SI, R12 + IMULQ DX, R12 + MOVQ R12, BX + SHRQ $0x2f, BX + XORQ R12, BX + IMULQ DX, BX + MOVQ 16(CX), SI + IMULQ DX, SI + MOVQ 24(CX), DI + MOVQ AX, R12 + SUBQ $0x20, R12 + ADDQ CX, R12 + MOVQ (R12), R14 + ADDQ R13, R14 + IMULQ DX, R14 + MOVQ 8(R12), R12 + ADDQ BX, R12 + IMULQ DX, R12 + MOVQ SI, BX + ADDQ DI, BX + RORQ $0x2b, BX + ADDQ R12, BX + MOVQ R14, R12 + RORQ $0x1e, R12 + ADDQ R12, BX + ADDQ R14, SI + ADDQ BP, DI + RORQ $0x12, DI + ADDQ DI, SI + XORQ SI, BX + IMULQ DX, BX + MOVQ BX, BP + SHRQ $0x2f, BP + XORQ BX, BP + XORQ BP, SI + IMULQ DX, SI + MOVQ SI, BX + SHRQ $0x2f, BX + XORQ SI, BX + IMULQ DX, BX + MOVQ BX, ret+24(FP) + RET + +long: + XORQ R8, R8 + XORQ R9, R9 + XORQ R10, R10 + XORQ R11, R11 + MOVQ $0x01529cba0ca458ff, DX + ADDQ (CX), DX + MOVQ $0x226bb95b4e64b6d4, BX + MOVQ $0x134a747f856d0526, BP + MOVQ AX, SI + SUBQ $0x01, SI + MOVQ $0xffffffffffffffc0, DI + ANDQ DI, SI + MOVQ AX, DI + SUBQ $0x01, DI + ANDQ $0x3f, DI + SUBQ $0x3f, DI + ADDQ SI, DI + MOVQ DI, SI + ADDQ CX, SI + MOVQ AX, DI + +loop: + MOVQ $0xb492b66fbe98f273, R12 + ADDQ BX, DX + ADDQ R8, DX + ADDQ 8(CX), DX + RORQ $0x25, DX + IMULQ R12, DX + ADDQ R9, BX + ADDQ 48(CX), BX + RORQ $0x2a, BX + IMULQ R12, BX + XORQ R11, DX + ADDQ R8, BX + ADDQ 40(CX), BX + ADDQ R10, BP + RORQ $0x21, BP + IMULQ R12, BP + IMULQ R12, R9 + MOVQ DX, R8 + ADDQ R10, R8 + ADDQ (CX), R9 + ADDQ R9, R8 + ADDQ 24(CX), R8 + RORQ $0x15, R8 + MOVQ R9, R10 + ADDQ 8(CX), R9 + ADDQ 16(CX), R9 + MOVQ R9, R13 + RORQ $0x2c, R13 + ADDQ R13, R8 + ADDQ 24(CX), R9 + ADDQ R10, R8 + XCHGQ R9, R8 + ADDQ BP, R11 + MOVQ BX, R10 + ADDQ 16(CX), R10 + ADDQ 32(CX), R11 + ADDQ R11, R10 + ADDQ 56(CX), R10 + RORQ $0x15, R10 + MOVQ R11, R13 + ADDQ 40(CX), R11 + ADDQ 48(CX), R11 + MOVQ R11, R14 + RORQ $0x2c, R14 + ADDQ R14, R10 + ADDQ 56(CX), R11 + ADDQ R13, R10 + XCHGQ R11, R10 + XCHGQ BP, DX + ADDQ $0x40, CX + SUBQ $0x40, DI + CMPQ DI, $0x40 + JG loop + MOVQ SI, CX + MOVQ BP, DI + ANDQ $0xff, DI + SHLQ $0x01, DI + ADDQ R12, DI + MOVQ SI, CX + SUBQ $0x01, AX + ANDQ $0x3f, AX + ADDQ AX, R10 + ADDQ R10, R8 + ADDQ R8, R10 + ADDQ BX, DX + ADDQ R8, DX + ADDQ 8(CX), DX + RORQ $0x25, DX + IMULQ DI, DX + ADDQ R9, BX + ADDQ 48(CX), BX + RORQ $0x2a, BX + IMULQ DI, BX + MOVQ $0x00000009, AX + IMULQ R11, AX + XORQ AX, DX + MOVQ $0x00000009, AX + IMULQ R8, AX + ADDQ AX, BX + ADDQ 40(CX), BX + ADDQ R10, BP + RORQ $0x21, BP + IMULQ DI, BP + IMULQ DI, R9 + MOVQ DX, R8 + ADDQ R10, R8 + ADDQ (CX), R9 + ADDQ R9, R8 + ADDQ 24(CX), R8 + RORQ $0x15, R8 + MOVQ R9, AX + ADDQ 8(CX), R9 + ADDQ 16(CX), R9 + MOVQ R9, SI + RORQ $0x2c, SI + ADDQ SI, R8 + ADDQ 24(CX), R9 + ADDQ AX, R8 + XCHGQ R9, R8 + ADDQ BP, R11 + MOVQ BX, R10 + ADDQ 16(CX), R10 + ADDQ 32(CX), R11 + ADDQ R11, R10 + ADDQ 56(CX), R10 + RORQ $0x15, R10 + MOVQ R11, AX + ADDQ 40(CX), R11 + ADDQ 48(CX), R11 + MOVQ R11, SI + RORQ $0x2c, SI + ADDQ SI, R10 + ADDQ 56(CX), R11 + ADDQ AX, R10 + XCHGQ R11, R10 + XCHGQ BP, DX + XORQ R10, R8 + IMULQ DI, R8 + MOVQ R8, AX + SHRQ $0x2f, AX + XORQ R8, AX + XORQ AX, R10 + IMULQ DI, R10 + MOVQ R10, AX + SHRQ $0x2f, AX + XORQ R10, AX + IMULQ DI, AX + ADDQ BP, AX + MOVQ BX, CX + SHRQ $0x2f, CX + XORQ BX, CX + MOVQ $0xc3a5c85c97cb3127, BX + IMULQ BX, CX + ADDQ CX, AX + XORQ R11, R9 + IMULQ DI, R9 + MOVQ R9, CX + SHRQ $0x2f, CX + XORQ R9, CX + XORQ CX, R11 + IMULQ DI, R11 + MOVQ R11, CX + SHRQ $0x2f, CX + XORQ R11, CX + IMULQ DI, CX + ADDQ DX, CX + XORQ CX, AX + IMULQ DI, AX + MOVQ AX, DX + SHRQ $0x2f, DX + XORQ AX, DX + XORQ DX, CX + IMULQ DI, CX + MOVQ CX, AX + SHRQ $0x2f, AX + XORQ CX, AX + IMULQ DI, AX + MOVQ AX, ret+24(FP) + RET + +// func Fingerprint32(s []byte) uint32 +TEXT ·Fingerprint32(SB), NOSPLIT, $0-28 + MOVQ s_base+0(FP), AX + MOVQ s_len+8(FP), CX + CMPQ CX, $0x18 + JG long + CMPQ CX, $0x0c + JG hash_13_24 + CMPQ CX, $0x04 + JG hash_5_12 + XORL DX, DX + MOVL $0x00000009, BX + TESTQ CX, CX + JZ done + MOVQ CX, BP + MOVL $0xcc9e2d51, DI + IMULL DI, DX + MOVBLSX (AX), SI + ADDL SI, DX + XORL DX, BX + SUBQ $0x01, BP + TESTQ BP, BP + JZ done + IMULL DI, DX + MOVBLSX 1(AX), SI + ADDL SI, DX + XORL DX, BX + SUBQ $0x01, BP + TESTQ BP, BP + JZ done + IMULL DI, DX + MOVBLSX 2(AX), SI + ADDL SI, DX + XORL DX, BX + SUBQ $0x01, BP + TESTQ BP, BP + JZ done + IMULL DI, DX + MOVBLSX 3(AX), SI + ADDL SI, DX + XORL DX, BX + SUBQ $0x01, BP + TESTQ BP, BP + JZ done + +done: + MOVL CX, BP + MOVL $0xcc9e2d51, SI + IMULL SI, BP + RORL $0x11, BP + MOVL $0x1b873593, SI + IMULL SI, BP + XORL BP, BX + RORL $0x13, BX + LEAL (BX)(BX*4), BP + LEAL 3864292196(BP), BX + MOVL $0xcc9e2d51, BP + IMULL BP, DX + RORL $0x11, DX + MOVL $0x1b873593, BP + IMULL BP, DX + XORL DX, BX + RORL $0x13, BX + LEAL (BX)(BX*4), DX + LEAL 3864292196(DX), BX + MOVL BX, DX + SHRL $0x10, DX + XORL DX, BX + MOVL $0x85ebca6b, DX + IMULL DX, BX + MOVL BX, DX + SHRL $0x0d, DX + XORL DX, BX + MOVL $0xc2b2ae35, DX + IMULL DX, BX + MOVL BX, DX + SHRL $0x10, DX + XORL DX, BX + MOVL BX, ret+24(FP) + RET + +hash_5_12: + MOVL CX, DX + MOVL DX, BX + SHLL $0x02, BX + ADDL DX, BX + MOVL $0x00000009, BP + MOVL BX, SI + ADDL (AX), DX + MOVQ CX, DI + SUBQ $0x04, DI + ADDQ AX, DI + ADDL (DI), BX + MOVQ CX, DI + SHRQ $0x01, DI + ANDQ $0x04, DI + ADDQ AX, DI + ADDL (DI), BP + MOVL $0xcc9e2d51, DI + IMULL DI, DX + RORL $0x11, DX + MOVL $0x1b873593, DI + IMULL DI, DX + XORL DX, SI + RORL $0x13, SI + LEAL (SI)(SI*4), DX + LEAL 3864292196(DX), SI + MOVL $0xcc9e2d51, DX + IMULL DX, BX + RORL $0x11, BX + MOVL $0x1b873593, DX + IMULL DX, BX + XORL BX, SI + RORL $0x13, SI + LEAL (SI)(SI*4), BX + LEAL 3864292196(BX), SI + MOVL $0xcc9e2d51, DX + IMULL DX, BP + RORL $0x11, BP + MOVL $0x1b873593, DX + IMULL DX, BP + XORL BP, SI + RORL $0x13, SI + LEAL (SI)(SI*4), BP + LEAL 3864292196(BP), SI + MOVL SI, DX + SHRL $0x10, DX + XORL DX, SI + MOVL $0x85ebca6b, DX + IMULL DX, SI + MOVL SI, DX + SHRL $0x0d, DX + XORL DX, SI + MOVL $0xc2b2ae35, DX + IMULL DX, SI + MOVL SI, DX + SHRL $0x10, DX + XORL DX, SI + MOVL SI, ret+24(FP) + RET + +hash_13_24: + MOVQ CX, DX + SHRQ $0x01, DX + ADDQ AX, DX + MOVL -4(DX), BX + MOVL 4(AX), BP + MOVQ CX, SI + ADDQ AX, SI + MOVL -8(SI), DI + MOVL (DX), DX + MOVL (AX), R8 + MOVL -4(SI), SI + MOVL $0xcc9e2d51, R9 + IMULL DX, R9 + ADDL CX, R9 + RORL $0x0c, BX + ADDL SI, BX + MOVL DI, R10 + MOVL $0xcc9e2d51, R11 + IMULL R11, R10 + RORL $0x11, R10 + MOVL $0x1b873593, R11 + IMULL R11, R10 + XORL R10, R9 + RORL $0x13, R9 + LEAL (R9)(R9*4), R10 + LEAL 3864292196(R10), R9 + ADDL BX, R9 + RORL $0x03, BX + ADDL DI, BX + MOVL $0xcc9e2d51, DI + IMULL DI, R8 + RORL $0x11, R8 + MOVL $0x1b873593, DI + IMULL DI, R8 + XORL R8, R9 + RORL $0x13, R9 + LEAL (R9)(R9*4), R8 + LEAL 3864292196(R8), R9 + ADDL BX, R9 + ADDL SI, BX + RORL $0x0c, BX + ADDL DX, BX + MOVL $0xcc9e2d51, DX + IMULL DX, BP + RORL $0x11, BP + MOVL $0x1b873593, DX + IMULL DX, BP + XORL BP, R9 + RORL $0x13, R9 + LEAL (R9)(R9*4), BP + LEAL 3864292196(BP), R9 + ADDL BX, R9 + MOVL R9, DX + SHRL $0x10, DX + XORL DX, R9 + MOVL $0x85ebca6b, DX + IMULL DX, R9 + MOVL R9, DX + SHRL $0x0d, DX + XORL DX, R9 + MOVL $0xc2b2ae35, DX + IMULL DX, R9 + MOVL R9, DX + SHRL $0x10, DX + XORL DX, R9 + MOVL R9, ret+24(FP) + RET + +long: + MOVL CX, DX + MOVL $0xcc9e2d51, BX + IMULL DX, BX + MOVL BX, BP + MOVQ CX, SI + ADDQ AX, SI + MOVL $0xcc9e2d51, DI + MOVL $0x1b873593, R8 + MOVL -4(SI), R9 + IMULL DI, R9 + RORL $0x11, R9 + IMULL R8, R9 + XORL R9, DX + RORL $0x13, DX + MOVL DX, R9 + SHLL $0x02, R9 + ADDL R9, DX + ADDL $0xe6546b64, DX + MOVL -8(SI), R9 + IMULL DI, R9 + RORL $0x11, R9 + IMULL R8, R9 + XORL R9, BX + RORL $0x13, BX + MOVL BX, R9 + SHLL $0x02, R9 + ADDL R9, BX + ADDL $0xe6546b64, BX + MOVL -16(SI), R9 + IMULL DI, R9 + RORL $0x11, R9 + IMULL R8, R9 + XORL R9, DX + RORL $0x13, DX + MOVL DX, R9 + SHLL $0x02, R9 + ADDL R9, DX + ADDL $0xe6546b64, DX + MOVL -12(SI), R9 + IMULL DI, R9 + RORL $0x11, R9 + IMULL R8, R9 + XORL R9, BX + RORL $0x13, BX + MOVL BX, R9 + SHLL $0x02, R9 + ADDL R9, BX + ADDL $0xe6546b64, BX + PREFETCHT0 (AX) + MOVL -20(SI), SI + IMULL DI, SI + RORL $0x11, SI + IMULL R8, SI + ADDL SI, BP + RORL $0x13, BP + ADDL $0x71, BP + +loop80: + CMPQ CX, $0x64 + JL loop20 + PREFETCHT0 20(AX) + MOVL (AX), SI + ADDL SI, DX + MOVL 4(AX), DI + ADDL DI, BX + MOVL 8(AX), R8 + ADDL R8, BP + MOVL 12(AX), R9 + MOVL R9, R11 + MOVL $0xcc9e2d51, R10 + IMULL R10, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R10 + IMULL R10, R11 + XORL R11, DX + RORL $0x13, DX + LEAL (DX)(DX*4), R11 + LEAL 3864292196(R11), DX + MOVL 16(AX), R10 + ADDL R10, DX + MOVL R8, R11 + MOVL $0xcc9e2d51, R8 + IMULL R8, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R8 + IMULL R8, R11 + XORL R11, BX + RORL $0x13, BX + LEAL (BX)(BX*4), R11 + LEAL 3864292196(R11), BX + ADDL SI, BX + MOVL $0xcc9e2d51, SI + IMULL SI, R10 + MOVL R10, R11 + ADDL DI, R11 + MOVL $0xcc9e2d51, SI + IMULL SI, R11 + RORL $0x11, R11 + MOVL $0x1b873593, SI + IMULL SI, R11 + XORL R11, BP + RORL $0x13, BP + LEAL (BP)(BP*4), R11 + LEAL 3864292196(R11), BP + ADDL R9, BP + ADDL BX, BP + ADDL BP, BX + PREFETCHT0 40(AX) + MOVL 20(AX), SI + ADDL SI, DX + MOVL 24(AX), DI + ADDL DI, BX + MOVL 28(AX), R8 + ADDL R8, BP + MOVL 32(AX), R9 + MOVL R9, R11 + MOVL $0xcc9e2d51, R10 + IMULL R10, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R10 + IMULL R10, R11 + XORL R11, DX + RORL $0x13, DX + LEAL (DX)(DX*4), R11 + LEAL 3864292196(R11), DX + MOVL 36(AX), R10 + ADDL R10, DX + MOVL R8, R11 + MOVL $0xcc9e2d51, R8 + IMULL R8, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R8 + IMULL R8, R11 + XORL R11, BX + RORL $0x13, BX + LEAL (BX)(BX*4), R11 + LEAL 3864292196(R11), BX + ADDL SI, BX + MOVL $0xcc9e2d51, SI + IMULL SI, R10 + MOVL R10, R11 + ADDL DI, R11 + MOVL $0xcc9e2d51, SI + IMULL SI, R11 + RORL $0x11, R11 + MOVL $0x1b873593, SI + IMULL SI, R11 + XORL R11, BP + RORL $0x13, BP + LEAL (BP)(BP*4), R11 + LEAL 3864292196(R11), BP + ADDL R9, BP + ADDL BX, BP + ADDL BP, BX + PREFETCHT0 60(AX) + MOVL 40(AX), SI + ADDL SI, DX + MOVL 44(AX), DI + ADDL DI, BX + MOVL 48(AX), R8 + ADDL R8, BP + MOVL 52(AX), R9 + MOVL R9, R11 + MOVL $0xcc9e2d51, R10 + IMULL R10, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R10 + IMULL R10, R11 + XORL R11, DX + RORL $0x13, DX + LEAL (DX)(DX*4), R11 + LEAL 3864292196(R11), DX + MOVL 56(AX), R10 + ADDL R10, DX + MOVL R8, R11 + MOVL $0xcc9e2d51, R8 + IMULL R8, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R8 + IMULL R8, R11 + XORL R11, BX + RORL $0x13, BX + LEAL (BX)(BX*4), R11 + LEAL 3864292196(R11), BX + ADDL SI, BX + MOVL $0xcc9e2d51, SI + IMULL SI, R10 + MOVL R10, R11 + ADDL DI, R11 + MOVL $0xcc9e2d51, SI + IMULL SI, R11 + RORL $0x11, R11 + MOVL $0x1b873593, SI + IMULL SI, R11 + XORL R11, BP + RORL $0x13, BP + LEAL (BP)(BP*4), R11 + LEAL 3864292196(R11), BP + ADDL R9, BP + ADDL BX, BP + ADDL BP, BX + PREFETCHT0 80(AX) + MOVL 60(AX), SI + ADDL SI, DX + MOVL 64(AX), DI + ADDL DI, BX + MOVL 68(AX), R8 + ADDL R8, BP + MOVL 72(AX), R9 + MOVL R9, R11 + MOVL $0xcc9e2d51, R10 + IMULL R10, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R10 + IMULL R10, R11 + XORL R11, DX + RORL $0x13, DX + LEAL (DX)(DX*4), R11 + LEAL 3864292196(R11), DX + MOVL 76(AX), R10 + ADDL R10, DX + MOVL R8, R11 + MOVL $0xcc9e2d51, R8 + IMULL R8, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R8 + IMULL R8, R11 + XORL R11, BX + RORL $0x13, BX + LEAL (BX)(BX*4), R11 + LEAL 3864292196(R11), BX + ADDL SI, BX + MOVL $0xcc9e2d51, SI + IMULL SI, R10 + MOVL R10, R11 + ADDL DI, R11 + MOVL $0xcc9e2d51, SI + IMULL SI, R11 + RORL $0x11, R11 + MOVL $0x1b873593, SI + IMULL SI, R11 + XORL R11, BP + RORL $0x13, BP + LEAL (BP)(BP*4), R11 + LEAL 3864292196(R11), BP + ADDL R9, BP + ADDL BX, BP + ADDL BP, BX + ADDQ $0x50, AX + SUBQ $0x50, CX + JMP loop80 + +loop20: + CMPQ CX, $0x14 + JLE after + MOVL (AX), SI + ADDL SI, DX + MOVL 4(AX), DI + ADDL DI, BX + MOVL 8(AX), R8 + ADDL R8, BP + MOVL 12(AX), R9 + MOVL R9, R11 + MOVL $0xcc9e2d51, R10 + IMULL R10, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R10 + IMULL R10, R11 + XORL R11, DX + RORL $0x13, DX + LEAL (DX)(DX*4), R11 + LEAL 3864292196(R11), DX + MOVL 16(AX), R10 + ADDL R10, DX + MOVL R8, R11 + MOVL $0xcc9e2d51, R8 + IMULL R8, R11 + RORL $0x11, R11 + MOVL $0x1b873593, R8 + IMULL R8, R11 + XORL R11, BX + RORL $0x13, BX + LEAL (BX)(BX*4), R11 + LEAL 3864292196(R11), BX + ADDL SI, BX + MOVL $0xcc9e2d51, SI + IMULL SI, R10 + MOVL R10, R11 + ADDL DI, R11 + MOVL $0xcc9e2d51, SI + IMULL SI, R11 + RORL $0x11, R11 + MOVL $0x1b873593, SI + IMULL SI, R11 + XORL R11, BP + RORL $0x13, BP + LEAL (BP)(BP*4), R11 + LEAL 3864292196(R11), BP + ADDL R9, BP + ADDL BX, BP + ADDL BP, BX + ADDQ $0x14, AX + SUBQ $0x14, CX + JMP loop20 + +after: + MOVL $0xcc9e2d51, AX + RORL $0x0b, BX + IMULL AX, BX + RORL $0x11, BX + IMULL AX, BX + RORL $0x0b, BP + IMULL AX, BP + RORL $0x11, BP + IMULL AX, BP + ADDL BX, DX + RORL $0x13, DX + MOVL DX, CX + SHLL $0x02, CX + ADDL CX, DX + ADDL $0xe6546b64, DX + RORL $0x11, DX + IMULL AX, DX + ADDL BP, DX + RORL $0x13, DX + MOVL DX, CX + SHLL $0x02, CX + ADDL CX, DX + ADDL $0xe6546b64, DX + RORL $0x11, DX + IMULL AX, DX + MOVL DX, ret+24(FP) + RET diff --git a/vendor/github.com/dgryski/go-farm/fp_generic.go b/vendor/github.com/dgryski/go-farm/fp_generic.go new file mode 100644 index 000000000..2cfa1b9dc --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/fp_generic.go @@ -0,0 +1,13 @@ +// +build !amd64 purego + +package farm + +// Fingerprint64 is a 64-bit fingerprint function for byte-slices +func Fingerprint64(s []byte) uint64 { + return naHash64(s) +} + +// Fingerprint32 is a 32-bit fingerprint function for byte-slices +func Fingerprint32(s []byte) uint32 { + return Hash32(s) +} diff --git a/vendor/github.com/dgryski/go-farm/fp_stub.go b/vendor/github.com/dgryski/go-farm/fp_stub.go new file mode 100644 index 000000000..94fff8de5 --- /dev/null +++ b/vendor/github.com/dgryski/go-farm/fp_stub.go @@ -0,0 +1,9 @@ +// Code generated by command: go run asm.go -out=fp_amd64.s -stubs=fp_stub.go. DO NOT EDIT. + +// +build amd64,!purego + +package farm + +func Fingerprint64(s []byte) uint64 + +func Fingerprint32(s []byte) uint32 diff --git a/vendor/github.com/eapache/channels/.gitignore b/vendor/github.com/eapache/channels/.gitignore new file mode 100644 index 000000000..00268614f --- /dev/null +++ b/vendor/github.com/eapache/channels/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/eapache/channels/.travis.yml b/vendor/github.com/eapache/channels/.travis.yml new file mode 100644 index 000000000..b072a4c85 --- /dev/null +++ b/vendor/github.com/eapache/channels/.travis.yml @@ -0,0 +1,11 @@ +language: go +sudo: false + +script: go test -v -race -timeout 10s ./... + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 diff --git a/vendor/github.com/eapache/channels/CHANGELOG.md b/vendor/github.com/eapache/channels/CHANGELOG.md new file mode 100644 index 000000000..63825cd2f --- /dev/null +++ b/vendor/github.com/eapache/channels/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +#### Version 1.1.0 (2015-11-22) + +Bug Fixes: + - The `Len()` and `Cap()` methods on several implementations were racy + ([#18](https://github.com/eapache/channels/issues/18)). + +Note: Fixing the above issue led to a fairly substantial performance hit +(anywhere from 10-25% in benchmarks depending on use case) and involved fairly +major refactoring, which is why this is being released as v1.1.0 instead +of v1.0.1. + +#### Version 1.0.0 (2015-01-24) + +Version 1.0.0 is the first tagged release. All core functionality was available +at this point. diff --git a/vendor/github.com/eapache/channels/LICENSE b/vendor/github.com/eapache/channels/LICENSE new file mode 100644 index 000000000..8c4bddf75 --- /dev/null +++ b/vendor/github.com/eapache/channels/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Evan Huus + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/eapache/channels/README.md b/vendor/github.com/eapache/channels/README.md new file mode 100644 index 000000000..aab2a53a3 --- /dev/null +++ b/vendor/github.com/eapache/channels/README.md @@ -0,0 +1,27 @@ +channels +======== + +[![Build Status](https://travis-ci.org/eapache/channels.svg?branch=master)](https://travis-ci.org/eapache/channels) +[![GoDoc](https://godoc.org/github.com/eapache/channels?status.png)](https://godoc.org/github.com/eapache/channels) +[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](https://eapache.github.io/conduct.html) + +A collection of helper functions and special types for working with and +extending [Go](https://golang.org/)'s existing channels. Due to limitations +of Go's type system, importing this library directly is often not practical for +production code. It serves equally well, however, as a reference guide and +template for implementing many common idioms; if you use it in this way I would +appreciate the inclusion of some sort of credit in the resulting code. + +See https://godoc.org/github.com/eapache/channels for full documentation or +https://gopkg.in/eapache/channels.v1 for a versioned import path. + +Requires Go version 1.1 or later, as certain necessary elements of the `reflect` +package were not present in 1.0. + +Most of the buffered channel types in this package are backed by a very fast +queue implementation that used to be built into this package but has now been +extracted into its own package at https://github.com/eapache/queue. + +*Note:* Several types in this package provide so-called "infinite" buffers. Be +very careful using these, as no buffer is truly infinite. If such a buffer +grows too large your program will run out of memory and crash. Caveat emptor. diff --git a/vendor/github.com/eapache/channels/batching_channel.go b/vendor/github.com/eapache/channels/batching_channel.go new file mode 100644 index 000000000..5be622f2f --- /dev/null +++ b/vendor/github.com/eapache/channels/batching_channel.go @@ -0,0 +1,87 @@ +package channels + +// BatchingChannel implements the Channel interface, with the change that instead of producing individual elements +// on Out(), it batches together the entire internal buffer each time. Trying to construct an unbuffered batching channel +// will panic, that configuration is not supported (and provides no benefit over an unbuffered NativeChannel). +type BatchingChannel struct { + input, output chan interface{} + length chan int + buffer []interface{} + size BufferCap +} + +func NewBatchingChannel(size BufferCap) *BatchingChannel { + if size == None { + panic("channels: BatchingChannel does not support unbuffered behaviour") + } + if size < 0 && size != Infinity { + panic("channels: invalid negative size in NewBatchingChannel") + } + ch := &BatchingChannel{ + input: make(chan interface{}), + output: make(chan interface{}), + length: make(chan int), + size: size, + } + go ch.batchingBuffer() + return ch +} + +func (ch *BatchingChannel) In() chan<- interface{} { + return ch.input +} + +// Out returns a <-chan interface{} in order that BatchingChannel conforms to the standard Channel interface provided +// by this package, however each output value is guaranteed to be of type []interface{} - a slice collecting the most +// recent batch of values sent on the In channel. The slice is guaranteed to not be empty or nil. In practice the net +// result is that you need an additional type assertion to access the underlying values. +func (ch *BatchingChannel) Out() <-chan interface{} { + return ch.output +} + +func (ch *BatchingChannel) Len() int { + return <-ch.length +} + +func (ch *BatchingChannel) Cap() BufferCap { + return ch.size +} + +func (ch *BatchingChannel) Close() { + close(ch.input) +} + +func (ch *BatchingChannel) batchingBuffer() { + var input, output, nextInput chan interface{} + nextInput = ch.input + input = nextInput + + for input != nil || output != nil { + select { + case elem, open := <-input: + if open { + ch.buffer = append(ch.buffer, elem) + } else { + input = nil + nextInput = nil + } + case output <- ch.buffer: + ch.buffer = nil + case ch.length <- len(ch.buffer): + } + + if len(ch.buffer) == 0 { + input = nextInput + output = nil + } else if ch.size != Infinity && len(ch.buffer) >= int(ch.size) { + input = nil + output = ch.output + } else { + input = nextInput + output = ch.output + } + } + + close(ch.output) + close(ch.length) +} diff --git a/vendor/github.com/eapache/channels/black_hole.go b/vendor/github.com/eapache/channels/black_hole.go new file mode 100644 index 000000000..0d1ba97b3 --- /dev/null +++ b/vendor/github.com/eapache/channels/black_hole.go @@ -0,0 +1,54 @@ +package channels + +// BlackHole implements the InChannel interface and provides an analogue for the "Discard" variable in +// the ioutil package - it never blocks, and simply discards every value it reads. The number of items +// discarded in this way is counted and returned from Len. +type BlackHole struct { + input chan interface{} + length chan int + count int +} + +func NewBlackHole() *BlackHole { + ch := &BlackHole{ + input: make(chan interface{}), + length: make(chan int), + } + go ch.discard() + return ch +} + +func (ch *BlackHole) In() chan<- interface{} { + return ch.input +} + +func (ch *BlackHole) Len() int { + val, open := <-ch.length + if open { + return val + } else { + return ch.count + } +} + +func (ch *BlackHole) Cap() BufferCap { + return Infinity +} + +func (ch *BlackHole) Close() { + close(ch.input) +} + +func (ch *BlackHole) discard() { + for { + select { + case _, open := <-ch.input: + if !open { + close(ch.length) + return + } + ch.count++ + case ch.length <- ch.count: + } + } +} diff --git a/vendor/github.com/eapache/channels/channels.go b/vendor/github.com/eapache/channels/channels.go new file mode 100644 index 000000000..efcb2b5c5 --- /dev/null +++ b/vendor/github.com/eapache/channels/channels.go @@ -0,0 +1,277 @@ +/* +Package channels provides a collection of helper functions, interfaces and implementations for +working with and extending the capabilities of golang's existing channels. The main interface of +interest is Channel, though sub-interfaces are also provided for cases where the full Channel interface +cannot be met (for example, InChannel for write-only channels). + +For integration with native typed golang channels, functions Wrap and Unwrap are provided which do the +appropriate type conversions. The NativeChannel, NativeInChannel and NativeOutChannel type definitions +are also provided for use with native channels which already carry values of type interface{}. + +The heart of the package consists of several distinct implementations of the Channel interface, including +channels backed by special buffers (resizable, infinite, ring buffers, etc) and other useful types. A +"black hole" channel for discarding unwanted values (similar in purpose to ioutil.Discard or /dev/null) +rounds out the set. + +Helper functions for operating on Channels include Pipe and Tee (which behave much like their Unix +namesakes), as well as Multiplex and Distribute. "Weak" versions of these functions also exist, which +do not close their output channel(s) on completion. + +Due to limitations of Go's type system, importing this library directly is often not practical for +production code. It serves equally well, however, as a reference guide and template for implementing +many common idioms; if you use it in this way I would appreciate the inclusion of some sort of credit +in the resulting code. + +Warning: several types in this package provide so-called "infinite" buffers. Be *very* careful using +these, as no buffer is truly infinite - if such a buffer grows too large your program will run out of +memory and crash. Caveat emptor. +*/ +package channels + +import "reflect" + +// BufferCap represents the capacity of the buffer backing a channel. Valid values consist of all +// positive integers, as well as the special values below. +type BufferCap int + +const ( + // None is the capacity for channels that have no buffer at all. + None BufferCap = 0 + // Infinity is the capacity for channels with no limit on their buffer size. + Infinity BufferCap = -1 +) + +// Buffer is an interface for any channel that provides access to query the state of its buffer. +// Even unbuffered channels can implement this interface by simply returning 0 from Len() and None from Cap(). +type Buffer interface { + Len() int // The number of elements currently buffered. + Cap() BufferCap // The maximum number of elements that can be buffered. +} + +// SimpleInChannel is an interface representing a writeable channel that does not necessarily +// implement the Buffer interface. +type SimpleInChannel interface { + In() chan<- interface{} // The writeable end of the channel. + Close() // Closes the channel. It is an error to write to In() after calling Close(). +} + +// InChannel is an interface representing a writeable channel with a buffer. +type InChannel interface { + SimpleInChannel + Buffer +} + +// SimpleOutChannel is an interface representing a readable channel that does not necessarily +// implement the Buffer interface. +type SimpleOutChannel interface { + Out() <-chan interface{} // The readable end of the channel. +} + +// OutChannel is an interface representing a readable channel implementing the Buffer interface. +type OutChannel interface { + SimpleOutChannel + Buffer +} + +// SimpleChannel is an interface representing a channel that is both readable and writeable, +// but does not necessarily implement the Buffer interface. +type SimpleChannel interface { + SimpleInChannel + SimpleOutChannel +} + +// Channel is an interface representing a channel that is readable, writeable and implements +// the Buffer interface +type Channel interface { + SimpleChannel + Buffer +} + +func pipe(input SimpleOutChannel, output SimpleInChannel, closeWhenDone bool) { + for elem := range input.Out() { + output.In() <- elem + } + if closeWhenDone { + output.Close() + } +} + +func multiplex(output SimpleInChannel, inputs []SimpleOutChannel, closeWhenDone bool) { + inputCount := len(inputs) + cases := make([]reflect.SelectCase, inputCount) + for i := range cases { + cases[i].Dir = reflect.SelectRecv + cases[i].Chan = reflect.ValueOf(inputs[i].Out()) + } + for inputCount > 0 { + chosen, recv, recvOK := reflect.Select(cases) + if recvOK { + output.In() <- recv.Interface() + } else { + cases[chosen].Chan = reflect.ValueOf(nil) + inputCount-- + } + } + if closeWhenDone { + output.Close() + } +} + +func tee(input SimpleOutChannel, outputs []SimpleInChannel, closeWhenDone bool) { + cases := make([]reflect.SelectCase, len(outputs)) + for i := range cases { + cases[i].Dir = reflect.SelectSend + } + for elem := range input.Out() { + for i := range cases { + cases[i].Chan = reflect.ValueOf(outputs[i].In()) + cases[i].Send = reflect.ValueOf(elem) + } + for _ = range cases { + chosen, _, _ := reflect.Select(cases) + cases[chosen].Chan = reflect.ValueOf(nil) + } + } + if closeWhenDone { + for i := range outputs { + outputs[i].Close() + } + } +} + +func distribute(input SimpleOutChannel, outputs []SimpleInChannel, closeWhenDone bool) { + cases := make([]reflect.SelectCase, len(outputs)) + for i := range cases { + cases[i].Dir = reflect.SelectSend + cases[i].Chan = reflect.ValueOf(outputs[i].In()) + } + for elem := range input.Out() { + for i := range cases { + cases[i].Send = reflect.ValueOf(elem) + } + reflect.Select(cases) + } + if closeWhenDone { + for i := range outputs { + outputs[i].Close() + } + } +} + +// Pipe connects the input channel to the output channel so that +// they behave as if a single channel. +func Pipe(input SimpleOutChannel, output SimpleInChannel) { + go pipe(input, output, true) +} + +// Multiplex takes an arbitrary number of input channels and multiplexes their output into a single output +// channel. When all input channels have been closed, the output channel is closed. Multiplex with a single +// input channel is equivalent to Pipe (though slightly less efficient). +func Multiplex(output SimpleInChannel, inputs ...SimpleOutChannel) { + if len(inputs) == 0 { + panic("channels: Multiplex requires at least one input") + } + go multiplex(output, inputs, true) +} + +// Tee (like its Unix namesake) takes a single input channel and an arbitrary number of output channels +// and duplicates each input into every output. When the input channel is closed, all outputs channels are closed. +// Tee with a single output channel is equivalent to Pipe (though slightly less efficient). +func Tee(input SimpleOutChannel, outputs ...SimpleInChannel) { + if len(outputs) == 0 { + panic("channels: Tee requires at least one output") + } + go tee(input, outputs, true) +} + +// Distribute takes a single input channel and an arbitrary number of output channels and duplicates each input +// into *one* available output. If multiple outputs are waiting for a value, one is chosen at random. When the +// input channel is closed, all outputs channels are closed. Distribute with a single output channel is +// equivalent to Pipe (though slightly less efficient). +func Distribute(input SimpleOutChannel, outputs ...SimpleInChannel) { + if len(outputs) == 0 { + panic("channels: Distribute requires at least one output") + } + go distribute(input, outputs, true) +} + +// WeakPipe behaves like Pipe (connecting the two channels) except that it does not close +// the output channel when the input channel is closed. +func WeakPipe(input SimpleOutChannel, output SimpleInChannel) { + go pipe(input, output, false) +} + +// WeakMultiplex behaves like Multiplex (multiplexing multiple inputs into a single output) except that it does not close +// the output channel when the input channels are closed. +func WeakMultiplex(output SimpleInChannel, inputs ...SimpleOutChannel) { + if len(inputs) == 0 { + panic("channels: WeakMultiplex requires at least one input") + } + go multiplex(output, inputs, false) +} + +// WeakTee behaves like Tee (duplicating a single input into multiple outputs) except that it does not close +// the output channels when the input channel is closed. +func WeakTee(input SimpleOutChannel, outputs ...SimpleInChannel) { + if len(outputs) == 0 { + panic("channels: WeakTee requires at least one output") + } + go tee(input, outputs, false) +} + +// WeakDistribute behaves like Distribute (distributing a single input amongst multiple outputs) except that +// it does not close the output channels when the input channel is closed. +func WeakDistribute(input SimpleOutChannel, outputs ...SimpleInChannel) { + if len(outputs) == 0 { + panic("channels: WeakDistribute requires at least one output") + } + go distribute(input, outputs, false) +} + +// Wrap takes any readable channel type (chan or <-chan but not chan<-) and +// exposes it as a SimpleOutChannel for easy integration with existing channel sources. +// It panics if the input is not a readable channel. +func Wrap(ch interface{}) SimpleOutChannel { + t := reflect.TypeOf(ch) + if t.Kind() != reflect.Chan || t.ChanDir()&reflect.RecvDir == 0 { + panic("channels: input to Wrap must be readable channel") + } + realChan := make(chan interface{}) + + go func() { + v := reflect.ValueOf(ch) + for { + x, ok := v.Recv() + if !ok { + close(realChan) + return + } + realChan <- x.Interface() + } + }() + + return NativeOutChannel(realChan) +} + +// Unwrap takes a SimpleOutChannel and uses reflection to pipe it to a typed native channel for +// easy integration with existing channel sources. Output can be any writable channel type (chan or chan<-). +// It panics if the output is not a writable channel, or if a value is received that cannot be sent on the +// output channel. +func Unwrap(input SimpleOutChannel, output interface{}) { + t := reflect.TypeOf(output) + if t.Kind() != reflect.Chan || t.ChanDir()&reflect.SendDir == 0 { + panic("channels: input to Unwrap must be readable channel") + } + + go func() { + v := reflect.ValueOf(output) + for { + x, ok := <-input.Out() + if !ok { + v.Close() + return + } + v.Send(reflect.ValueOf(x)) + } + }() +} diff --git a/vendor/github.com/eapache/channels/infinite_channel.go b/vendor/github.com/eapache/channels/infinite_channel.go new file mode 100644 index 000000000..3aa9e8e7e --- /dev/null +++ b/vendor/github.com/eapache/channels/infinite_channel.go @@ -0,0 +1,72 @@ +package channels + +import "github.com/eapache/queue" + +// InfiniteChannel implements the Channel interface with an infinite buffer between the input and the output. +type InfiniteChannel struct { + input, output chan interface{} + length chan int + buffer *queue.Queue +} + +func NewInfiniteChannel() *InfiniteChannel { + ch := &InfiniteChannel{ + input: make(chan interface{}), + output: make(chan interface{}), + length: make(chan int), + buffer: queue.New(), + } + go ch.infiniteBuffer() + return ch +} + +func (ch *InfiniteChannel) In() chan<- interface{} { + return ch.input +} + +func (ch *InfiniteChannel) Out() <-chan interface{} { + return ch.output +} + +func (ch *InfiniteChannel) Len() int { + return <-ch.length +} + +func (ch *InfiniteChannel) Cap() BufferCap { + return Infinity +} + +func (ch *InfiniteChannel) Close() { + close(ch.input) +} + +func (ch *InfiniteChannel) infiniteBuffer() { + var input, output chan interface{} + var next interface{} + input = ch.input + + for input != nil || output != nil { + select { + case elem, open := <-input: + if open { + ch.buffer.Add(elem) + } else { + input = nil + } + case output <- next: + ch.buffer.Remove() + case ch.length <- ch.buffer.Length(): + } + + if ch.buffer.Length() > 0 { + output = ch.output + next = ch.buffer.Peek() + } else { + output = nil + next = nil + } + } + + close(ch.output) + close(ch.length) +} diff --git a/vendor/github.com/eapache/channels/native_channel.go b/vendor/github.com/eapache/channels/native_channel.go new file mode 100644 index 000000000..3807a1991 --- /dev/null +++ b/vendor/github.com/eapache/channels/native_channel.go @@ -0,0 +1,92 @@ +package channels + +// NativeInChannel implements the InChannel interface by wrapping a native go write-only channel. +type NativeInChannel chan<- interface{} + +func (ch NativeInChannel) In() chan<- interface{} { + return ch +} + +func (ch NativeInChannel) Len() int { + return len(ch) +} + +func (ch NativeInChannel) Cap() BufferCap { + return BufferCap(cap(ch)) +} + +func (ch NativeInChannel) Close() { + close(ch) +} + +// NativeOutChannel implements the OutChannel interface by wrapping a native go read-only channel. +type NativeOutChannel <-chan interface{} + +func (ch NativeOutChannel) Out() <-chan interface{} { + return ch +} + +func (ch NativeOutChannel) Len() int { + return len(ch) +} + +func (ch NativeOutChannel) Cap() BufferCap { + return BufferCap(cap(ch)) +} + +// NativeChannel implements the Channel interface by wrapping a native go channel. +type NativeChannel chan interface{} + +// NewNativeChannel makes a new NativeChannel with the given buffer size. Just a convenience wrapper +// to avoid having to cast the result of make(). +func NewNativeChannel(size BufferCap) NativeChannel { + return make(chan interface{}, size) +} + +func (ch NativeChannel) In() chan<- interface{} { + return ch +} + +func (ch NativeChannel) Out() <-chan interface{} { + return ch +} + +func (ch NativeChannel) Len() int { + return len(ch) +} + +func (ch NativeChannel) Cap() BufferCap { + return BufferCap(cap(ch)) +} + +func (ch NativeChannel) Close() { + close(ch) +} + +// DeadChannel is a placeholder implementation of the Channel interface with no buffer +// that is never ready for reading or writing. Closing a dead channel is a no-op. +// Behaves almost like NativeChannel(nil) except that closing a nil NativeChannel will panic. +type DeadChannel struct{} + +func NewDeadChannel() DeadChannel { + return DeadChannel{} +} + +func (ch DeadChannel) In() chan<- interface{} { + return nil +} + +func (ch DeadChannel) Out() <-chan interface{} { + return nil +} + +func (ch DeadChannel) Len() int { + return 0 +} + +func (ch DeadChannel) Cap() BufferCap { + return BufferCap(0) +} + +func (ch DeadChannel) Close() { +} diff --git a/vendor/github.com/eapache/channels/overflowing_channel.go b/vendor/github.com/eapache/channels/overflowing_channel.go new file mode 100644 index 000000000..35090f8e8 --- /dev/null +++ b/vendor/github.com/eapache/channels/overflowing_channel.go @@ -0,0 +1,113 @@ +package channels + +import "github.com/eapache/queue" + +// OverflowingChannel implements the Channel interface in a way that never blocks the writer. +// Specifically, if a value is written to an OverflowingChannel when its buffer is full +// (or, in an unbuffered case, when the recipient is not ready) then that value is simply discarded. +// Note that Go's scheduler can cause discarded values when they could be avoided, simply by scheduling +// the writer before the reader, so caveat emptor. +// For the opposite behaviour (discarding the oldest element, not the newest) see RingChannel. +type OverflowingChannel struct { + input, output chan interface{} + length chan int + buffer *queue.Queue + size BufferCap +} + +func NewOverflowingChannel(size BufferCap) *OverflowingChannel { + if size < 0 && size != Infinity { + panic("channels: invalid negative size in NewOverflowingChannel") + } + ch := &OverflowingChannel{ + input: make(chan interface{}), + output: make(chan interface{}), + length: make(chan int), + size: size, + } + if size == None { + go ch.overflowingDirect() + } else { + ch.buffer = queue.New() + go ch.overflowingBuffer() + } + return ch +} + +func (ch *OverflowingChannel) In() chan<- interface{} { + return ch.input +} + +func (ch *OverflowingChannel) Out() <-chan interface{} { + return ch.output +} + +func (ch *OverflowingChannel) Len() int { + if ch.size == None { + return 0 + } else { + return <-ch.length + } +} + +func (ch *OverflowingChannel) Cap() BufferCap { + return ch.size +} + +func (ch *OverflowingChannel) Close() { + close(ch.input) +} + +// for entirely unbuffered cases +func (ch *OverflowingChannel) overflowingDirect() { + for elem := range ch.input { + // if we can't write it immediately, drop it and move on + select { + case ch.output <- elem: + default: + } + } + close(ch.output) +} + +// for all buffered cases +func (ch *OverflowingChannel) overflowingBuffer() { + var input, output chan interface{} + var next interface{} + input = ch.input + + for input != nil || output != nil { + select { + // Prefer to write if possible, which is surprisingly effective in reducing + // dropped elements due to overflow. The naive read/write select chooses randomly + // when both channels are ready, which produces unnecessary drops 50% of the time. + case output <- next: + ch.buffer.Remove() + default: + select { + case elem, open := <-input: + if open { + if ch.size == Infinity || ch.buffer.Length() < int(ch.size) { + ch.buffer.Add(elem) + } + } else { + input = nil + } + case output <- next: + ch.buffer.Remove() + case ch.length <- ch.buffer.Length(): + } + } + + if ch.buffer.Length() > 0 { + output = ch.output + next = ch.buffer.Peek() + } else { + output = nil + next = nil + } + } + + close(ch.output) + close(ch.length) +} diff --git a/vendor/github.com/eapache/channels/resizable_channel.go b/vendor/github.com/eapache/channels/resizable_channel.go new file mode 100644 index 000000000..fafed0a29 --- /dev/null +++ b/vendor/github.com/eapache/channels/resizable_channel.go @@ -0,0 +1,109 @@ +package channels + +import "github.com/eapache/queue" + +// ResizableChannel implements the Channel interface with a resizable buffer between the input and the output. +// The channel initially has a buffer size of 1, but can be resized by calling Resize(). +// +// Resizing to a buffer capacity of None is, unfortunately, not supported and will panic +// (see https://github.com/eapache/channels/issues/1). +// Resizing back and forth between a finite and infinite buffer is fully supported. +type ResizableChannel struct { + input, output chan interface{} + length chan int + capacity, resize chan BufferCap + size BufferCap + buffer *queue.Queue +} + +func NewResizableChannel() *ResizableChannel { + ch := &ResizableChannel{ + input: make(chan interface{}), + output: make(chan interface{}), + length: make(chan int), + capacity: make(chan BufferCap), + resize: make(chan BufferCap), + size: 1, + buffer: queue.New(), + } + go ch.magicBuffer() + return ch +} + +func (ch *ResizableChannel) In() chan<- interface{} { + return ch.input +} + +func (ch *ResizableChannel) Out() <-chan interface{} { + return ch.output +} + +func (ch *ResizableChannel) Len() int { + return <-ch.length +} + +func (ch *ResizableChannel) Cap() BufferCap { + val, open := <-ch.capacity + if open { + return val + } else { + return ch.size + } +} + +func (ch *ResizableChannel) Close() { + close(ch.input) +} + +func (ch *ResizableChannel) Resize(newSize BufferCap) { + if newSize == None { + panic("channels: ResizableChannel does not support unbuffered behaviour") + } + if newSize < 0 && newSize != Infinity { + panic("channels: invalid negative size trying to resize channel") + } + ch.resize <- newSize +} + +func (ch *ResizableChannel) magicBuffer() { + var input, output, nextInput chan interface{} + var next interface{} + nextInput = ch.input + input = nextInput + + for input != nil || output != nil { + select { + case elem, open := <-input: + if open { + ch.buffer.Add(elem) + } else { + input = nil + nextInput = nil + } + case output <- next: + ch.buffer.Remove() + case ch.size = <-ch.resize: + case ch.length <- ch.buffer.Length(): + case ch.capacity <- ch.size: + } + + if ch.buffer.Length() == 0 { + output = nil + next = nil + } else { + output = ch.output + next = ch.buffer.Peek() + } + + if ch.size != Infinity && ch.buffer.Length() >= int(ch.size) { + input = nil + } else { + input = nextInput + } + } + + close(ch.output) + close(ch.resize) + close(ch.length) + close(ch.capacity) +} diff --git a/vendor/github.com/eapache/channels/ring_channel.go b/vendor/github.com/eapache/channels/ring_channel.go new file mode 100644 index 000000000..7aec207bd --- /dev/null +++ b/vendor/github.com/eapache/channels/ring_channel.go @@ -0,0 +1,114 @@ +package channels + +import "github.com/eapache/queue" + +// RingChannel implements the Channel interface in a way that never blocks the writer. +// Specifically, if a value is written to a RingChannel when its buffer is full then the oldest +// value in the buffer is discarded to make room (just like a standard ring-buffer). +// Note that Go's scheduler can cause discarded values when they could be avoided, simply by scheduling +// the writer before the reader, so caveat emptor. +// For the opposite behaviour (discarding the newest element, not the oldest) see OverflowingChannel. +type RingChannel struct { + input, output chan interface{} + length chan int + buffer *queue.Queue + size BufferCap +} + +func NewRingChannel(size BufferCap) *RingChannel { + if size < 0 && size != Infinity { + panic("channels: invalid negative size in NewRingChannel") + } + ch := &RingChannel{ + input: make(chan interface{}), + output: make(chan interface{}), + buffer: queue.New(), + size: size, + } + if size == None { + go ch.overflowingDirect() + } else { + ch.length = make(chan int) + go ch.ringBuffer() + } + return ch +} + +func (ch *RingChannel) In() chan<- interface{} { + return ch.input +} + +func (ch *RingChannel) Out() <-chan interface{} { + return ch.output +} + +func (ch *RingChannel) Len() int { + if ch.size == None { + return 0 + } else { + return <-ch.length + } +} + +func (ch *RingChannel) Cap() BufferCap { + return ch.size +} + +func (ch *RingChannel) Close() { + close(ch.input) +} + +// for entirely unbuffered cases +func (ch *RingChannel) overflowingDirect() { + for elem := range ch.input { + // if we can't write it immediately, drop it and move on + select { + case ch.output <- elem: + default: + } + } + close(ch.output) +} + +// for all buffered cases +func (ch *RingChannel) ringBuffer() { + var input, output chan interface{} + var next interface{} + input = ch.input + + for input != nil || output != nil { + select { + // Prefer to write if possible, which is surprisingly effective in reducing + // dropped elements due to overflow. The naive read/write select chooses randomly + // when both channels are ready, which produces unnecessary drops 50% of the time. + case output <- next: + ch.buffer.Remove() + default: + select { + case elem, open := <-input: + if open { + ch.buffer.Add(elem) + if ch.size != Infinity && ch.buffer.Length() > int(ch.size) { + ch.buffer.Remove() + } + } else { + input = nil + } + case output <- next: + ch.buffer.Remove() + case ch.length <- ch.buffer.Length(): + } + } + + if ch.buffer.Length() > 0 { + output = ch.output + next = ch.buffer.Peek() + } else { + output = nil + next = nil + } + } + + close(ch.output) + close(ch.length) +} diff --git a/vendor/github.com/eapache/channels/shared_buffer.go b/vendor/github.com/eapache/channels/shared_buffer.go new file mode 100644 index 000000000..556dc190a --- /dev/null +++ b/vendor/github.com/eapache/channels/shared_buffer.go @@ -0,0 +1,167 @@ +package channels + +import ( + "reflect" + + "github.com/eapache/queue" +) + +//sharedBufferChannel implements SimpleChannel and is created by the public +//SharedBuffer type below +type sharedBufferChannel struct { + in chan interface{} + out chan interface{} + buf *queue.Queue + closed bool +} + +func (sch *sharedBufferChannel) In() chan<- interface{} { + return sch.in +} + +func (sch *sharedBufferChannel) Out() <-chan interface{} { + return sch.out +} + +func (sch *sharedBufferChannel) Close() { + close(sch.in) +} + +//SharedBuffer implements the Buffer interface, and permits multiple SimpleChannel instances to "share" a single buffer. +//Each channel spawned by NewChannel has its own internal queue (so values flowing through do not get mixed up with +//other channels) but the total number of elements buffered by all spawned channels is limited to a single capacity. This +//means *all* such channels block and unblock for writing together. The primary use case is for implementing pipeline-style +//parallelism with goroutines, limiting the total number of elements in the pipeline without limiting the number of elements +//at any particular step. +type SharedBuffer struct { + cases []reflect.SelectCase // 2n+1 of these; [0] is for control, [1,3,5...] for recv, [2,4,6...] for send + chans []*sharedBufferChannel // n of these + count int + size BufferCap + in chan *sharedBufferChannel +} + +func NewSharedBuffer(size BufferCap) *SharedBuffer { + if size < 0 && size != Infinity { + panic("channels: invalid negative size in NewSharedBuffer") + } else if size == None { + panic("channels: SharedBuffer does not support unbuffered behaviour") + } + + buf := &SharedBuffer{ + size: size, + in: make(chan *sharedBufferChannel), + } + + buf.cases = append(buf.cases, reflect.SelectCase{ + Dir: reflect.SelectRecv, + Chan: reflect.ValueOf(buf.in), + }) + + go buf.mainLoop() + + return buf +} + +//NewChannel spawns and returns a new channel sharing the underlying buffer. +func (buf *SharedBuffer) NewChannel() SimpleChannel { + ch := &sharedBufferChannel{ + in: make(chan interface{}), + out: make(chan interface{}), + buf: queue.New(), + } + buf.in <- ch + return ch +} + +//Close shuts down the SharedBuffer. It is an error to call Close while channels are still using +//the buffer (I'm not really sure what would happen if you do so). +func (buf *SharedBuffer) Close() { + // TODO: what if there are still active channels using this buffer? + close(buf.in) +} + +func (buf *SharedBuffer) mainLoop() { + for { + i, val, ok := reflect.Select(buf.cases) + + if i == 0 { + if !ok { + //Close was called on the SharedBuffer itself + return + } + + //NewChannel was called on the SharedBuffer + ch := val.Interface().(*sharedBufferChannel) + buf.chans = append(buf.chans, ch) + buf.cases = append(buf.cases, + reflect.SelectCase{Dir: reflect.SelectRecv}, + reflect.SelectCase{Dir: reflect.SelectSend}, + ) + if buf.size == Infinity || buf.count < int(buf.size) { + buf.cases[len(buf.cases)-2].Chan = reflect.ValueOf(ch.in) + } + } else if i%2 == 0 { + //Send + if buf.count == int(buf.size) { + //room in the buffer again, re-enable all recv cases + for j := range buf.chans { + if !buf.chans[j].closed { + buf.cases[(j*2)+1].Chan = reflect.ValueOf(buf.chans[j].in) + } + } + } + buf.count-- + ch := buf.chans[(i-1)/2] + if ch.buf.Length() > 0 { + buf.cases[i].Send = reflect.ValueOf(ch.buf.Peek()) + ch.buf.Remove() + } else { + //nothing left for this channel to send, disable sending + buf.cases[i].Chan = reflect.Value{} + buf.cases[i].Send = reflect.Value{} + if ch.closed { + // and it was closed, so close the output channel + //TODO: shrink slice + close(ch.out) + } + } + } else { + ch := buf.chans[i/2] + if ok { + //Receive + buf.count++ + if ch.buf.Length() == 0 && !buf.cases[i+1].Chan.IsValid() { + //this channel now has something to send + buf.cases[i+1].Chan = reflect.ValueOf(ch.out) + buf.cases[i+1].Send = val + } else { + ch.buf.Add(val.Interface()) + } + if buf.count == int(buf.size) { + //buffer full, disable recv cases + for j := range buf.chans { + buf.cases[(j*2)+1].Chan = reflect.Value{} + } + } + } else { + //Close + buf.cases[i].Chan = reflect.Value{} + ch.closed = true + if ch.buf.Length() == 0 && !buf.cases[i+1].Chan.IsValid() { + //nothing pending, close the out channel right away + //TODO: shrink slice + close(ch.out) + } + } + } + } +} + +func (buf *SharedBuffer) Len() int { + return buf.count +} + +func (buf *SharedBuffer) Cap() BufferCap { + return buf.size +} diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index 42d9abc07..5152bf59b 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -1,20 +1,11 @@ -# Archived project. No maintenance. - -This project is not maintained anymore and is archived. Feel free to fork and -make your own changes if needed. For more detail read my blog post: [Taking an indefinite sabbatical from my projects](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/) - -Thanks to everyone for their valuable feedback and contributions. - - -# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color) +# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color) Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you. - -![Color](https://i.imgur.com/c1JI0lA.png) +![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg) ## Install @@ -87,7 +78,7 @@ notice("Don't forget this...") ### Custom fprint functions (FprintFunc) ```go -blue := color.New(FgBlue).FprintfFunc() +blue := color.New(color.FgBlue).FprintfFunc() blue(myWriter, "important notice: %s", stars) // Mix up with multiple attributes @@ -136,14 +127,16 @@ fmt.Println("All text will now be bold magenta.") There might be a case where you want to explicitly disable/enable color output. the `go-isatty` package will automatically disable color output for non-tty output streams -(for example if the output were piped directly to `less`) +(for example if the output were piped directly to `less`). -`Color` has support to disable/enable colors both globally and for single color -definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You -can easily disable the color output with: +The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment +variable is set (regardless of its value). -```go +`Color` has support to disable/enable colors programatically both globally and +for single color definitions. For example suppose you have a CLI app and a +`--no-color` bool flag. You can easily disable the color output with: +```go var flagNoColor = flag.Bool("no-color", false, "Disable color output") if *flagNoColor { @@ -165,6 +158,10 @@ c.EnableColor() c.Println("This prints again cyan...") ``` +## GitHub Actions + +To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. + ## Todo * Save/Return previous values @@ -179,4 +176,3 @@ c.Println("This prints again cyan...") ## License The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details - diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go index 91c8e9f06..98a60f3c8 100644 --- a/vendor/github.com/fatih/color/color.go +++ b/vendor/github.com/fatih/color/color.go @@ -15,9 +15,11 @@ import ( var ( // NoColor defines if the output is colorized or not. It's dynamically set to // false or true based on the stdout's file descriptor referring to a terminal - // or not. This is a global option and affects all colors. For more control - // over each color block use the methods DisableColor() individually. - NoColor = os.Getenv("TERM") == "dumb" || + // or not. It's also set to true if the NO_COLOR environment variable is + // set (regardless of its value). This is a global option and affects all + // colors. For more control over each color block use the methods + // DisableColor() individually. + NoColor = noColorExists() || os.Getenv("TERM") == "dumb" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) // Output defines the standard output of the print functions. By default @@ -33,6 +35,12 @@ var ( colorsCacheMu sync.Mutex // protects colorsCache ) +// noColorExists returns true if the environment variable NO_COLOR exists. +func noColorExists() bool { + _, exists := os.LookupEnv("NO_COLOR") + return exists +} + // Color defines a custom color object which is defined by SGR parameters. type Color struct { params []Attribute @@ -108,7 +116,14 @@ const ( // New returns a newly created color object. func New(value ...Attribute) *Color { - c := &Color{params: make([]Attribute, 0)} + c := &Color{ + params: make([]Attribute, 0), + } + + if noColorExists() { + c.noColor = boolPtr(true) + } + c.Add(value...) return c } @@ -387,7 +402,7 @@ func (c *Color) EnableColor() { } func (c *Color) isNoColorSet() bool { - // check first if we have user setted action + // check first if we have user set action if c.noColor != nil { return *c.noColor } diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go index cf1e96500..04541de78 100644 --- a/vendor/github.com/fatih/color/doc.go +++ b/vendor/github.com/fatih/color/doc.go @@ -118,6 +118,8 @@ the color output with: color.NoColor = true // disables colorized output } +You can also disable the color by setting the NO_COLOR environment variable to any value. + It also has support for single color definitions (local). You can disable/enable color output on the fly: diff --git a/vendor/github.com/fatih/color/go.mod b/vendor/github.com/fatih/color/go.mod index bc0df7545..c9b3cd59a 100644 --- a/vendor/github.com/fatih/color/go.mod +++ b/vendor/github.com/fatih/color/go.mod @@ -3,6 +3,6 @@ module github.com/fatih/color go 1.13 require ( - github.com/mattn/go-colorable v0.1.4 - github.com/mattn/go-isatty v0.0.11 + github.com/mattn/go-colorable v0.1.9 + github.com/mattn/go-isatty v0.0.14 ) diff --git a/vendor/github.com/fatih/color/go.sum b/vendor/github.com/fatih/color/go.sum index 44328a8db..cbbcfb644 100644 --- a/vendor/github.com/fatih/color/go.sum +++ b/vendor/github.com/fatih/color/go.sum @@ -1,8 +1,9 @@ -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/fsnotify/fsnotify/.editorconfig b/vendor/github.com/fsnotify/fsnotify/.editorconfig new file mode 100644 index 000000000..fad895851 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*.go] +indent_style = tab +indent_size = 4 +insert_final_newline = true + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/vendor/github.com/fsnotify/fsnotify/.gitattributes b/vendor/github.com/fsnotify/fsnotify/.gitattributes new file mode 100644 index 000000000..32f1001be --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.gitattributes @@ -0,0 +1 @@ +go.sum linguist-generated diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore new file mode 100644 index 000000000..4cd0cbaf4 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -0,0 +1,6 @@ +# Setup a Global .gitignore for OS and editor generated files: +# https://help.github.com/articles/ignoring-files +# git config --global core.excludesfile ~/.gitignore_global + +.vagrant +*.sublime-project diff --git a/vendor/github.com/fsnotify/fsnotify/.mailmap b/vendor/github.com/fsnotify/fsnotify/.mailmap new file mode 100644 index 000000000..a04f2907f --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.mailmap @@ -0,0 +1,2 @@ +Chris Howey +Nathan Youngman <4566+nathany@users.noreply.github.com> diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS new file mode 100644 index 000000000..6cbabe5ef --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/AUTHORS @@ -0,0 +1,62 @@ +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# You can update this list using the following command: +# +# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS + +# Please keep the list sorted. + +Aaron L +Adrien Bustany +Alexey Kazakov +Amit Krishnan +Anmol Sethi +Bjørn Erik Pedersen +Brian Goff +Bruno Bigras +Caleb Spare +Case Nelson +Chris Howey +Christoffer Buchholz +Daniel Wagner-Hall +Dave Cheney +Eric Lin +Evan Phoenix +Francisco Souza +Gautam Dey +Hari haran +Ichinose Shogo +Johannes Ebke +John C Barstow +Kelvin Fo +Ken-ichirou MATSUZAWA +Matt Layher +Matthias Stone +Nathan Youngman +Nickolai Zeldovich +Oliver Bristow +Patrick +Paul Hammond +Pawel Knap +Pieter Droogendijk +Pratik Shinde +Pursuit92 +Riku Voipio +Rob Figueiredo +Rodrigo Chiossi +Slawek Ligus +Soge Zhang +Tiffany Jernigan +Tilak Sharma +Tobias Klauser +Tom Payne +Travis Cline +Tudor Golubenco +Vahe Khachikyan +Yukang +bronze1man +debrando +henrikedwards +铁哥 diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md new file mode 100644 index 000000000..a438fe4b4 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -0,0 +1,339 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.5.1] - 2021-08-24 + +* Revert Add AddRaw to not follow symlinks + +## [1.5.0] - 2021-08-20 + +* Go: Increase minimum required version to Go 1.12 [#381](https://github.com/fsnotify/fsnotify/pull/381) +* Feature: Add AddRaw method which does not follow symlinks when adding a watch [#289](https://github.com/fsnotify/fsnotify/pull/298) +* Windows: Follow symlinks by default like on all other systems [#289](https://github.com/fsnotify/fsnotify/pull/289) +* CI: Use GitHub Actions for CI and cover go 1.12-1.17 + [#378](https://github.com/fsnotify/fsnotify/pull/378) + [#381](https://github.com/fsnotify/fsnotify/pull/381) + [#385](https://github.com/fsnotify/fsnotify/pull/385) +* Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325) + +## [1.4.7] - 2018-01-09 + +* BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) +* Tests: Fix missing verb on format string (thanks @rchiossi) +* Linux: Fix deadlock in Remove (thanks @aarondl) +* Linux: Watch.Add improvements (avoid race, fix consistency, reduce garbage) (thanks @twpayne) +* Docs: Moved FAQ into the README (thanks @vahe) +* Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich) +* Docs: replace references to OS X with macOS + +## [1.4.2] - 2016-10-10 + +* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack) + +## [1.4.1] - 2016-10-04 + +* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack) + +## [1.4.0] - 2016-10-01 + +* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie) + +## [1.3.1] - 2016-06-28 + +* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc) + +## [1.3.0] - 2016-04-19 + +* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135) + +## [1.2.10] - 2016-03-02 + +* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj) + +## [1.2.9] - 2016-01-13 + +kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep) + +## [1.2.8] - 2015-12-17 + +* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test) +* inotify: fix race in test +* enable race detection for continuous integration (Linux, Mac, Windows) + +## [1.2.5] - 2015-10-17 + +* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki) +* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken) +* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie) +* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion) + +## [1.2.1] - 2015-10-14 + +* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx) + +## [1.2.0] - 2015-02-08 + +* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD) +* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD) +* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59) + +## [1.1.1] - 2015-02-05 + +* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD) + +## [1.1.0] - 2014-12-12 + +* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43) + * add low-level functions + * only need to store flags on directories + * less mutexes [#13](https://github.com/fsnotify/fsnotify/issues/13) + * done can be an unbuffered channel + * remove calls to os.NewSyscallError +* More efficient string concatenation for Event.String() [#52](https://github.com/fsnotify/fsnotify/pull/52) (thanks @mdlayher) +* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48) +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) + +## [1.0.4] - 2014-09-07 + +* kqueue: add dragonfly to the build tags. +* Rename source code files, rearrange code so exported APIs are at the top. +* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang) + +## [1.0.3] - 2014-08-19 + +* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36) + +## [1.0.2] - 2014-08-17 + +* [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) +* [Fix] Make ./path and path equivalent. (thanks @zhsso) + +## [1.0.0] - 2014-08-15 + +* [API] Remove AddWatch on Windows, use Add. +* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30) +* Minor updates based on feedback from golint. + +## dev / 2014-07-09 + +* Moved to [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify). +* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno) + +## dev / 2014-07-04 + +* kqueue: fix incorrect mutex used in Close() +* Update example to demonstrate usage of Op. + +## dev / 2014-06-28 + +* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/fsnotify/fsnotify/issues/4) +* Fix for String() method on Event (thanks Alex Brainman) +* Don't build on Plan 9 or Solaris (thanks @4ad) + +## dev / 2014-06-21 + +* Events channel of type Event rather than *Event. +* [internal] use syscall constants directly for inotify and kqueue. +* [internal] kqueue: rename events to kevents and fileEvent to event. + +## dev / 2014-06-19 + +* Go 1.3+ required on Windows (uses syscall.ERROR_MORE_DATA internally). +* [internal] remove cookie from Event struct (unused). +* [internal] Event struct has the same definition across every OS. +* [internal] remove internal watch and removeWatch methods. + +## dev / 2014-06-12 + +* [API] Renamed Watch() to Add() and RemoveWatch() to Remove(). +* [API] Pluralized channel names: Events and Errors. +* [API] Renamed FileEvent struct to Event. +* [API] Op constants replace methods like IsCreate(). + +## dev / 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## dev / 2014-05-23 + +* [API] Remove current implementation of WatchFlags. + * current implementation doesn't take advantage of OS for efficiency + * provides little benefit over filtering events as they are received, but has extra bookkeeping and mutexes + * no tests for the current implementation + * not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195) + +## [0.9.3] - 2014-12-31 + +* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) + +## [0.9.2] - 2014-08-17 + +* [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) + +## [0.9.1] - 2014-06-12 + +* Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) + +## [0.9.0] - 2014-01-17 + +* IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany) +* [Fix] kqueue: fix deadlock [#77][] (thanks @cespare) +* [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library. + +## [0.8.12] - 2013-11-13 + +* [API] Remove FD_SET and friends from Linux adapter + +## [0.8.11] - 2013-11-02 + +* [Doc] Add Changelog [#72][] (thanks @nathany) +* [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond) + +## [0.8.10] - 2013-10-19 + +* [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott) +* [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer) +* [Doc] specify OS-specific limits in README (thanks @debrando) + +## [0.8.9] - 2013-09-08 + +* [Doc] Contributing (thanks @nathany) +* [Doc] update package path in example code [#63][] (thanks @paulhammond) +* [Doc] GoCI badge in README (Linux only) [#60][] +* [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany) + +## [0.8.8] - 2013-06-17 + +* [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie) + +## [0.8.7] - 2013-06-03 + +* [API] Make syscall flags internal +* [Fix] inotify: ignore event changes +* [Fix] race in symlink test [#45][] (reported by @srid) +* [Fix] tests on Windows +* lower case error messages + +## [0.8.6] - 2013-05-23 + +* kqueue: Use EVT_ONLY flag on Darwin +* [Doc] Update README with full example + +## [0.8.5] - 2013-05-09 + +* [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg) + +## [0.8.4] - 2013-04-07 + +* [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz) + +## [0.8.3] - 2013-03-13 + +* [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin) +* [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin) + +## [0.8.2] - 2013-02-07 + +* [Doc] add Authors +* [Fix] fix data races for map access [#29][] (thanks @fsouza) + +## [0.8.1] - 2013-01-09 + +* [Fix] Windows path separators +* [Doc] BSD License + +## [0.8.0] - 2012-11-09 + +* kqueue: directory watching improvements (thanks @vmirage) +* inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto) +* [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr) + +## [0.7.4] - 2012-10-09 + +* [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji) +* [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig) +* [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig) +* [Fix] kqueue: modify after recreation of file + +## [0.7.3] - 2012-09-27 + +* [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage) +* [Fix] kqueue: no longer get duplicate CREATE events + +## [0.7.2] - 2012-09-01 + +* kqueue: events for created directories + +## [0.7.1] - 2012-07-14 + +* [Fix] for renaming files + +## [0.7.0] - 2012-07-02 + +* [Feature] FSNotify flags +* [Fix] inotify: Added file name back to event path + +## [0.6.0] - 2012-06-06 + +* kqueue: watch files after directory created (thanks @tmc) + +## [0.5.1] - 2012-05-22 + +* [Fix] inotify: remove all watches before Close() + +## [0.5.0] - 2012-05-03 + +* [API] kqueue: return errors during watch instead of sending over channel +* kqueue: match symlink behavior on Linux +* inotify: add `DELETE_SELF` (requested by @taralx) +* [Fix] kqueue: handle EINTR (reported by @robfig) +* [Doc] Godoc example [#1][] (thanks @davecheney) + +## [0.4.0] - 2012-03-30 + +* Go 1 released: build with go tool +* [Feature] Windows support using winfsnotify +* Windows does not have attribute change notifications +* Roll attribute notifications into IsModify + +## [0.3.0] - 2012-02-19 + +* kqueue: add files when watch directory + +## [0.2.0] - 2011-12-30 + +* update to latest Go weekly code + +## [0.1.0] - 2011-10-19 + +* kqueue: add watch on file creation to match inotify +* kqueue: create file event +* inotify: ignore `IN_IGNORED` events +* event String() +* linux: common FileEvent functions +* initial commit + +[#79]: https://github.com/howeyc/fsnotify/pull/79 +[#77]: https://github.com/howeyc/fsnotify/pull/77 +[#72]: https://github.com/howeyc/fsnotify/issues/72 +[#71]: https://github.com/howeyc/fsnotify/issues/71 +[#70]: https://github.com/howeyc/fsnotify/issues/70 +[#63]: https://github.com/howeyc/fsnotify/issues/63 +[#62]: https://github.com/howeyc/fsnotify/issues/62 +[#60]: https://github.com/howeyc/fsnotify/issues/60 +[#59]: https://github.com/howeyc/fsnotify/issues/59 +[#49]: https://github.com/howeyc/fsnotify/issues/49 +[#45]: https://github.com/howeyc/fsnotify/issues/45 +[#40]: https://github.com/howeyc/fsnotify/issues/40 +[#36]: https://github.com/howeyc/fsnotify/issues/36 +[#33]: https://github.com/howeyc/fsnotify/issues/33 +[#29]: https://github.com/howeyc/fsnotify/issues/29 +[#25]: https://github.com/howeyc/fsnotify/issues/25 +[#24]: https://github.com/howeyc/fsnotify/issues/24 +[#21]: https://github.com/howeyc/fsnotify/issues/21 diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md new file mode 100644 index 000000000..828a60b24 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -0,0 +1,77 @@ +# Contributing + +## Issues + +* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). +* Please indicate the platform you are using fsnotify on. +* A code example to reproduce the problem is appreciated. + +## Pull Requests + +### Contributor License Agreement + +fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). + +Please indicate that you have signed the CLA in your pull request. + +### How fsnotify is Developed + +* Development is done on feature branches. +* Tests are run on BSD, Linux, macOS and Windows. +* Pull requests are reviewed and [applied to master][am] using [hub][]. + * Maintainers may modify or squash commits rather than asking contributors to. +* To issue a new release, the maintainers will: + * Update the CHANGELOG + * Tag a version, which will become available through gopkg.in. + +### How to Fork + +For smooth sailing, always use the original import path. Installing with `go get` makes this easy. + +1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Ensure everything works and the tests pass (see below) +4. Commit your changes (`git commit -am 'Add some feature'`) + +Contribute upstream: + +1. Fork fsnotify on GitHub +2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) +3. Push to the branch (`git push fork my-new-feature`) +4. Create a new Pull Request on GitHub + +This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). + +### Testing + +fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. + +Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. + +To aid in cross-platform testing there is a Vagrantfile for Linux and BSD. + +* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) +* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder. +* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password) +* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd fsnotify/fsnotify; go test'`. +* When you're done, you will want to halt or destroy the Vagrant boxes. + +Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory. + +Right now there is no equivalent solution for Windows and macOS, but there are Windows VMs [freely available from Microsoft](http://www.modern.ie/en-us/virtualization-tools#downloads). + +### Maintainers + +Help maintaining fsnotify is welcome. To be a maintainer: + +* Submit a pull request and sign the CLA as above. +* You must be able to run the test suite on Mac, Windows, Linux and BSD. + +To keep master clean, the fsnotify project uses the "apply mail" workflow outlined in Nathaniel Talbott's post ["Merge pull request" Considered Harmful][am]. This requires installing [hub][]. + +All code changes should be internal pull requests. + +Releases are tagged using [Semantic Versioning](http://semver.org/). + +[hub]: https://github.com/github/hub +[am]: http://blog.spreedly.com/2014/06/24/merge-pull-request-considered-harmful/#.VGa5yZPF_Zs diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE new file mode 100644 index 000000000..e180c8fb0 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md new file mode 100644 index 000000000..df57b1b28 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -0,0 +1,130 @@ +# File system notifications for Go + +[![GoDoc](https://godoc.org/github.com/fsnotify/fsnotify?status.svg)](https://godoc.org/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) + +fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather than `syscall` from the standard library. Ensure you have the latest version installed by running: + +```console +go get -u golang.org/x/sys/... +``` + +Cross platform: Windows, Linux, BSD and macOS. + +| Adapter | OS | Status | +| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| inotify | Linux 2.6.27 or later, Android\* | Supported | +| kqueue | BSD, macOS, iOS\* | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | +| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) | +| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) | +| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | +| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | + +\* Android and iOS are untested. + +Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. + +## API stability + +fsnotify is a fork of [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). + +All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). Further API changes are [planned](https://github.com/fsnotify/fsnotify/milestones), and will be tagged with a new major revision number. + +Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`. + +## Usage + +```go +package main + +import ( + "log" + + "github.com/fsnotify/fsnotify" +) + +func main() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + done := make(chan bool) + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + log.Println("event:", event) + if event.Op&fsnotify.Write == fsnotify.Write { + log.Println("modified file:", event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Println("error:", err) + } + } + }() + + err = watcher.Add("/tmp/foo") + if err != nil { + log.Fatal(err) + } + <-done +} +``` + +## Contributing + +Please refer to [CONTRIBUTING][] before opening an issue or pull request. + +## Example + +See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go). + +## FAQ + +**When a file is moved to another directory is it still being watched?** + +No (it shouldn't be, unless you are watching where it was moved to). + +**When I watch a directory, are all subdirectories watched as well?** + +No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). + +**Do I have to watch the Error and Event channels in a separate goroutine?** + +As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) + +**Why am I receiving multiple events for the same file on OS X?** + +Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). + +**How many files can be watched at once?** + +There are OS-specific limits as to how many watches can be created: +* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. +* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. + +**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?** + +fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications. + +[#62]: https://github.com/howeyc/fsnotify/issues/62 +[#18]: https://github.com/fsnotify/fsnotify/issues/18 +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#7]: https://github.com/howeyc/fsnotify/issues/7 + +[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md + +## Related Projects + +* [notify](https://github.com/rjeczalik/notify) +* [fsevents](https://github.com/fsnotify/fsevents) + diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go new file mode 100644 index 000000000..b3ac3d8f5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/fen.go @@ -0,0 +1,38 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build solaris +// +build solaris + +package fsnotify + +import ( + "errors" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + return nil +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + return nil +} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go new file mode 100644 index 000000000..0f4ee52e8 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -0,0 +1,69 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !plan9 +// +build !plan9 + +// Package fsnotify provides a platform-independent interface for file system notifications. +package fsnotify + +import ( + "bytes" + "errors" + "fmt" +) + +// Event represents a single file system notification. +type Event struct { + Name string // Relative path to the file or directory. + Op Op // File operation that triggered the event. +} + +// Op describes a set of file operations. +type Op uint32 + +// These are the generalized file operations that can trigger a notification. +const ( + Create Op = 1 << iota + Write + Remove + Rename + Chmod +) + +func (op Op) String() string { + // Use a buffer for efficient string concatenation + var buffer bytes.Buffer + + if op&Create == Create { + buffer.WriteString("|CREATE") + } + if op&Remove == Remove { + buffer.WriteString("|REMOVE") + } + if op&Write == Write { + buffer.WriteString("|WRITE") + } + if op&Rename == Rename { + buffer.WriteString("|RENAME") + } + if op&Chmod == Chmod { + buffer.WriteString("|CHMOD") + } + if buffer.Len() == 0 { + return "" + } + return buffer.String()[1:] // Strip leading pipe +} + +// String returns a string representation of the event in the form +// "file: REMOVE|WRITE|..." +func (e Event) String() string { + return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) +} + +// Common errors that can be reported by a watcher +var ( + ErrEventOverflow = errors.New("fsnotify queue overflow") +) diff --git a/vendor/github.com/fsnotify/fsnotify/go.mod b/vendor/github.com/fsnotify/fsnotify/go.mod new file mode 100644 index 000000000..54089e48b --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/go.mod @@ -0,0 +1,7 @@ +module github.com/fsnotify/fsnotify + +go 1.13 + +require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c + +retract v1.5.0 diff --git a/vendor/github.com/fsnotify/fsnotify/go.sum b/vendor/github.com/fsnotify/fsnotify/go.sum new file mode 100644 index 000000000..0f478630c --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go new file mode 100644 index 000000000..eb87699b5 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/inotify.go @@ -0,0 +1,338 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package fsnotify + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "sync" + "unsafe" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + mu sync.Mutex // Map access + fd int + poller *fdPoller + watches map[string]*watch // Map of inotify watches (key: path) + paths map[int]string // Map of watched paths (key: watch descriptor) + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneResp chan struct{} // Channel to respond to Close +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + // Create inotify fd + fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC) + if fd == -1 { + return nil, errno + } + // Create epoll + poller, err := newFdPoller(fd) + if err != nil { + unix.Close(fd) + return nil, err + } + w := &Watcher{ + fd: fd, + poller: poller, + watches: make(map[string]*watch), + paths: make(map[int]string), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + doneResp: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +func (w *Watcher) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed() { + return nil + } + + // Send 'close' signal to goroutine, and set the Watcher to closed. + close(w.done) + + // Wake up goroutine + w.poller.wake() + + // Wait for goroutine to close + <-w.doneResp + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + name = filepath.Clean(name) + if w.isClosed() { + return errors.New("inotify instance already closed") + } + + const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | + unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | + unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF + + var flags uint32 = agnosticEvents + + w.mu.Lock() + defer w.mu.Unlock() + watchEntry := w.watches[name] + if watchEntry != nil { + flags |= watchEntry.flags | unix.IN_MASK_ADD + } + wd, errno := unix.InotifyAddWatch(w.fd, name, flags) + if wd == -1 { + return errno + } + + if watchEntry == nil { + w.watches[name] = &watch{wd: uint32(wd), flags: flags} + w.paths[wd] = name + } else { + watchEntry.wd = uint32(wd) + watchEntry.flags = flags + } + + return nil +} + +// Remove stops watching the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + + // Fetch the watch. + w.mu.Lock() + defer w.mu.Unlock() + watch, ok := w.watches[name] + + // Remove it from inotify. + if !ok { + return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) + } + + // We successfully removed the watch if InotifyRmWatch doesn't return an + // error, we need to clean up our internal state to ensure it matches + // inotify's kernel state. + delete(w.paths, int(watch.wd)) + delete(w.watches, name) + + // inotify_rm_watch will return EINVAL if the file has been deleted; + // the inotify will already have been removed. + // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously + // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE + // so that EINVAL means that the wd is being rm_watch()ed or its file removed + // by another thread and we have not received IN_IGNORE event. + success, errno := unix.InotifyRmWatch(w.fd, watch.wd) + if success == -1 { + // TODO: Perhaps it's not helpful to return an error here in every case. + // the only two possible errors are: + // EBADF, which happens when w.fd is not a valid file descriptor of any kind. + // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. + // Watch descriptors are invalidated when they are removed explicitly or implicitly; + // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. + return errno + } + + return nil +} + +type watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Events channel +func (w *Watcher) readEvents() { + var ( + buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events + n int // Number of bytes read with read() + errno error // Syscall errno + ok bool // For poller.wait + ) + + defer close(w.doneResp) + defer close(w.Errors) + defer close(w.Events) + defer unix.Close(w.fd) + defer w.poller.close() + + for { + // See if we have been closed. + if w.isClosed() { + return + } + + ok, errno = w.poller.wait() + if errno != nil { + select { + case w.Errors <- errno: + case <-w.done: + return + } + continue + } + + if !ok { + continue + } + + n, errno = unix.Read(w.fd, buf[:]) + // If a signal interrupted execution, see if we've been asked to close, and try again. + // http://man7.org/linux/man-pages/man7/signal.7.html : + // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" + if errno == unix.EINTR { + continue + } + + // unix.Read might have been woken up by Close. If so, we're done. + if w.isClosed() { + return + } + + if n < unix.SizeofInotifyEvent { + var err error + if n == 0 { + // If EOF is received. This should really never happen. + err = io.EOF + } else if n < 0 { + // If an error occurred while reading. + err = errno + } else { + // Read was too short. + err = errors.New("notify: short read in readEvents()") + } + select { + case w.Errors <- err: + case <-w.done: + return + } + continue + } + + var offset uint32 + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + for offset <= uint32(n-unix.SizeofInotifyEvent) { + // Point "raw" to the event in the buffer + raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) + + mask := uint32(raw.Mask) + nameLen := uint32(raw.Len) + + if mask&unix.IN_Q_OVERFLOW != 0 { + select { + case w.Errors <- ErrEventOverflow: + case <-w.done: + return + } + } + + // If the event happened to the watched directory or the watched file, the kernel + // doesn't append the filename to the event, but we would like to always fill the + // the "Name" field with a valid filename. We retrieve the path of the watch from + // the "paths" map. + w.mu.Lock() + name, ok := w.paths[int(raw.Wd)] + // IN_DELETE_SELF occurs when the file/directory being watched is removed. + // This is a sign to clean up the maps, otherwise we are no longer in sync + // with the inotify kernel state which has already deleted the watch + // automatically. + if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + delete(w.paths, int(raw.Wd)) + delete(w.watches, name) + } + w.mu.Unlock() + + if nameLen > 0 { + // Point "bytes" at the first byte of the filename + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] + // The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + event := newEvent(name, mask) + + // Send the events that are not ignored on the events channel + if !event.ignoreLinux(mask) { + select { + case w.Events <- event: + case <-w.done: + return + } + } + + // Move to the next event in the buffer + offset += unix.SizeofInotifyEvent + nameLen + } + } +} + +// Certain types of events can be "ignored" and not sent over the Events +// channel. Such as events marked ignore by the kernel, or MODIFY events +// against files that do not exist. +func (e *Event) ignoreLinux(mask uint32) bool { + // Ignore anything the inotify API says to ignore + if mask&unix.IN_IGNORED == unix.IN_IGNORED { + return true + } + + // If the event is not a DELETE or RENAME, the file must exist. + // Otherwise the event is ignored. + // *Note*: this was put in place because it was seen that a MODIFY + // event was sent after the DELETE. This ignores that MODIFY and + // assumes a DELETE will come or has come if the file doesn't exist. + if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { + _, statErr := os.Lstat(e.Name) + return os.IsNotExist(statErr) + } + return false +} + +// newEvent returns an platform-independent Event based on an inotify mask. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + e.Op |= Create + } + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { + e.Op |= Remove + } + if mask&unix.IN_MODIFY == unix.IN_MODIFY { + e.Op |= Write + } + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + e.Op |= Rename + } + if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { + e.Op |= Chmod + } + return e +} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go new file mode 100644 index 000000000..e9ff9439f --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go @@ -0,0 +1,188 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package fsnotify + +import ( + "errors" + + "golang.org/x/sys/unix" +) + +type fdPoller struct { + fd int // File descriptor (as returned by the inotify_init() syscall) + epfd int // Epoll file descriptor + pipe [2]int // Pipe for waking up +} + +func emptyPoller(fd int) *fdPoller { + poller := new(fdPoller) + poller.fd = fd + poller.epfd = -1 + poller.pipe[0] = -1 + poller.pipe[1] = -1 + return poller +} + +// Create a new inotify poller. +// This creates an inotify handler, and an epoll handler. +func newFdPoller(fd int) (*fdPoller, error) { + var errno error + poller := emptyPoller(fd) + defer func() { + if errno != nil { + poller.close() + } + }() + poller.fd = fd + + // Create epoll fd + poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC) + if poller.epfd == -1 { + return nil, errno + } + // Create pipe; pipe[0] is the read end, pipe[1] the write end. + errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC) + if errno != nil { + return nil, errno + } + + // Register inotify fd with epoll + event := unix.EpollEvent{ + Fd: int32(poller.fd), + Events: unix.EPOLLIN, + } + errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event) + if errno != nil { + return nil, errno + } + + // Register pipe fd with epoll + event = unix.EpollEvent{ + Fd: int32(poller.pipe[0]), + Events: unix.EPOLLIN, + } + errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event) + if errno != nil { + return nil, errno + } + + return poller, nil +} + +// Wait using epoll. +// Returns true if something is ready to be read, +// false if there is not. +func (poller *fdPoller) wait() (bool, error) { + // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. + // I don't know whether epoll_wait returns the number of events returned, + // or the total number of events ready. + // I decided to catch both by making the buffer one larger than the maximum. + events := make([]unix.EpollEvent, 7) + for { + n, errno := unix.EpollWait(poller.epfd, events, -1) + if n == -1 { + if errno == unix.EINTR { + continue + } + return false, errno + } + if n == 0 { + // If there are no events, try again. + continue + } + if n > 6 { + // This should never happen. More events were returned than should be possible. + return false, errors.New("epoll_wait returned more events than I know what to do with") + } + ready := events[:n] + epollhup := false + epollerr := false + epollin := false + for _, event := range ready { + if event.Fd == int32(poller.fd) { + if event.Events&unix.EPOLLHUP != 0 { + // This should not happen, but if it does, treat it as a wakeup. + epollhup = true + } + if event.Events&unix.EPOLLERR != 0 { + // If an error is waiting on the file descriptor, we should pretend + // something is ready to read, and let unix.Read pick up the error. + epollerr = true + } + if event.Events&unix.EPOLLIN != 0 { + // There is data to read. + epollin = true + } + } + if event.Fd == int32(poller.pipe[0]) { + if event.Events&unix.EPOLLHUP != 0 { + // Write pipe descriptor was closed, by us. This means we're closing down the + // watcher, and we should wake up. + } + if event.Events&unix.EPOLLERR != 0 { + // If an error is waiting on the pipe file descriptor. + // This is an absolute mystery, and should never ever happen. + return false, errors.New("Error on the pipe descriptor.") + } + if event.Events&unix.EPOLLIN != 0 { + // This is a regular wakeup, so we have to clear the buffer. + err := poller.clearWake() + if err != nil { + return false, err + } + } + } + } + + if epollhup || epollerr || epollin { + return true, nil + } + return false, nil + } +} + +// Close the write end of the poller. +func (poller *fdPoller) wake() error { + buf := make([]byte, 1) + n, errno := unix.Write(poller.pipe[1], buf) + if n == -1 { + if errno == unix.EAGAIN { + // Buffer is full, poller will wake. + return nil + } + return errno + } + return nil +} + +func (poller *fdPoller) clearWake() error { + // You have to be woken up a LOT in order to get to 100! + buf := make([]byte, 100) + n, errno := unix.Read(poller.pipe[0], buf) + if n == -1 { + if errno == unix.EAGAIN { + // Buffer is empty, someone else cleared our wake. + return nil + } + return errno + } + return nil +} + +// Close all poller file descriptors, but not the one passed to it. +func (poller *fdPoller) close() { + if poller.pipe[1] != -1 { + unix.Close(poller.pipe[1]) + } + if poller.pipe[0] != -1 { + unix.Close(poller.pipe[0]) + } + if poller.epfd != -1 { + unix.Close(poller.epfd) + } +} diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go new file mode 100644 index 000000000..368f5b790 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/kqueue.go @@ -0,0 +1,522 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build freebsd || openbsd || netbsd || dragonfly || darwin +// +build freebsd openbsd netbsd dragonfly darwin + +package fsnotify + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sync" + "time" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + + kq int // File descriptor (as returned by the kqueue() syscall). + + mu sync.Mutex // Protects access to watcher data + watches map[string]int // Map of watched file descriptors (key: path). + externalWatches map[string]bool // Map of watches added by user of the library. + dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. + paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. + fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). + isClosed bool // Set to true when Close() is first called +} + +type pathInfo struct { + name string + isDir bool +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + kq, err := kqueue() + if err != nil { + return nil, err + } + + w := &Watcher{ + kq: kq, + watches: make(map[string]int), + dirFlags: make(map[string]uint32), + paths: make(map[int]pathInfo), + fileExists: make(map[string]bool), + externalWatches: make(map[string]bool), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } + w.isClosed = true + + // copy paths to remove while locked + var pathsToRemove = make([]string, 0, len(w.watches)) + for name := range w.watches { + pathsToRemove = append(pathsToRemove, name) + } + w.mu.Unlock() + // unlock before calling Remove, which also locks + + for _, name := range pathsToRemove { + w.Remove(name) + } + + // send a "quit" message to the reader goroutine + close(w.done) + + return nil +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + w.mu.Lock() + w.externalWatches[name] = true + w.mu.Unlock() + _, err := w.addWatch(name, noteAllEvents) + return err +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + w.mu.Lock() + watchfd, ok := w.watches[name] + w.mu.Unlock() + if !ok { + return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) + } + + const registerRemove = unix.EV_DELETE + if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { + return err + } + + unix.Close(watchfd) + + w.mu.Lock() + isDir := w.paths[watchfd].isDir + delete(w.watches, name) + delete(w.paths, watchfd) + delete(w.dirFlags, name) + w.mu.Unlock() + + // Find all watched paths that are in this directory that are not external. + if isDir { + var pathsToRemove []string + w.mu.Lock() + for _, path := range w.paths { + wdir, _ := filepath.Split(path.name) + if filepath.Clean(wdir) == name { + if !w.externalWatches[path.name] { + pathsToRemove = append(pathsToRemove, path.name) + } + } + } + w.mu.Unlock() + for _, name := range pathsToRemove { + // Since these are internal, not much sense in propagating error + // to the user, as that will just confuse them with an error about + // a path they did not explicitly watch themselves. + w.Remove(name) + } + } + + return nil +} + +// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) +const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME + +// keventWaitTime to block on each read from kevent +var keventWaitTime = durationToTimespec(100 * time.Millisecond) + +// addWatch adds name to the watched file set. +// The flags are interpreted as described in kevent(2). +// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. +func (w *Watcher) addWatch(name string, flags uint32) (string, error) { + var isDir bool + // Make ./name and name equivalent + name = filepath.Clean(name) + + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return "", errors.New("kevent instance already closed") + } + watchfd, alreadyWatching := w.watches[name] + // We already have a watch, but we can still override flags. + if alreadyWatching { + isDir = w.paths[watchfd].isDir + } + w.mu.Unlock() + + if !alreadyWatching { + fi, err := os.Lstat(name) + if err != nil { + return "", err + } + + // Don't watch sockets. + if fi.Mode()&os.ModeSocket == os.ModeSocket { + return "", nil + } + + // Don't watch named pipes. + if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { + return "", nil + } + + // Follow Symlinks + // Unfortunately, Linux can add bogus symlinks to watch list without + // issue, and Windows can't do symlinks period (AFAIK). To maintain + // consistency, we will act like everything is fine. There will simply + // be no file events for broken symlinks. + // Hence the returns of nil on errors. + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + name, err = filepath.EvalSymlinks(name) + if err != nil { + return "", nil + } + + w.mu.Lock() + _, alreadyWatching = w.watches[name] + w.mu.Unlock() + + if alreadyWatching { + return name, nil + } + + fi, err = os.Lstat(name) + if err != nil { + return "", nil + } + } + + watchfd, err = unix.Open(name, openMode, 0700) + if watchfd == -1 { + return "", err + } + + isDir = fi.IsDir() + } + + const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE + if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { + unix.Close(watchfd) + return "", err + } + + if !alreadyWatching { + w.mu.Lock() + w.watches[name] = watchfd + w.paths[watchfd] = pathInfo{name: name, isDir: isDir} + w.mu.Unlock() + } + + if isDir { + // Watch the directory if it has not been watched before, + // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + w.mu.Lock() + + watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && + (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) + // Store flags so this watch can be updated later + w.dirFlags[name] = flags + w.mu.Unlock() + + if watchDir { + if err := w.watchDirectoryFiles(name); err != nil { + return "", err + } + } + } + return name, nil +} + +// readEvents reads from kqueue and converts the received kevents into +// Event values that it sends down the Events channel. +func (w *Watcher) readEvents() { + eventBuffer := make([]unix.Kevent_t, 10) + +loop: + for { + // See if there is a message on the "done" channel + select { + case <-w.done: + break loop + default: + } + + // Get new events + kevents, err := read(w.kq, eventBuffer, &keventWaitTime) + // EINTR is okay, the syscall was interrupted before timeout expired. + if err != nil && err != unix.EINTR { + select { + case w.Errors <- err: + case <-w.done: + break loop + } + continue + } + + // Flush the events we received to the Events channel + for len(kevents) > 0 { + kevent := &kevents[0] + watchfd := int(kevent.Ident) + mask := uint32(kevent.Fflags) + w.mu.Lock() + path := w.paths[watchfd] + w.mu.Unlock() + event := newEvent(path.name, mask) + + if path.isDir && !(event.Op&Remove == Remove) { + // Double check to make sure the directory exists. This can happen when + // we do a rm -fr on a recursively watched folders and we receive a + // modification event first but the folder has been deleted and later + // receive the delete event + if _, err := os.Lstat(event.Name); os.IsNotExist(err) { + // mark is as delete event + event.Op |= Remove + } + } + + if event.Op&Rename == Rename || event.Op&Remove == Remove { + w.Remove(event.Name) + w.mu.Lock() + delete(w.fileExists, event.Name) + w.mu.Unlock() + } + + if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { + w.sendDirectoryChangeEvents(event.Name) + } else { + // Send the event on the Events channel. + select { + case w.Events <- event: + case <-w.done: + break loop + } + } + + if event.Op&Remove == Remove { + // Look for a file that may have overwritten this. + // For example, mv f1 f2 will delete f2, then create f2. + if path.isDir { + fileDir := filepath.Clean(event.Name) + w.mu.Lock() + _, found := w.watches[fileDir] + w.mu.Unlock() + if found { + // make sure the directory exists before we watch for changes. When we + // do a recursive watch and perform rm -fr, the parent directory might + // have gone missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the parent directory. + if _, err := os.Lstat(fileDir); err == nil { + w.sendDirectoryChangeEvents(fileDir) + } + } + } else { + filePath := filepath.Clean(event.Name) + if fileInfo, err := os.Lstat(filePath); err == nil { + w.sendFileCreatedEventIfNew(filePath, fileInfo) + } + } + } + + // Move to next event + kevents = kevents[1:] + } + } + + // cleanup + err := unix.Close(w.kq) + if err != nil { + // only way the previous loop breaks is if w.done was closed so we need to async send to w.Errors. + select { + case w.Errors <- err: + default: + } + } + close(w.Events) + close(w.Errors) +} + +// newEvent returns an platform-independent Event based on kqueue Fflags. +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { + e.Op |= Remove + } + if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { + e.Op |= Write + } + if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { + e.Op |= Rename + } + if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { + e.Op |= Chmod + } + return e +} + +func newCreateEvent(name string) Event { + return Event{Name: name, Op: Create} +} + +// watchDirectoryFiles to mimic inotify when adding a watch on a directory +func (w *Watcher) watchDirectoryFiles(dirPath string) error { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + return err + } + + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + } + + return nil +} + +// sendDirectoryEvents searches the directory for newly created files +// and sends them over the event channel. This functionality is to have +// the BSD version of fsnotify match Linux inotify which provides a +// create event for files created in a watched directory. +func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + select { + case w.Errors <- err: + case <-w.done: + return + } + } + + // Search for new files + for _, fileInfo := range files { + filePath := filepath.Join(dirPath, fileInfo.Name()) + err := w.sendFileCreatedEventIfNew(filePath, fileInfo) + + if err != nil { + return + } + } +} + +// sendFileCreatedEvent sends a create event if the file isn't already being tracked. +func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { + w.mu.Lock() + _, doesExist := w.fileExists[filePath] + w.mu.Unlock() + if !doesExist { + // Send create event + select { + case w.Events <- newCreateEvent(filePath): + case <-w.done: + return + } + } + + // like watchDirectoryFiles (but without doing another ReadDir) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = true + w.mu.Unlock() + + return nil +} + +func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { + if fileInfo.IsDir() { + // mimic Linux providing delete events for subdirectories + // but preserve the flags used if currently watching subdirectory + w.mu.Lock() + flags := w.dirFlags[name] + w.mu.Unlock() + + flags |= unix.NOTE_DELETE | unix.NOTE_RENAME + return w.addWatch(name, flags) + } + + // watch file to mimic Linux inotify + return w.addWatch(name, noteAllEvents) +} + +// kqueue creates a new kernel event queue and returns a descriptor. +func kqueue() (kq int, err error) { + kq, err = unix.Kqueue() + if kq == -1 { + return kq, err + } + return kq, nil +} + +// register events with the queue +func register(kq int, fds []int, flags int, fflags uint32) error { + changes := make([]unix.Kevent_t, len(fds)) + + for i, fd := range fds { + // SetKevent converts int to the platform-specific types: + unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) + changes[i].Fflags = fflags + } + + // register the events + success, err := unix.Kevent(kq, changes, nil, nil) + if success == -1 { + return err + } + return nil +} + +// read retrieves pending events, or waits until an event occurs. +// A timeout of nil blocks indefinitely, while 0 polls the queue. +func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) { + n, err := unix.Kevent(kq, nil, events, timeout) + if err != nil { + return nil, err + } + return events[0:n], nil +} + +// durationToTimespec prepares a timeout value +func durationToTimespec(d time.Duration) unix.Timespec { + return unix.NsecToTimespec(d.Nanoseconds()) +} diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go new file mode 100644 index 000000000..36cc3845b --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build freebsd || openbsd || netbsd || dragonfly +// +build freebsd openbsd netbsd dragonfly + +package fsnotify + +import "golang.org/x/sys/unix" + +const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go new file mode 100644 index 000000000..98cd8476f --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go @@ -0,0 +1,13 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin +// +build darwin + +package fsnotify + +import "golang.org/x/sys/unix" + +// note: this constant is not defined on BSD +const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go new file mode 100644 index 000000000..c02b75f7c --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/windows.go @@ -0,0 +1,562 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows +// +build windows + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "sync" + "syscall" + "unsafe" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct { + Events chan Event + Errors chan error + isClosed bool // Set to true when Close() is first called + mu sync.Mutex // Map access + port syscall.Handle // Handle to completion port + watches watchMap // Map of watches (key: i-number) + input chan *input // Inputs to the reader are sent on this channel + quit chan chan<- error +} + +// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. +func NewWatcher() (*Watcher, error) { + port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) + if e != nil { + return nil, os.NewSyscallError("CreateIoCompletionPort", e) + } + w := &Watcher{ + port: port, + watches: make(watchMap), + input: make(chan *input, 1), + Events: make(chan Event, 50), + Errors: make(chan error), + quit: make(chan chan<- error, 1), + } + go w.readEvents() + return w, nil +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + if w.isClosed { + return nil + } + w.isClosed = true + + // Send "quit" message to the reader goroutine + ch := make(chan error) + w.quit <- ch + if err := w.wakeupReader(); err != nil { + return err + } + return <-ch +} + +// Add starts watching the named file or directory (non-recursively). +func (w *Watcher) Add(name string) error { + if w.isClosed { + return errors.New("watcher already closed") + } + in := &input{ + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +// Remove stops watching the the named file or directory (non-recursively). +func (w *Watcher) Remove(name string) error { + in := &input{ + op: opRemoveWatch, + path: filepath.Clean(name), + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +const ( + // Options for AddWatch + sysFSONESHOT = 0x80000000 + sysFSONLYDIR = 0x1000000 + + // Events + sysFSACCESS = 0x1 + sysFSALLEVENTS = 0xfff + sysFSATTRIB = 0x4 + sysFSCLOSE = 0x18 + sysFSCREATE = 0x100 + sysFSDELETE = 0x200 + sysFSDELETESELF = 0x400 + sysFSMODIFY = 0x2 + sysFSMOVE = 0xc0 + sysFSMOVEDFROM = 0x40 + sysFSMOVEDTO = 0x80 + sysFSMOVESELF = 0x800 + + // Special events + sysFSIGNORED = 0x8000 + sysFSQOVERFLOW = 0x4000 +) + +func newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { + e.Op |= Create + } + if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { + e.Op |= Remove + } + if mask&sysFSMODIFY == sysFSMODIFY { + e.Op |= Write + } + if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { + e.Op |= Rename + } + if mask&sysFSATTRIB == sysFSATTRIB { + e.Op |= Chmod + } + return e +} + +const ( + opAddWatch = iota + opRemoveWatch +) + +const ( + provisional uint64 = 1 << (32 + iota) +) + +type input struct { + op int + path string + flags uint32 + reply chan error +} + +type inode struct { + handle syscall.Handle + volume uint32 + index uint64 +} + +type watch struct { + ov syscall.Overlapped + ino *inode // i-number + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf [4096]byte +} + +type indexMap map[uint64]*watch +type watchMap map[uint32]indexMap + +func (w *Watcher) wakeupReader() error { + e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) + if e != nil { + return os.NewSyscallError("PostQueuedCompletionStatus", e) + } + return nil +} + +func getDir(pathname string) (dir string, err error) { + attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) + if e != nil { + return "", os.NewSyscallError("GetFileAttributes", e) + } + if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { + dir = pathname + } else { + dir, _ = filepath.Split(pathname) + dir = filepath.Clean(dir) + } + return +} + +func getIno(path string) (ino *inode, err error) { + h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), + syscall.FILE_LIST_DIRECTORY, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + nil, syscall.OPEN_EXISTING, + syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) + if e != nil { + return nil, os.NewSyscallError("CreateFile", e) + } + var fi syscall.ByHandleFileInformation + if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { + syscall.CloseHandle(h) + return nil, os.NewSyscallError("GetFileInformationByHandle", e) + } + ino = &inode{ + handle: h, + volume: fi.VolumeSerialNumber, + index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), + } + return ino, nil +} + +// Must run within the I/O thread. +func (m watchMap) get(ino *inode) *watch { + if i := m[ino.volume]; i != nil { + return i[ino.index] + } + return nil +} + +// Must run within the I/O thread. +func (m watchMap) set(ino *inode, watch *watch) { + i := m[ino.volume] + if i == nil { + i = make(indexMap) + m[ino.volume] = i + } + i[ino.index] = watch +} + +// Must run within the I/O thread. +func (w *Watcher) addWatch(pathname string, flags uint64) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + if flags&sysFSONLYDIR != 0 && pathname != dir { + return nil + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watchEntry := w.watches.get(ino) + w.mu.Unlock() + if watchEntry == nil { + if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { + syscall.CloseHandle(ino.handle) + return os.NewSyscallError("CreateIoCompletionPort", e) + } + watchEntry = &watch{ + ino: ino, + path: dir, + names: make(map[string]uint64), + } + w.mu.Lock() + w.watches.set(ino, watchEntry) + w.mu.Unlock() + flags |= provisional + } else { + syscall.CloseHandle(ino.handle) + } + if pathname == dir { + watchEntry.mask |= flags + } else { + watchEntry.names[filepath.Base(pathname)] |= flags + } + if err = w.startRead(watchEntry); err != nil { + return err + } + if pathname == dir { + watchEntry.mask &= ^provisional + } else { + watchEntry.names[filepath.Base(pathname)] &= ^provisional + } + return nil +} + +// Must run within the I/O thread. +func (w *Watcher) remWatch(pathname string) error { + dir, err := getDir(pathname) + if err != nil { + return err + } + ino, err := getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watch := w.watches.get(ino) + w.mu.Unlock() + if watch == nil { + return fmt.Errorf("can't remove non-existent watch for: %s", pathname) + } + if pathname == dir { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + watch.mask = 0 + } else { + name := filepath.Base(pathname) + w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + return w.startRead(watch) +} + +// Must run within the I/O thread. +func (w *Watcher) deleteWatch(watch *watch) { + for name, mask := range watch.names { + if mask&provisional == 0 { + w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) + } + delete(watch.names, name) + } + if watch.mask != 0 { + if watch.mask&provisional == 0 { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + } + watch.mask = 0 + } +} + +// Must run within the I/O thread. +func (w *Watcher) startRead(watch *watch) error { + if e := syscall.CancelIo(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CancelIo", e) + w.deleteWatch(watch) + } + mask := toWindowsFlags(watch.mask) + for _, m := range watch.names { + mask |= toWindowsFlags(m) + } + if mask == 0 { + if e := syscall.CloseHandle(watch.ino.handle); e != nil { + w.Errors <- os.NewSyscallError("CloseHandle", e) + } + w.mu.Lock() + delete(w.watches[watch.ino.volume], watch.ino.index) + w.mu.Unlock() + return nil + } + e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], + uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + if e != nil { + err := os.NewSyscallError("ReadDirectoryChanges", e) + if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { + // Watched directory was probably removed + if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) { + if watch.mask&sysFSONESHOT != 0 { + watch.mask = 0 + } + } + err = nil + } + w.deleteWatch(watch) + w.startRead(watch) + return err + } + return nil +} + +// readEvents reads from the I/O completion port, converts the +// received events into Event objects and sends them via the Events channel. +// Entry point to the I/O thread. +func (w *Watcher) readEvents() { + var ( + n, key uint32 + ov *syscall.Overlapped + ) + runtime.LockOSThread() + + for { + e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) + watch := (*watch)(unsafe.Pointer(ov)) + + if watch == nil { + select { + case ch := <-w.quit: + w.mu.Lock() + var indexes []indexMap + for _, index := range w.watches { + indexes = append(indexes, index) + } + w.mu.Unlock() + for _, index := range indexes { + for _, watch := range index { + w.deleteWatch(watch) + w.startRead(watch) + } + } + var err error + if e := syscall.CloseHandle(w.port); e != nil { + err = os.NewSyscallError("CloseHandle", e) + } + close(w.Events) + close(w.Errors) + ch <- err + return + case in := <-w.input: + switch in.op { + case opAddWatch: + in.reply <- w.addWatch(in.path, uint64(in.flags)) + case opRemoveWatch: + in.reply <- w.remWatch(in.path) + } + default: + } + continue + } + + switch e { + case syscall.ERROR_MORE_DATA: + if watch == nil { + w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") + } else { + // The i/o succeeded but the buffer is full. + // In theory we should be building up a full packet. + // In practice we can get away with just carrying on. + n = uint32(unsafe.Sizeof(watch.buf)) + } + case syscall.ERROR_ACCESS_DENIED: + // Watched directory was probably removed + w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.deleteWatch(watch) + w.startRead(watch) + continue + case syscall.ERROR_OPERATION_ABORTED: + // CancelIo was called on this handle + continue + default: + w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) + continue + case nil: + } + + var offset uint32 + for { + if n == 0 { + w.Events <- newEvent("", sysFSQOVERFLOW) + w.Errors <- errors.New("short read in readEvents()") + break + } + + // Point "raw" to the event in the buffer + raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) + buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName)) + name := syscall.UTF16ToString(buf[:raw.FileNameLength/2]) + fullname := filepath.Join(watch.path, name) + + var mask uint64 + switch raw.Action { + case syscall.FILE_ACTION_REMOVED: + mask = sysFSDELETESELF + case syscall.FILE_ACTION_MODIFIED: + mask = sysFSMODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + watch.rename = name + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + if watch.names[watch.rename] != 0 { + watch.names[name] |= watch.names[watch.rename] + delete(watch.names, watch.rename) + mask = sysFSMOVESELF + } + } + + sendNameEvent := func() { + if w.sendEvent(fullname, watch.names[name]&mask) { + if watch.names[name]&sysFSONESHOT != 0 { + delete(watch.names, name) + } + } + } + if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { + sendNameEvent() + } + if raw.Action == syscall.FILE_ACTION_REMOVED { + w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { + if watch.mask&sysFSONESHOT != 0 { + watch.mask = 0 + } + } + if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { + fullname = filepath.Join(watch.path, watch.rename) + sendNameEvent() + } + + // Move to the next event in the buffer + if raw.NextEntryOffset == 0 { + break + } + offset += raw.NextEntryOffset + + // Error! + if offset >= n { + w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") + break + } + } + + if err := w.startRead(watch); err != nil { + w.Errors <- err + } + } +} + +func (w *Watcher) sendEvent(name string, mask uint64) bool { + if mask == 0 { + return false + } + event := newEvent(name, uint32(mask)) + select { + case ch := <-w.quit: + w.quit <- ch + case w.Events <- event: + } + return true +} + +func toWindowsFlags(mask uint64) uint32 { + var m uint32 + if mask&sysFSACCESS != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS + } + if mask&sysFSMODIFY != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE + } + if mask&sysFSATTRIB != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES + } + if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { + m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME + } + return m +} + +func toFSnotifyFlags(action uint32) uint64 { + switch action { + case syscall.FILE_ACTION_ADDED: + return sysFSCREATE + case syscall.FILE_ACTION_REMOVED: + return sysFSDELETE + case syscall.FILE_ACTION_MODIFIED: + return sysFSMODIFY + case syscall.FILE_ACTION_RENAMED_OLD_NAME: + return sysFSMOVEDFROM + case syscall.FILE_ACTION_RENAMED_NEW_NAME: + return sysFSMOVEDTO + } + return 0 +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/decode.go b/vendor/github.com/golang/protobuf/jsonpb/decode.go new file mode 100644 index 000000000..60e82caa9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/decode.go @@ -0,0 +1,524 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package jsonpb + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/encoding/protojson" + protoV2 "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +const wrapJSONUnmarshalV2 = false + +// UnmarshalNext unmarshals the next JSON object from d into m. +func UnmarshalNext(d *json.Decoder, m proto.Message) error { + return new(Unmarshaler).UnmarshalNext(d, m) +} + +// Unmarshal unmarshals a JSON object from r into m. +func Unmarshal(r io.Reader, m proto.Message) error { + return new(Unmarshaler).Unmarshal(r, m) +} + +// UnmarshalString unmarshals a JSON object from s into m. +func UnmarshalString(s string, m proto.Message) error { + return new(Unmarshaler).Unmarshal(strings.NewReader(s), m) +} + +// Unmarshaler is a configurable object for converting from a JSON +// representation to a protocol buffer object. +type Unmarshaler struct { + // AllowUnknownFields specifies whether to allow messages to contain + // unknown JSON fields, as opposed to failing to unmarshal. + AllowUnknownFields bool + + // AnyResolver is used to resolve the google.protobuf.Any well-known type. + // If unset, the global registry is used by default. + AnyResolver AnyResolver +} + +// JSONPBUnmarshaler is implemented by protobuf messages that customize the way +// they are unmarshaled from JSON. Messages that implement this should also +// implement JSONPBMarshaler so that the custom format can be produced. +// +// The JSON unmarshaling must follow the JSON to proto specification: +// https://developers.google.com/protocol-buffers/docs/proto3#json +// +// Deprecated: Custom types should implement protobuf reflection instead. +type JSONPBUnmarshaler interface { + UnmarshalJSONPB(*Unmarshaler, []byte) error +} + +// Unmarshal unmarshals a JSON object from r into m. +func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error { + return u.UnmarshalNext(json.NewDecoder(r), m) +} + +// UnmarshalNext unmarshals the next JSON object from d into m. +func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error { + if m == nil { + return errors.New("invalid nil message") + } + + // Parse the next JSON object from the stream. + raw := json.RawMessage{} + if err := d.Decode(&raw); err != nil { + return err + } + + // Check for custom unmarshalers first since they may not properly + // implement protobuf reflection that the logic below relies on. + if jsu, ok := m.(JSONPBUnmarshaler); ok { + return jsu.UnmarshalJSONPB(u, raw) + } + + mr := proto.MessageReflect(m) + + // NOTE: For historical reasons, a top-level null is treated as a noop. + // This is incorrect, but kept for compatibility. + if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" { + return nil + } + + if wrapJSONUnmarshalV2 { + // NOTE: If input message is non-empty, we need to preserve merge semantics + // of the old jsonpb implementation. These semantics are not supported by + // the protobuf JSON specification. + isEmpty := true + mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { + isEmpty = false // at least one iteration implies non-empty + return false + }) + if !isEmpty { + // Perform unmarshaling into a newly allocated, empty message. + mr = mr.New() + + // Use a defer to copy all unmarshaled fields into the original message. + dst := proto.MessageReflect(m) + defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { + dst.Set(fd, v) + return true + }) + } + + // Unmarshal using the v2 JSON unmarshaler. + opts := protojson.UnmarshalOptions{ + DiscardUnknown: u.AllowUnknownFields, + } + if u.AnyResolver != nil { + opts.Resolver = anyResolver{u.AnyResolver} + } + return opts.Unmarshal(raw, mr.Interface()) + } else { + if err := u.unmarshalMessage(mr, raw); err != nil { + return err + } + return protoV2.CheckInitialized(mr.Interface()) + } +} + +func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error { + md := m.Descriptor() + fds := md.Fields() + + if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { + return jsu.UnmarshalJSONPB(u, in) + } + + if string(in) == "null" && md.FullName() != "google.protobuf.Value" { + return nil + } + + switch wellKnownType(md.FullName()) { + case "Any": + var jsonObject map[string]json.RawMessage + if err := json.Unmarshal(in, &jsonObject); err != nil { + return err + } + + rawTypeURL, ok := jsonObject["@type"] + if !ok { + return errors.New("Any JSON doesn't have '@type'") + } + typeURL, err := unquoteString(string(rawTypeURL)) + if err != nil { + return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL) + } + m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL)) + + var m2 protoreflect.Message + if u.AnyResolver != nil { + mi, err := u.AnyResolver.Resolve(typeURL) + if err != nil { + return err + } + m2 = proto.MessageReflect(mi) + } else { + mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) + if err != nil { + if err == protoregistry.NotFound { + return fmt.Errorf("could not resolve Any message type: %v", typeURL) + } + return err + } + m2 = mt.New() + } + + if wellKnownType(m2.Descriptor().FullName()) != "" { + rawValue, ok := jsonObject["value"] + if !ok { + return errors.New("Any JSON doesn't have 'value'") + } + if err := u.unmarshalMessage(m2, rawValue); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) + } + } else { + delete(jsonObject, "@type") + rawJSON, err := json.Marshal(jsonObject) + if err != nil { + return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) + } + if err = u.unmarshalMessage(m2, rawJSON); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) + } + } + + rawWire, err := protoV2.Marshal(m2.Interface()) + if err != nil { + return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err) + } + m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire)) + return nil + case "BoolValue", "BytesValue", "StringValue", + "Int32Value", "UInt32Value", "FloatValue", + "Int64Value", "UInt64Value", "DoubleValue": + fd := fds.ByNumber(1) + v, err := u.unmarshalValue(m.NewField(fd), in, fd) + if err != nil { + return err + } + m.Set(fd, v) + return nil + case "Duration": + v, err := unquoteString(string(in)) + if err != nil { + return err + } + d, err := time.ParseDuration(v) + if err != nil { + return fmt.Errorf("bad Duration: %v", err) + } + + sec := d.Nanoseconds() / 1e9 + nsec := d.Nanoseconds() % 1e9 + m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) + m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) + return nil + case "Timestamp": + v, err := unquoteString(string(in)) + if err != nil { + return err + } + t, err := time.Parse(time.RFC3339Nano, v) + if err != nil { + return fmt.Errorf("bad Timestamp: %v", err) + } + + sec := t.Unix() + nsec := t.Nanosecond() + m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) + m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) + return nil + case "Value": + switch { + case string(in) == "null": + m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0)) + case string(in) == "true": + m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true)) + case string(in) == "false": + m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false)) + case hasPrefixAndSuffix('"', in, '"'): + s, err := unquoteString(string(in)) + if err != nil { + return fmt.Errorf("unrecognized type for Value %q", in) + } + m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s)) + case hasPrefixAndSuffix('[', in, ']'): + v := m.Mutable(fds.ByNumber(6)) + return u.unmarshalMessage(v.Message(), in) + case hasPrefixAndSuffix('{', in, '}'): + v := m.Mutable(fds.ByNumber(5)) + return u.unmarshalMessage(v.Message(), in) + default: + f, err := strconv.ParseFloat(string(in), 0) + if err != nil { + return fmt.Errorf("unrecognized type for Value %q", in) + } + m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f)) + } + return nil + case "ListValue": + var jsonArray []json.RawMessage + if err := json.Unmarshal(in, &jsonArray); err != nil { + return fmt.Errorf("bad ListValue: %v", err) + } + + lv := m.Mutable(fds.ByNumber(1)).List() + for _, raw := range jsonArray { + ve := lv.NewElement() + if err := u.unmarshalMessage(ve.Message(), raw); err != nil { + return err + } + lv.Append(ve) + } + return nil + case "Struct": + var jsonObject map[string]json.RawMessage + if err := json.Unmarshal(in, &jsonObject); err != nil { + return fmt.Errorf("bad StructValue: %v", err) + } + + mv := m.Mutable(fds.ByNumber(1)).Map() + for key, raw := range jsonObject { + kv := protoreflect.ValueOf(key).MapKey() + vv := mv.NewValue() + if err := u.unmarshalMessage(vv.Message(), raw); err != nil { + return fmt.Errorf("bad value in StructValue for key %q: %v", key, err) + } + mv.Set(kv, vv) + } + return nil + } + + var jsonObject map[string]json.RawMessage + if err := json.Unmarshal(in, &jsonObject); err != nil { + return err + } + + // Handle known fields. + for i := 0; i < fds.Len(); i++ { + fd := fds.Get(i) + if fd.IsWeak() && fd.Message().IsPlaceholder() { + continue // weak reference is not linked in + } + + // Search for any raw JSON value associated with this field. + var raw json.RawMessage + name := string(fd.Name()) + if fd.Kind() == protoreflect.GroupKind { + name = string(fd.Message().Name()) + } + if v, ok := jsonObject[name]; ok { + delete(jsonObject, name) + raw = v + } + name = string(fd.JSONName()) + if v, ok := jsonObject[name]; ok { + delete(jsonObject, name) + raw = v + } + + field := m.NewField(fd) + // Unmarshal the field value. + if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { + continue + } + v, err := u.unmarshalValue(field, raw, fd) + if err != nil { + return err + } + m.Set(fd, v) + } + + // Handle extension fields. + for name, raw := range jsonObject { + if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") { + continue + } + + // Resolve the extension field by name. + xname := protoreflect.FullName(name[len("[") : len(name)-len("]")]) + xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname) + if xt == nil && isMessageSet(md) { + xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension")) + } + if xt == nil { + continue + } + delete(jsonObject, name) + fd := xt.TypeDescriptor() + if fd.ContainingMessage().FullName() != m.Descriptor().FullName() { + return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) + } + + field := m.NewField(fd) + // Unmarshal the field value. + if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { + continue + } + v, err := u.unmarshalValue(field, raw, fd) + if err != nil { + return err + } + m.Set(fd, v) + } + + if !u.AllowUnknownFields && len(jsonObject) > 0 { + for name := range jsonObject { + return fmt.Errorf("unknown field %q in %v", name, md.FullName()) + } + } + return nil +} + +func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { + if md := fd.Message(); md != nil { + return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated + } + return false +} + +func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { + if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { + _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) + return ok + } + return false +} + +func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { + switch { + case fd.IsList(): + var jsonArray []json.RawMessage + if err := json.Unmarshal(in, &jsonArray); err != nil { + return v, err + } + lv := v.List() + for _, raw := range jsonArray { + ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd) + if err != nil { + return v, err + } + lv.Append(ve) + } + return v, nil + case fd.IsMap(): + var jsonObject map[string]json.RawMessage + if err := json.Unmarshal(in, &jsonObject); err != nil { + return v, err + } + kfd := fd.MapKey() + vfd := fd.MapValue() + mv := v.Map() + for key, raw := range jsonObject { + var kv protoreflect.MapKey + if kfd.Kind() == protoreflect.StringKind { + kv = protoreflect.ValueOf(key).MapKey() + } else { + v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd) + if err != nil { + return v, err + } + kv = v.MapKey() + } + + vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd) + if err != nil { + return v, err + } + mv.Set(kv, vv) + } + return v, nil + default: + return u.unmarshalSingularValue(v, in, fd) + } +} + +var nonFinite = map[string]float64{ + `"NaN"`: math.NaN(), + `"Infinity"`: math.Inf(+1), + `"-Infinity"`: math.Inf(-1), +} + +func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { + switch fd.Kind() { + case protoreflect.BoolKind: + return unmarshalValue(in, new(bool)) + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + return unmarshalValue(trimQuote(in), new(int32)) + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + return unmarshalValue(trimQuote(in), new(int64)) + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + return unmarshalValue(trimQuote(in), new(uint32)) + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + return unmarshalValue(trimQuote(in), new(uint64)) + case protoreflect.FloatKind: + if f, ok := nonFinite[string(in)]; ok { + return protoreflect.ValueOfFloat32(float32(f)), nil + } + return unmarshalValue(trimQuote(in), new(float32)) + case protoreflect.DoubleKind: + if f, ok := nonFinite[string(in)]; ok { + return protoreflect.ValueOfFloat64(float64(f)), nil + } + return unmarshalValue(trimQuote(in), new(float64)) + case protoreflect.StringKind: + return unmarshalValue(in, new(string)) + case protoreflect.BytesKind: + return unmarshalValue(in, new([]byte)) + case protoreflect.EnumKind: + if hasPrefixAndSuffix('"', in, '"') { + vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in))) + if vd == nil { + return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName()) + } + return protoreflect.ValueOfEnum(vd.Number()), nil + } + return unmarshalValue(in, new(protoreflect.EnumNumber)) + case protoreflect.MessageKind, protoreflect.GroupKind: + err := u.unmarshalMessage(v.Message(), in) + return v, err + default: + panic(fmt.Sprintf("invalid kind %v", fd.Kind())) + } +} + +func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) { + err := json.Unmarshal(in, v) + return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err +} + +func unquoteString(in string) (out string, err error) { + err = json.Unmarshal([]byte(in), &out) + return out, err +} + +func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool { + if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix { + return true + } + return false +} + +// trimQuote is like unquoteString but simply strips surrounding quotes. +// This is incorrect, but is behavior done by the legacy implementation. +func trimQuote(in []byte) []byte { + if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' { + in = in[1 : len(in)-1] + } + return in +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/encode.go b/vendor/github.com/golang/protobuf/jsonpb/encode.go new file mode 100644 index 000000000..685c80a62 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/encode.go @@ -0,0 +1,559 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package jsonpb + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/encoding/protojson" + protoV2 "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" +) + +const wrapJSONMarshalV2 = false + +// Marshaler is a configurable object for marshaling protocol buffer messages +// to the specified JSON representation. +type Marshaler struct { + // OrigName specifies whether to use the original protobuf name for fields. + OrigName bool + + // EnumsAsInts specifies whether to render enum values as integers, + // as opposed to string values. + EnumsAsInts bool + + // EmitDefaults specifies whether to render fields with zero values. + EmitDefaults bool + + // Indent controls whether the output is compact or not. + // If empty, the output is compact JSON. Otherwise, every JSON object + // entry and JSON array value will be on its own line. + // Each line will be preceded by repeated copies of Indent, where the + // number of copies is the current indentation depth. + Indent string + + // AnyResolver is used to resolve the google.protobuf.Any well-known type. + // If unset, the global registry is used by default. + AnyResolver AnyResolver +} + +// JSONPBMarshaler is implemented by protobuf messages that customize the +// way they are marshaled to JSON. Messages that implement this should also +// implement JSONPBUnmarshaler so that the custom format can be parsed. +// +// The JSON marshaling must follow the proto to JSON specification: +// https://developers.google.com/protocol-buffers/docs/proto3#json +// +// Deprecated: Custom types should implement protobuf reflection instead. +type JSONPBMarshaler interface { + MarshalJSONPB(*Marshaler) ([]byte, error) +} + +// Marshal serializes a protobuf message as JSON into w. +func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error { + b, err := jm.marshal(m) + if len(b) > 0 { + if _, err := w.Write(b); err != nil { + return err + } + } + return err +} + +// MarshalToString serializes a protobuf message as JSON in string form. +func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) { + b, err := jm.marshal(m) + if err != nil { + return "", err + } + return string(b), nil +} + +func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) { + v := reflect.ValueOf(m) + if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { + return nil, errors.New("Marshal called with nil") + } + + // Check for custom marshalers first since they may not properly + // implement protobuf reflection that the logic below relies on. + if jsm, ok := m.(JSONPBMarshaler); ok { + return jsm.MarshalJSONPB(jm) + } + + if wrapJSONMarshalV2 { + opts := protojson.MarshalOptions{ + UseProtoNames: jm.OrigName, + UseEnumNumbers: jm.EnumsAsInts, + EmitUnpopulated: jm.EmitDefaults, + Indent: jm.Indent, + } + if jm.AnyResolver != nil { + opts.Resolver = anyResolver{jm.AnyResolver} + } + return opts.Marshal(proto.MessageReflect(m).Interface()) + } else { + // Check for unpopulated required fields first. + m2 := proto.MessageReflect(m) + if err := protoV2.CheckInitialized(m2.Interface()); err != nil { + return nil, err + } + + w := jsonWriter{Marshaler: jm} + err := w.marshalMessage(m2, "", "") + return w.buf, err + } +} + +type jsonWriter struct { + *Marshaler + buf []byte +} + +func (w *jsonWriter) write(s string) { + w.buf = append(w.buf, s...) +} + +func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error { + if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok { + b, err := jsm.MarshalJSONPB(w.Marshaler) + if err != nil { + return err + } + if typeURL != "" { + // we are marshaling this object to an Any type + var js map[string]*json.RawMessage + if err = json.Unmarshal(b, &js); err != nil { + return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err) + } + turl, err := json.Marshal(typeURL) + if err != nil { + return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) + } + js["@type"] = (*json.RawMessage)(&turl) + if b, err = json.Marshal(js); err != nil { + return err + } + } + w.write(string(b)) + return nil + } + + md := m.Descriptor() + fds := md.Fields() + + // Handle well-known types. + const secondInNanos = int64(time.Second / time.Nanosecond) + switch wellKnownType(md.FullName()) { + case "Any": + return w.marshalAny(m, indent) + case "BoolValue", "BytesValue", "StringValue", + "Int32Value", "UInt32Value", "FloatValue", + "Int64Value", "UInt64Value", "DoubleValue": + fd := fds.ByNumber(1) + return w.marshalValue(fd, m.Get(fd), indent) + case "Duration": + const maxSecondsInDuration = 315576000000 + // "Generated output always contains 0, 3, 6, or 9 fractional digits, + // depending on required precision." + s := m.Get(fds.ByNumber(1)).Int() + ns := m.Get(fds.ByNumber(2)).Int() + if s < -maxSecondsInDuration || s > maxSecondsInDuration { + return fmt.Errorf("seconds out of range %v", s) + } + if ns <= -secondInNanos || ns >= secondInNanos { + return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) + } + if (s > 0 && ns < 0) || (s < 0 && ns > 0) { + return errors.New("signs of seconds and nanos do not match") + } + var sign string + if s < 0 || ns < 0 { + sign, s, ns = "-", -1*s, -1*ns + } + x := fmt.Sprintf("%s%d.%09d", sign, s, ns) + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + w.write(fmt.Sprintf(`"%vs"`, x)) + return nil + case "Timestamp": + // "RFC 3339, where generated output will always be Z-normalized + // and uses 0, 3, 6 or 9 fractional digits." + s := m.Get(fds.ByNumber(1)).Int() + ns := m.Get(fds.ByNumber(2)).Int() + if ns < 0 || ns >= secondInNanos { + return fmt.Errorf("ns out of range [0, %v)", secondInNanos) + } + t := time.Unix(s, ns).UTC() + // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). + x := t.Format("2006-01-02T15:04:05.000000000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, ".000") + w.write(fmt.Sprintf(`"%vZ"`, x)) + return nil + case "Value": + // JSON value; which is a null, number, string, bool, object, or array. + od := md.Oneofs().Get(0) + fd := m.WhichOneof(od) + if fd == nil { + return errors.New("nil Value") + } + return w.marshalValue(fd, m.Get(fd), indent) + case "Struct", "ListValue": + // JSON object or array. + fd := fds.ByNumber(1) + return w.marshalValue(fd, m.Get(fd), indent) + } + + w.write("{") + if w.Indent != "" { + w.write("\n") + } + + firstField := true + if typeURL != "" { + if err := w.marshalTypeURL(indent, typeURL); err != nil { + return err + } + firstField = false + } + + for i := 0; i < fds.Len(); { + fd := fds.Get(i) + if od := fd.ContainingOneof(); od != nil { + fd = m.WhichOneof(od) + i += od.Fields().Len() + if fd == nil { + continue + } + } else { + i++ + } + + v := m.Get(fd) + + if !m.Has(fd) { + if !w.EmitDefaults || fd.ContainingOneof() != nil { + continue + } + if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) { + v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars + } + } + + if !firstField { + w.writeComma() + } + if err := w.marshalField(fd, v, indent); err != nil { + return err + } + firstField = false + } + + // Handle proto2 extensions. + if md.ExtensionRanges().Len() > 0 { + // Collect a sorted list of all extension descriptor and values. + type ext struct { + desc protoreflect.FieldDescriptor + val protoreflect.Value + } + var exts []ext + m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { + if fd.IsExtension() { + exts = append(exts, ext{fd, v}) + } + return true + }) + sort.Slice(exts, func(i, j int) bool { + return exts[i].desc.Number() < exts[j].desc.Number() + }) + + for _, ext := range exts { + if !firstField { + w.writeComma() + } + if err := w.marshalField(ext.desc, ext.val, indent); err != nil { + return err + } + firstField = false + } + } + + if w.Indent != "" { + w.write("\n") + w.write(indent) + } + w.write("}") + return nil +} + +func (w *jsonWriter) writeComma() { + if w.Indent != "" { + w.write(",\n") + } else { + w.write(",") + } +} + +func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error { + // "If the Any contains a value that has a special JSON mapping, + // it will be converted as follows: {"@type": xxx, "value": yyy}. + // Otherwise, the value will be converted into a JSON object, + // and the "@type" field will be inserted to indicate the actual data type." + md := m.Descriptor() + typeURL := m.Get(md.Fields().ByNumber(1)).String() + rawVal := m.Get(md.Fields().ByNumber(2)).Bytes() + + var m2 protoreflect.Message + if w.AnyResolver != nil { + mi, err := w.AnyResolver.Resolve(typeURL) + if err != nil { + return err + } + m2 = proto.MessageReflect(mi) + } else { + mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) + if err != nil { + return err + } + m2 = mt.New() + } + + if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil { + return err + } + + if wellKnownType(m2.Descriptor().FullName()) == "" { + return w.marshalMessage(m2, indent, typeURL) + } + + w.write("{") + if w.Indent != "" { + w.write("\n") + } + if err := w.marshalTypeURL(indent, typeURL); err != nil { + return err + } + w.writeComma() + if w.Indent != "" { + w.write(indent) + w.write(w.Indent) + w.write(`"value": `) + } else { + w.write(`"value":`) + } + if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil { + return err + } + if w.Indent != "" { + w.write("\n") + w.write(indent) + } + w.write("}") + return nil +} + +func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error { + if w.Indent != "" { + w.write(indent) + w.write(w.Indent) + } + w.write(`"@type":`) + if w.Indent != "" { + w.write(" ") + } + b, err := json.Marshal(typeURL) + if err != nil { + return err + } + w.write(string(b)) + return nil +} + +// marshalField writes field description and value to the Writer. +func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { + if w.Indent != "" { + w.write(indent) + w.write(w.Indent) + } + w.write(`"`) + switch { + case fd.IsExtension(): + // For message set, use the fname of the message as the extension name. + name := string(fd.FullName()) + if isMessageSet(fd.ContainingMessage()) { + name = strings.TrimSuffix(name, ".message_set_extension") + } + + w.write("[" + name + "]") + case w.OrigName: + name := string(fd.Name()) + if fd.Kind() == protoreflect.GroupKind { + name = string(fd.Message().Name()) + } + w.write(name) + default: + w.write(string(fd.JSONName())) + } + w.write(`":`) + if w.Indent != "" { + w.write(" ") + } + return w.marshalValue(fd, v, indent) +} + +func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { + switch { + case fd.IsList(): + w.write("[") + comma := "" + lv := v.List() + for i := 0; i < lv.Len(); i++ { + w.write(comma) + if w.Indent != "" { + w.write("\n") + w.write(indent) + w.write(w.Indent) + w.write(w.Indent) + } + if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil { + return err + } + comma = "," + } + if w.Indent != "" { + w.write("\n") + w.write(indent) + w.write(w.Indent) + } + w.write("]") + return nil + case fd.IsMap(): + kfd := fd.MapKey() + vfd := fd.MapValue() + mv := v.Map() + + // Collect a sorted list of all map keys and values. + type entry struct{ key, val protoreflect.Value } + var entries []entry + mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { + entries = append(entries, entry{k.Value(), v}) + return true + }) + sort.Slice(entries, func(i, j int) bool { + switch kfd.Kind() { + case protoreflect.BoolKind: + return !entries[i].key.Bool() && entries[j].key.Bool() + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + return entries[i].key.Int() < entries[j].key.Int() + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + return entries[i].key.Uint() < entries[j].key.Uint() + case protoreflect.StringKind: + return entries[i].key.String() < entries[j].key.String() + default: + panic("invalid kind") + } + }) + + w.write(`{`) + comma := "" + for _, entry := range entries { + w.write(comma) + if w.Indent != "" { + w.write("\n") + w.write(indent) + w.write(w.Indent) + w.write(w.Indent) + } + + s := fmt.Sprint(entry.key.Interface()) + b, err := json.Marshal(s) + if err != nil { + return err + } + w.write(string(b)) + + w.write(`:`) + if w.Indent != "" { + w.write(` `) + } + + if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil { + return err + } + comma = "," + } + if w.Indent != "" { + w.write("\n") + w.write(indent) + w.write(w.Indent) + } + w.write(`}`) + return nil + default: + return w.marshalSingularValue(fd, v, indent) + } +} + +func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { + switch { + case !v.IsValid(): + w.write("null") + return nil + case fd.Message() != nil: + return w.marshalMessage(v.Message(), indent+w.Indent, "") + case fd.Enum() != nil: + if fd.Enum().FullName() == "google.protobuf.NullValue" { + w.write("null") + return nil + } + + vd := fd.Enum().Values().ByNumber(v.Enum()) + if vd == nil || w.EnumsAsInts { + w.write(strconv.Itoa(int(v.Enum()))) + } else { + w.write(`"` + string(vd.Name()) + `"`) + } + return nil + default: + switch v.Interface().(type) { + case float32, float64: + switch { + case math.IsInf(v.Float(), +1): + w.write(`"Infinity"`) + return nil + case math.IsInf(v.Float(), -1): + w.write(`"-Infinity"`) + return nil + case math.IsNaN(v.Float()): + w.write(`"NaN"`) + return nil + } + case int64, uint64: + w.write(fmt.Sprintf(`"%d"`, v.Interface())) + return nil + } + + b, err := json.Marshal(v.Interface()) + if err != nil { + return err + } + w.write(string(b)) + return nil + } +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/json.go b/vendor/github.com/golang/protobuf/jsonpb/json.go new file mode 100644 index 000000000..480e2448d --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/json.go @@ -0,0 +1,69 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package jsonpb provides functionality to marshal and unmarshal between a +// protocol buffer message and JSON. It follows the specification at +// https://developers.google.com/protocol-buffers/docs/proto3#json. +// +// Do not rely on the default behavior of the standard encoding/json package +// when called on generated message types as it does not operate correctly. +// +// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson" +// package instead. +package jsonpb + +import ( + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + "google.golang.org/protobuf/runtime/protoimpl" +) + +// AnyResolver takes a type URL, present in an Any message, +// and resolves it into an instance of the associated message. +type AnyResolver interface { + Resolve(typeURL string) (proto.Message, error) +} + +type anyResolver struct{ AnyResolver } + +func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { + return r.FindMessageByURL(string(message)) +} + +func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) { + m, err := r.Resolve(url) + if err != nil { + return nil, err + } + return protoimpl.X.MessageTypeOf(m), nil +} + +func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { + return protoregistry.GlobalTypes.FindExtensionByName(field) +} + +func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { + return protoregistry.GlobalTypes.FindExtensionByNumber(message, field) +} + +func wellKnownType(s protoreflect.FullName) string { + if s.Parent() == "google.protobuf" { + switch s.Name() { + case "Empty", "Any", + "BoolValue", "BytesValue", "StringValue", + "Int32Value", "UInt32Value", "FloatValue", + "Int64Value", "UInt64Value", "DoubleValue", + "Duration", "Timestamp", + "NullValue", "Struct", "Value", "ListValue": + return string(s.Name()) + } + } + return "" +} + +func isMessageSet(md protoreflect.MessageDescriptor) bool { + ms, ok := md.(interface{ IsMessageSet() bool }) + return ok && ms.IsMessageSet() +} diff --git a/vendor/github.com/golang/protobuf/proto/registry.go b/vendor/github.com/golang/protobuf/proto/registry.go index 1e7ff6420..066b4323b 100644 --- a/vendor/github.com/golang/protobuf/proto/registry.go +++ b/vendor/github.com/golang/protobuf/proto/registry.go @@ -13,6 +13,7 @@ import ( "strings" "sync" + "google.golang.org/protobuf/reflect/protodesc" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/runtime/protoimpl" @@ -62,14 +63,7 @@ func FileDescriptor(s filePath) fileDescGZIP { // Find the descriptor in the v2 registry. var b []byte if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil { - if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok { - b = fd.ProtoLegacyRawDesc() - } else { - // TODO: Use protodesc.ToFileDescriptorProto to construct - // a descriptorpb.FileDescriptorProto and marshal it. - // However, doing so causes the proto package to have a dependency - // on descriptorpb, leading to cyclic dependency issues. - } + b, _ = Marshal(protodesc.ToFileDescriptorProto(fd)) } // Locally cache the raw descriptor form for the file. diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go index e729dcff1..85f9f5736 100644 --- a/vendor/github.com/golang/protobuf/ptypes/any.go +++ b/vendor/github.com/golang/protobuf/ptypes/any.go @@ -19,6 +19,8 @@ const urlPrefix = "type.googleapis.com/" // AnyMessageName returns the message name contained in an anypb.Any message. // Most type assertions should use the Is function instead. +// +// Deprecated: Call the any.MessageName method instead. func AnyMessageName(any *anypb.Any) (string, error) { name, err := anyMessageName(any) return string(name), err @@ -38,6 +40,8 @@ func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) { } // MarshalAny marshals the given message m into an anypb.Any message. +// +// Deprecated: Call the anypb.New function instead. func MarshalAny(m proto.Message) (*anypb.Any, error) { switch dm := m.(type) { case DynamicAny: @@ -58,6 +62,9 @@ func MarshalAny(m proto.Message) (*anypb.Any, error) { // Empty returns a new message of the type specified in an anypb.Any message. // It returns protoregistry.NotFound if the corresponding message type could not // be resolved in the global registry. +// +// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead +// to resolve the message name and create a new instance of it. func Empty(any *anypb.Any) (proto.Message, error) { name, err := anyMessageName(any) if err != nil { @@ -76,6 +83,8 @@ func Empty(any *anypb.Any) (proto.Message, error) { // // The target message m may be a *DynamicAny message. If the underlying message // type could not be resolved, then this returns protoregistry.NotFound. +// +// Deprecated: Call the any.UnmarshalTo method instead. func UnmarshalAny(any *anypb.Any, m proto.Message) error { if dm, ok := m.(*DynamicAny); ok { if dm.Message == nil { @@ -100,6 +109,8 @@ func UnmarshalAny(any *anypb.Any, m proto.Message) error { } // Is reports whether the Any message contains a message of the specified type. +// +// Deprecated: Call the any.MessageIs method instead. func Is(any *anypb.Any, m proto.Message) bool { if any == nil || m == nil { return false @@ -119,6 +130,9 @@ func Is(any *anypb.Any, m proto.Message) bool { // var x ptypes.DynamicAny // if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } // fmt.Printf("unmarshaled message: %v", x.Message) +// +// Deprecated: Use the any.UnmarshalNew method instead to unmarshal +// the any message contents into a new instance of the underlying message. type DynamicAny struct{ proto.Message } func (m DynamicAny) String() string { diff --git a/vendor/github.com/golang/protobuf/ptypes/doc.go b/vendor/github.com/golang/protobuf/ptypes/doc.go index fb9edd5c6..d3c33259d 100644 --- a/vendor/github.com/golang/protobuf/ptypes/doc.go +++ b/vendor/github.com/golang/protobuf/ptypes/doc.go @@ -3,4 +3,8 @@ // license that can be found in the LICENSE file. // Package ptypes provides functionality for interacting with well-known types. +// +// Deprecated: Well-known types have specialized functionality directly +// injected into the generated packages for each message type. +// See the deprecation notice for each function for the suggested alternative. package ptypes diff --git a/vendor/github.com/golang/protobuf/ptypes/duration.go b/vendor/github.com/golang/protobuf/ptypes/duration.go index 6110ae8a4..b2b55dd85 100644 --- a/vendor/github.com/golang/protobuf/ptypes/duration.go +++ b/vendor/github.com/golang/protobuf/ptypes/duration.go @@ -21,6 +21,8 @@ const ( // Duration converts a durationpb.Duration to a time.Duration. // Duration returns an error if dur is invalid or overflows a time.Duration. +// +// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead. func Duration(dur *durationpb.Duration) (time.Duration, error) { if err := validateDuration(dur); err != nil { return 0, err @@ -39,6 +41,8 @@ func Duration(dur *durationpb.Duration) (time.Duration, error) { } // DurationProto converts a time.Duration to a durationpb.Duration. +// +// Deprecated: Call the durationpb.New function instead. func DurationProto(d time.Duration) *durationpb.Duration { nanos := d.Nanoseconds() secs := nanos / 1e9 diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp.go b/vendor/github.com/golang/protobuf/ptypes/timestamp.go index 026d0d491..8368a3f70 100644 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp.go +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp.go @@ -33,6 +33,8 @@ const ( // // A nil Timestamp returns an error. The first return value in that case is // undefined. +// +// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead. func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { // Don't return the zero value on error, because corresponds to a valid // timestamp. Instead return whatever time.Unix gives us. @@ -46,6 +48,8 @@ func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { } // TimestampNow returns a google.protobuf.Timestamp for the current time. +// +// Deprecated: Call the timestamppb.Now function instead. func TimestampNow() *timestamppb.Timestamp { ts, err := TimestampProto(time.Now()) if err != nil { @@ -56,6 +60,8 @@ func TimestampNow() *timestamppb.Timestamp { // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. // It returns an error if the resulting Timestamp is invalid. +// +// Deprecated: Call the timestamppb.New function instead. func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { ts := ×tamppb.Timestamp{ Seconds: t.Unix(), @@ -69,6 +75,9 @@ func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { // TimestampString returns the RFC 3339 string for valid Timestamps. // For invalid Timestamps, it returns an error message in parentheses. +// +// Deprecated: Call the ts.AsTime method instead, +// followed by a call to the Format method on the time.Time value. func TimestampString(ts *timestamppb.Timestamp) string { t, err := Timestamp(ts) if err != nil { diff --git a/vendor/github.com/golang/snappy/decode_arm64.s b/vendor/github.com/golang/snappy/decode_arm64.s index bfafa0ccf..7a3ead17e 100644 --- a/vendor/github.com/golang/snappy/decode_arm64.s +++ b/vendor/github.com/golang/snappy/decode_arm64.s @@ -70,7 +70,7 @@ loop: // x := uint32(src[s] >> 2) // switch MOVW $60, R1 - ADD R4>>2, ZR, R4 + LSRW $2, R4, R4 CMPW R4, R1 BLS tagLit60Plus @@ -111,13 +111,12 @@ doLit: // is contiguous in memory and so it needs to leave enough source bytes to // read the next tag without refilling buffers, but Go's Decode assumes // contiguousness (the src argument is a []byte). - MOVD $16, R1 - CMP R1, R4 - BGT callMemmove - CMP R1, R2 - BLT callMemmove - CMP R1, R3 - BLT callMemmove + CMP $16, R4 + BGT callMemmove + CMP $16, R2 + BLT callMemmove + CMP $16, R3 + BLT callMemmove // !!! Implement the copy from src to dst as a 16-byte load and store. // (Decode's documentation says that dst and src must not overlap.) @@ -130,9 +129,8 @@ doLit: // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or // 16-byte loads and stores. This technique probably wouldn't be as // effective on architectures that are fussier about alignment. - - VLD1 0(R6), [V0.B16] - VST1 [V0.B16], 0(R7) + LDP 0(R6), (R14, R15) + STP (R14, R15), 0(R7) // d += length // s += length @@ -210,8 +208,7 @@ tagLit61: B doLit tagLit62Plus: - MOVW $62, R1 - CMPW R1, R4 + CMPW $62, R4 BHI tagLit63 // case x == 62: @@ -273,10 +270,9 @@ tagCopy: // We have a copy tag. We assume that: // - R3 == src[s] & 0x03 // - R4 == src[s] - MOVD $2, R1 - CMP R1, R3 - BEQ tagCopy2 - BGT tagCopy4 + CMP $2, R3 + BEQ tagCopy2 + BGT tagCopy4 // case tagCopy1: // s += 2 @@ -346,13 +342,11 @@ doCopy: // } // copy 16 bytes // d += length - MOVD $16, R1 - MOVD $8, R0 - CMP R1, R4 + CMP $16, R4 BGT slowForwardCopy - CMP R0, R5 + CMP $8, R5 BLT slowForwardCopy - CMP R1, R14 + CMP $16, R14 BLT slowForwardCopy MOVD 0(R15), R2 MOVD R2, 0(R7) @@ -426,8 +420,7 @@ makeOffsetAtLeast8: // // The two previous lines together means that d-offset, and therefore // // R15, is unchanged. // } - MOVD $8, R1 - CMP R1, R5 + CMP $8, R5 BGE fixUpSlowForwardCopy MOVD (R15), R3 MOVD R3, (R7) @@ -477,9 +470,7 @@ verySlowForwardCopy: ADD $1, R15, R15 ADD $1, R7, R7 SUB $1, R4, R4 - MOVD $0, R1 - CMP R1, R4 - BNE verySlowForwardCopy + CBNZ R4, verySlowForwardCopy B loop // The code above handles copy tags. diff --git a/vendor/github.com/golang/snappy/encode_arm64.s b/vendor/github.com/golang/snappy/encode_arm64.s index 1f565ee75..bf83667d7 100644 --- a/vendor/github.com/golang/snappy/encode_arm64.s +++ b/vendor/github.com/golang/snappy/encode_arm64.s @@ -35,11 +35,9 @@ TEXT ·emitLiteral(SB), NOSPLIT, $32-56 MOVW R3, R4 SUBW $1, R4, R4 - MOVW $60, R2 - CMPW R2, R4 + CMPW $60, R4 BLT oneByte - MOVW $256, R2 - CMPW R2, R4 + CMPW $256, R4 BLT twoBytes threeBytes: @@ -98,8 +96,7 @@ TEXT ·emitCopy(SB), NOSPLIT, $0-48 loop0: // for length >= 68 { etc } - MOVW $68, R2 - CMPW R2, R3 + CMPW $68, R3 BLT step1 // Emit a length 64 copy, encoded as 3 bytes. @@ -112,9 +109,8 @@ loop0: step1: // if length > 64 { etc } - MOVD $64, R2 - CMP R2, R3 - BLE step2 + CMP $64, R3 + BLE step2 // Emit a length 60 copy, encoded as 3 bytes. MOVD $0xee, R2 @@ -125,11 +121,9 @@ step1: step2: // if length >= 12 || offset >= 2048 { goto step3 } - MOVD $12, R2 - CMP R2, R3 + CMP $12, R3 BGE step3 - MOVW $2048, R2 - CMPW R2, R11 + CMPW $2048, R11 BGE step3 // Emit the remaining copy, encoded as 2 bytes. @@ -295,27 +289,24 @@ varTable: // var table [maxTableSize]uint16 // // In the asm code, unlike the Go code, we can zero-initialize only the - // first tableSize elements. Each uint16 element is 2 bytes and each VST1 - // writes 64 bytes, so we can do only tableSize/32 writes instead of the - // 2048 writes that would zero-initialize all of table's 32768 bytes. - // This clear could overrun the first tableSize elements, but it won't - // overrun the allocated stack size. + // first tableSize elements. Each uint16 element is 2 bytes and each + // iterations writes 64 bytes, so we can do only tableSize/32 writes + // instead of the 2048 writes that would zero-initialize all of table's + // 32768 bytes. This clear could overrun the first tableSize elements, but + // it won't overrun the allocated stack size. ADD $128, RSP, R17 MOVD R17, R4 // !!! R6 = &src[tableSize] ADD R6<<1, R17, R6 - // zero the SIMD registers - VEOR V0.B16, V0.B16, V0.B16 - VEOR V1.B16, V1.B16, V1.B16 - VEOR V2.B16, V2.B16, V2.B16 - VEOR V3.B16, V3.B16, V3.B16 - memclr: - VST1.P [V0.B16, V1.B16, V2.B16, V3.B16], 64(R4) - CMP R4, R6 - BHI memclr + STP.P (ZR, ZR), 64(R4) + STP (ZR, ZR), -48(R4) + STP (ZR, ZR), -32(R4) + STP (ZR, ZR), -16(R4) + CMP R4, R6 + BHI memclr // !!! R6 = &src[0] MOVD R7, R6 @@ -404,8 +395,7 @@ fourByteMatch: // on inputMargin in encode.go. MOVD R7, R3 SUB R10, R3, R3 - MOVD $16, R2 - CMP R2, R3 + CMP $16, R3 BLE emitLiteralFastPath // ---------------------------------------- @@ -454,18 +444,21 @@ inlineEmitLiteralMemmove: MOVD R3, 24(RSP) // Finish the "d +=" part of "d += emitLiteral(etc)". - ADD R3, R8, R8 - MOVD R7, 80(RSP) - MOVD R8, 88(RSP) - MOVD R15, 120(RSP) - CALL runtime·memmove(SB) - MOVD 64(RSP), R5 - MOVD 72(RSP), R6 - MOVD 80(RSP), R7 - MOVD 88(RSP), R8 - MOVD 96(RSP), R9 - MOVD 120(RSP), R15 - B inner1 + ADD R3, R8, R8 + MOVD R7, 80(RSP) + MOVD R8, 88(RSP) + MOVD R15, 120(RSP) + CALL runtime·memmove(SB) + MOVD 64(RSP), R5 + MOVD 72(RSP), R6 + MOVD 80(RSP), R7 + MOVD 88(RSP), R8 + MOVD 96(RSP), R9 + MOVD 120(RSP), R15 + ADD $128, RSP, R17 + MOVW $0xa7bd, R16 + MOVKW $(0x1e35<<16), R16 + B inner1 inlineEmitLiteralEnd: // End inline of the emitLiteral call. @@ -489,9 +482,9 @@ emitLiteralFastPath: // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or // 16-byte loads and stores. This technique probably wouldn't be as // effective on architectures that are fussier about alignment. - VLD1 0(R10), [V0.B16] - VST1 [V0.B16], 0(R8) - ADD R3, R8, R8 + LDP 0(R10), (R0, R1) + STP (R0, R1), 0(R8) + ADD R3, R8, R8 inner1: // for { etc } diff --git a/vendor/github.com/google/uuid/.travis.yml b/vendor/github.com/google/uuid/.travis.yml new file mode 100644 index 000000000..d8156a60b --- /dev/null +++ b/vendor/github.com/google/uuid/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4.3 + - 1.5.3 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md new file mode 100644 index 000000000..04fdf09f1 --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# How to contribute + +We definitely welcome patches and contribution to this project! + +### Legal requirements + +In order to protect both you and ourselves, you will need to sign the +[Contributor License Agreement](https://cla.developers.google.com/clas). + +You may have already signed it for other Google projects. diff --git a/vendor/github.com/google/uuid/CONTRIBUTORS b/vendor/github.com/google/uuid/CONTRIBUTORS new file mode 100644 index 000000000..b4bb97f6b --- /dev/null +++ b/vendor/github.com/google/uuid/CONTRIBUTORS @@ -0,0 +1,9 @@ +Paul Borman +bmatsuo +shawnps +theory +jboverfelt +dsymonds +cd1 +wallclockbuilder +dansouza diff --git a/vendor/github.com/google/uuid/LICENSE b/vendor/github.com/google/uuid/LICENSE new file mode 100644 index 000000000..5dc68268d --- /dev/null +++ b/vendor/github.com/google/uuid/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md new file mode 100644 index 000000000..f765a46f9 --- /dev/null +++ b/vendor/github.com/google/uuid/README.md @@ -0,0 +1,19 @@ +# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) +The uuid package generates and inspects UUIDs based on +[RFC 4122](http://tools.ietf.org/html/rfc4122) +and DCE 1.1: Authentication and Security Services. + +This package is based on the github.com/pborman/uuid package (previously named +code.google.com/p/go-uuid). It differs from these earlier packages in that +a UUID is a 16 byte array rather than a byte slice. One loss due to this +change is the ability to represent an invalid UUID (vs a NIL UUID). + +###### Install +`go get github.com/google/uuid` + +###### Documentation +[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) + +Full `go doc` style documentation for the package can be viewed online without +installing this package by using the GoDoc site here: +http://pkg.go.dev/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go new file mode 100644 index 000000000..fa820b9d3 --- /dev/null +++ b/vendor/github.com/google/uuid/dce.go @@ -0,0 +1,80 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "fmt" + "os" +) + +// A Domain represents a Version 2 domain +type Domain byte + +// Domain constants for DCE Security (Version 2) UUIDs. +const ( + Person = Domain(0) + Group = Domain(1) + Org = Domain(2) +) + +// NewDCESecurity returns a DCE Security (Version 2) UUID. +// +// The domain should be one of Person, Group or Org. +// On a POSIX system the id should be the users UID for the Person +// domain and the users GID for the Group. The meaning of id for +// the domain Org or on non-POSIX systems is site defined. +// +// For a given domain/id pair the same token may be returned for up to +// 7 minutes and 10 seconds. +func NewDCESecurity(domain Domain, id uint32) (UUID, error) { + uuid, err := NewUUID() + if err == nil { + uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 + uuid[9] = byte(domain) + binary.BigEndian.PutUint32(uuid[0:], id) + } + return uuid, err +} + +// NewDCEPerson returns a DCE Security (Version 2) UUID in the person +// domain with the id returned by os.Getuid. +// +// NewDCESecurity(Person, uint32(os.Getuid())) +func NewDCEPerson() (UUID, error) { + return NewDCESecurity(Person, uint32(os.Getuid())) +} + +// NewDCEGroup returns a DCE Security (Version 2) UUID in the group +// domain with the id returned by os.Getgid. +// +// NewDCESecurity(Group, uint32(os.Getgid())) +func NewDCEGroup() (UUID, error) { + return NewDCESecurity(Group, uint32(os.Getgid())) +} + +// Domain returns the domain for a Version 2 UUID. Domains are only defined +// for Version 2 UUIDs. +func (uuid UUID) Domain() Domain { + return Domain(uuid[9]) +} + +// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2 +// UUIDs. +func (uuid UUID) ID() uint32 { + return binary.BigEndian.Uint32(uuid[0:4]) +} + +func (d Domain) String() string { + switch d { + case Person: + return "Person" + case Group: + return "Group" + case Org: + return "Org" + } + return fmt.Sprintf("Domain%d", int(d)) +} diff --git a/vendor/github.com/google/uuid/doc.go b/vendor/github.com/google/uuid/doc.go new file mode 100644 index 000000000..5b8a4b9af --- /dev/null +++ b/vendor/github.com/google/uuid/doc.go @@ -0,0 +1,12 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package uuid generates and inspects UUIDs. +// +// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security +// Services. +// +// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to +// maps or compared directly. +package uuid diff --git a/vendor/github.com/google/uuid/go.mod b/vendor/github.com/google/uuid/go.mod new file mode 100644 index 000000000..fc84cd79d --- /dev/null +++ b/vendor/github.com/google/uuid/go.mod @@ -0,0 +1 @@ +module github.com/google/uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go new file mode 100644 index 000000000..b404f4bec --- /dev/null +++ b/vendor/github.com/google/uuid/hash.go @@ -0,0 +1,53 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "crypto/md5" + "crypto/sha1" + "hash" +) + +// Well known namespace IDs and UUIDs +var ( + NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) + Nil UUID // empty UUID, all zeros +) + +// NewHash returns a new UUID derived from the hash of space concatenated with +// data generated by h. The hash should be at least 16 byte in length. The +// first 16 bytes of the hash are used to form the UUID. The version of the +// UUID will be the lower 4 bits of version. NewHash is used to implement +// NewMD5 and NewSHA1. +func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { + h.Reset() + h.Write(space[:]) //nolint:errcheck + h.Write(data) //nolint:errcheck + s := h.Sum(nil) + var uuid UUID + copy(uuid[:], s) + uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) + uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant + return uuid +} + +// NewMD5 returns a new MD5 (Version 3) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(md5.New(), space, data, 3) +func NewMD5(space UUID, data []byte) UUID { + return NewHash(md5.New(), space, data, 3) +} + +// NewSHA1 returns a new SHA1 (Version 5) UUID based on the +// supplied name space and data. It is the same as calling: +// +// NewHash(sha1.New(), space, data, 5) +func NewSHA1(space UUID, data []byte) UUID { + return NewHash(sha1.New(), space, data, 5) +} diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go new file mode 100644 index 000000000..14bd34072 --- /dev/null +++ b/vendor/github.com/google/uuid/marshal.go @@ -0,0 +1,38 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "fmt" + +// MarshalText implements encoding.TextMarshaler. +func (uuid UUID) MarshalText() ([]byte, error) { + var js [36]byte + encodeHex(js[:], uuid) + return js[:], nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (uuid *UUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + return err + } + *uuid = id + return nil +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (uuid UUID) MarshalBinary() ([]byte, error) { + return uuid[:], nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (uuid *UUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(uuid[:], data) + return nil +} diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go new file mode 100644 index 000000000..d651a2b06 --- /dev/null +++ b/vendor/github.com/google/uuid/node.go @@ -0,0 +1,90 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "sync" +) + +var ( + nodeMu sync.Mutex + ifname string // name of interface being used + nodeID [6]byte // hardware for version 1 UUIDs + zeroID [6]byte // nodeID with only 0's +) + +// NodeInterface returns the name of the interface from which the NodeID was +// derived. The interface "user" is returned if the NodeID was set by +// SetNodeID. +func NodeInterface() string { + defer nodeMu.Unlock() + nodeMu.Lock() + return ifname +} + +// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. +// If name is "" then the first usable interface found will be used or a random +// Node ID will be generated. If a named interface cannot be found then false +// is returned. +// +// SetNodeInterface never fails when name is "". +func SetNodeInterface(name string) bool { + defer nodeMu.Unlock() + nodeMu.Lock() + return setNodeInterface(name) +} + +func setNodeInterface(name string) bool { + iname, addr := getHardwareInterface(name) // null implementation for js + if iname != "" && addr != nil { + ifname = iname + copy(nodeID[:], addr) + return true + } + + // We found no interfaces with a valid hardware address. If name + // does not specify a specific interface generate a random Node ID + // (section 4.1.6) + if name == "" { + ifname = "random" + randomBits(nodeID[:]) + return true + } + return false +} + +// NodeID returns a slice of a copy of the current Node ID, setting the Node ID +// if not already set. +func NodeID() []byte { + defer nodeMu.Unlock() + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + nid := nodeID + return nid[:] +} + +// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes +// of id are used. If id is less than 6 bytes then false is returned and the +// Node ID is not set. +func SetNodeID(id []byte) bool { + if len(id) < 6 { + return false + } + defer nodeMu.Unlock() + nodeMu.Lock() + copy(nodeID[:], id) + ifname = "user" + return true +} + +// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is +// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) NodeID() []byte { + var node [6]byte + copy(node[:], uuid[10:]) + return node[:] +} diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go new file mode 100644 index 000000000..24b78edc9 --- /dev/null +++ b/vendor/github.com/google/uuid/node_js.go @@ -0,0 +1,12 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build js + +package uuid + +// getHardwareInterface returns nil values for the JS version of the code. +// This remvoves the "net" dependency, because it is not used in the browser. +// Using the "net" library inflates the size of the transpiled JS code by 673k bytes. +func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go new file mode 100644 index 000000000..0cbbcddbd --- /dev/null +++ b/vendor/github.com/google/uuid/node_net.go @@ -0,0 +1,33 @@ +// Copyright 2017 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js + +package uuid + +import "net" + +var interfaces []net.Interface // cached list of interfaces + +// getHardwareInterface returns the name and hardware address of interface name. +// If name is "" then the name and hardware address of one of the system's +// interfaces is returned. If no interfaces are found (name does not exist or +// there are no interfaces) then "", nil is returned. +// +// Only addresses of at least 6 bytes are returned. +func getHardwareInterface(name string) (string, []byte) { + if interfaces == nil { + var err error + interfaces, err = net.Interfaces() + if err != nil { + return "", nil + } + } + for _, ifs := range interfaces { + if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { + return ifs.Name, ifs.HardwareAddr + } + } + return "", nil +} diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go new file mode 100644 index 000000000..d7fcbf286 --- /dev/null +++ b/vendor/github.com/google/uuid/null.go @@ -0,0 +1,118 @@ +// Copyright 2021 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +var jsonNull = []byte("null") + +// NullUUID represents a UUID that may be null. +// NullUUID implements the SQL driver.Scanner interface so +// it can be used as a scan destination: +// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } +// +type NullUUID struct { + UUID UUID + Valid bool // Valid is true if UUID is not NULL +} + +// Scan implements the SQL driver.Scanner interface. +func (nu *NullUUID) Scan(value interface{}) error { + if value == nil { + nu.UUID, nu.Valid = Nil, false + return nil + } + + err := nu.UUID.Scan(value) + if err != nil { + nu.Valid = false + return err + } + + nu.Valid = true + return nil +} + +// Value implements the driver Valuer interface. +func (nu NullUUID) Value() (driver.Value, error) { + if !nu.Valid { + return nil, nil + } + // Delegate to UUID Value function + return nu.UUID.Value() +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (nu NullUUID) MarshalBinary() ([]byte, error) { + if nu.Valid { + return nu.UUID[:], nil + } + + return []byte(nil), nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (nu *NullUUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(nu.UUID[:], data) + nu.Valid = true + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (nu NullUUID) MarshalText() ([]byte, error) { + if nu.Valid { + return nu.UUID.MarshalText() + } + + return jsonNull, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (nu *NullUUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + nu.Valid = false + return err + } + nu.UUID = id + nu.Valid = true + return nil +} + +// MarshalJSON implements json.Marshaler. +func (nu NullUUID) MarshalJSON() ([]byte, error) { + if nu.Valid { + return json.Marshal(nu.UUID) + } + + return jsonNull, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (nu *NullUUID) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, jsonNull) { + *nu = NullUUID{} + return nil // valid null UUID + } + err := json.Unmarshal(data, &nu.UUID) + nu.Valid = err == nil + return err +} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go new file mode 100644 index 000000000..2e02ec06c --- /dev/null +++ b/vendor/github.com/google/uuid/sql.go @@ -0,0 +1,59 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements sql.Scanner so UUIDs can be read from databases transparently. +// Currently, database types that map to string and []byte are supported. Please +// consult database-specific driver documentation for matching types. +func (uuid *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case nil: + return nil + + case string: + // if an empty UUID comes from a table, we return a null UUID + if src == "" { + return nil + } + + // see Parse for required string format + u, err := Parse(src) + if err != nil { + return fmt.Errorf("Scan: %v", err) + } + + *uuid = u + + case []byte: + // if an empty UUID comes from a table, we return a null UUID + if len(src) == 0 { + return nil + } + + // assumes a simple slice of bytes if 16 bytes + // otherwise attempts to parse + if len(src) != 16 { + return uuid.Scan(string(src)) + } + copy((*uuid)[:], src) + + default: + return fmt.Errorf("Scan: unable to scan type %T into UUID", src) + } + + return nil +} + +// Value implements sql.Valuer so that UUIDs can be written to databases +// transparently. Currently, UUIDs map to strings. Please consult +// database-specific driver documentation for matching types. +func (uuid UUID) Value() (driver.Value, error) { + return uuid.String(), nil +} diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go new file mode 100644 index 000000000..e6ef06cdc --- /dev/null +++ b/vendor/github.com/google/uuid/time.go @@ -0,0 +1,123 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" + "sync" + "time" +) + +// A Time represents a time as the number of 100's of nanoseconds since 15 Oct +// 1582. +type Time int64 + +const ( + lillian = 2299160 // Julian day of 15 Oct 1582 + unix = 2440587 // Julian day of 1 Jan 1970 + epoch = unix - lillian // Days between epochs + g1582 = epoch * 86400 // seconds between epochs + g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs +) + +var ( + timeMu sync.Mutex + lasttime uint64 // last time we returned + clockSeq uint16 // clock sequence for this run + + timeNow = time.Now // for testing +) + +// UnixTime converts t the number of seconds and nanoseconds using the Unix +// epoch of 1 Jan 1970. +func (t Time) UnixTime() (sec, nsec int64) { + sec = int64(t - g1582ns100) + nsec = (sec % 10000000) * 100 + sec /= 10000000 + return sec, nsec +} + +// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and +// clock sequence as well as adjusting the clock sequence as needed. An error +// is returned if the current time cannot be determined. +func GetTime() (Time, uint16, error) { + defer timeMu.Unlock() + timeMu.Lock() + return getTime() +} + +func getTime() (Time, uint16, error) { + t := timeNow() + + // If we don't have a clock sequence already, set one. + if clockSeq == 0 { + setClockSequence(-1) + } + now := uint64(t.UnixNano()/100) + g1582ns100 + + // If time has gone backwards with this clock sequence then we + // increment the clock sequence + if now <= lasttime { + clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 + } + lasttime = now + return Time(now), clockSeq, nil +} + +// ClockSequence returns the current clock sequence, generating one if not +// already set. The clock sequence is only used for Version 1 UUIDs. +// +// The uuid package does not use global static storage for the clock sequence or +// the last time a UUID was generated. Unless SetClockSequence is used, a new +// random clock sequence is generated the first time a clock sequence is +// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) +func ClockSequence() int { + defer timeMu.Unlock() + timeMu.Lock() + return clockSequence() +} + +func clockSequence() int { + if clockSeq == 0 { + setClockSequence(-1) + } + return int(clockSeq & 0x3fff) +} + +// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to +// -1 causes a new sequence to be generated. +func SetClockSequence(seq int) { + defer timeMu.Unlock() + timeMu.Lock() + setClockSequence(seq) +} + +func setClockSequence(seq int) { + if seq == -1 { + var b [2]byte + randomBits(b[:]) // clock sequence + seq = int(b[0])<<8 | int(b[1]) + } + oldSeq := clockSeq + clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant + if oldSeq != clockSeq { + lasttime = 0 + } +} + +// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in +// uuid. The time is only defined for version 1 and 2 UUIDs. +func (uuid UUID) Time() Time { + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + return Time(time) +} + +// ClockSequence returns the clock sequence encoded in uuid. +// The clock sequence is only well defined for version 1 and 2 UUIDs. +func (uuid UUID) ClockSequence() int { + return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff +} diff --git a/vendor/github.com/google/uuid/util.go b/vendor/github.com/google/uuid/util.go new file mode 100644 index 000000000..5ea6c7378 --- /dev/null +++ b/vendor/github.com/google/uuid/util.go @@ -0,0 +1,43 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// randomBits completely fills slice b with random data. +func randomBits(b []byte) { + if _, err := io.ReadFull(rander, b); err != nil { + panic(err.Error()) // rand should never fail + } +} + +// xvalues returns the value of a byte as a hexadecimal digit or 255. +var xvalues = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +} + +// xtob converts hex characters x1 and x2 into a byte. +func xtob(x1, x2 byte) (byte, bool) { + b1 := xvalues[x1] + b2 := xvalues[x2] + return (b1 << 4) | b2, b1 != 255 && b2 != 255 +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go new file mode 100644 index 000000000..a57207aeb --- /dev/null +++ b/vendor/github.com/google/uuid/uuid.go @@ -0,0 +1,294 @@ +// Copyright 2018 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "strings" + "sync" +) + +// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC +// 4122. +type UUID [16]byte + +// A Version represents a UUID's version. +type Version byte + +// A Variant represents a UUID's variant. +type Variant byte + +// Constants returned by Variant. +const ( + Invalid = Variant(iota) // Invalid UUID + RFC4122 // The variant specified in RFC4122 + Reserved // Reserved, NCS backward compatibility. + Microsoft // Reserved, Microsoft Corporation backward compatibility. + Future // Reserved for future definition. +) + +const randPoolSize = 16 * 16 + +var ( + rander = rand.Reader // random function + poolEnabled = false + poolMu sync.Mutex + poolPos = randPoolSize // protected with poolMu + pool [randPoolSize]byte // protected with poolMu +) + +type invalidLengthError struct{ len int } + +func (err invalidLengthError) Error() string { + return fmt.Sprintf("invalid UUID length: %d", err.len) +} + +// IsInvalidLengthError is matcher function for custom error invalidLengthError +func IsInvalidLengthError(err error) bool { + _, ok := err.(invalidLengthError) + return ok +} + +// Parse decodes s into a UUID or returns an error. Both the standard UUID +// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the +// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex +// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. +func Parse(s string) (UUID, error) { + var uuid UUID + switch len(s) { + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36: + + // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: + if strings.ToLower(s[:9]) != "urn:uuid:" { + return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + case 36 + 2: + s = s[1:] + + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + case 32: + var ok bool + for i := range uuid { + uuid[i], ok = xtob(s[i*2], s[i*2+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, invalidLengthError{len(s)} + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + v, ok := xtob(s[x], s[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// ParseBytes is like Parse, except it parses a byte slice instead of a string. +func ParseBytes(b []byte) (UUID, error) { + var uuid UUID + switch len(b) { + case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { + return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) + } + b = b[9:] + case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} + b = b[1:] + case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + var ok bool + for i := 0; i < 32; i += 2 { + uuid[i/2], ok = xtob(b[i], b[i+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + } + return uuid, nil + default: + return uuid, invalidLengthError{len(b)} + } + // s is now at least 36 bytes long + // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { + return uuid, errors.New("invalid UUID format") + } + for i, x := range [16]int{ + 0, 2, 4, 6, + 9, 11, + 14, 16, + 19, 21, + 24, 26, 28, 30, 32, 34} { + v, ok := xtob(b[x], b[x+1]) + if !ok { + return uuid, errors.New("invalid UUID format") + } + uuid[i] = v + } + return uuid, nil +} + +// MustParse is like Parse but panics if the string cannot be parsed. +// It simplifies safe initialization of global variables holding compiled UUIDs. +func MustParse(s string) UUID { + uuid, err := Parse(s) + if err != nil { + panic(`uuid: Parse(` + s + `): ` + err.Error()) + } + return uuid +} + +// FromBytes creates a new UUID from a byte slice. Returns an error if the slice +// does not have a length of 16. The bytes are copied from the slice. +func FromBytes(b []byte) (uuid UUID, err error) { + err = uuid.UnmarshalBinary(b) + return uuid, err +} + +// Must returns uuid if err is nil and panics otherwise. +func Must(uuid UUID, err error) UUID { + if err != nil { + panic(err) + } + return uuid +} + +// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// , or "" if uuid is invalid. +func (uuid UUID) String() string { + var buf [36]byte + encodeHex(buf[:], uuid) + return string(buf[:]) +} + +// URN returns the RFC 2141 URN form of uuid, +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. +func (uuid UUID) URN() string { + var buf [36 + 9]byte + copy(buf[:], "urn:uuid:") + encodeHex(buf[9:], uuid) + return string(buf[:]) +} + +func encodeHex(dst []byte, uuid UUID) { + hex.Encode(dst, uuid[:4]) + dst[8] = '-' + hex.Encode(dst[9:13], uuid[4:6]) + dst[13] = '-' + hex.Encode(dst[14:18], uuid[6:8]) + dst[18] = '-' + hex.Encode(dst[19:23], uuid[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], uuid[10:]) +} + +// Variant returns the variant encoded in uuid. +func (uuid UUID) Variant() Variant { + switch { + case (uuid[8] & 0xc0) == 0x80: + return RFC4122 + case (uuid[8] & 0xe0) == 0xc0: + return Microsoft + case (uuid[8] & 0xe0) == 0xe0: + return Future + default: + return Reserved + } +} + +// Version returns the version of uuid. +func (uuid UUID) Version() Version { + return Version(uuid[6] >> 4) +} + +func (v Version) String() string { + if v > 15 { + return fmt.Sprintf("BAD_VERSION_%d", v) + } + return fmt.Sprintf("VERSION_%d", v) +} + +func (v Variant) String() string { + switch v { + case RFC4122: + return "RFC4122" + case Reserved: + return "Reserved" + case Microsoft: + return "Microsoft" + case Future: + return "Future" + case Invalid: + return "Invalid" + } + return fmt.Sprintf("BadVariant%d", int(v)) +} + +// SetRand sets the random number generator to r, which implements io.Reader. +// If r.Read returns an error when the package requests random data then +// a panic will be issued. +// +// Calling SetRand with nil sets the random number generator to the default +// generator. +func SetRand(r io.Reader) { + if r == nil { + rander = rand.Reader + return + } + rander = r +} + +// EnableRandPool enables internal randomness pool used for Random +// (Version 4) UUID generation. The pool contains random bytes read from +// the random number generator on demand in batches. Enabling the pool +// may improve the UUID generation throughput significantly. +// +// Since the pool is stored on the Go heap, this feature may be a bad fit +// for security sensitive applications. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func EnableRandPool() { + poolEnabled = true +} + +// DisableRandPool disables the randomness pool if it was previously +// enabled with EnableRandPool. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func DisableRandPool() { + poolEnabled = false + defer poolMu.Unlock() + poolMu.Lock() + poolPos = randPoolSize +} diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go new file mode 100644 index 000000000..463109629 --- /dev/null +++ b/vendor/github.com/google/uuid/version1.go @@ -0,0 +1,44 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "encoding/binary" +) + +// NewUUID returns a Version 1 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewUUID returns nil. If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewUUID returns nil and an error. +// +// In most cases, New should be used. +func NewUUID() (UUID, error) { + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + timeLow := uint32(now & 0xffffffff) + timeMid := uint16((now >> 32) & 0xffff) + timeHi := uint16((now >> 48) & 0x0fff) + timeHi |= 0x1000 // Version 1 + + binary.BigEndian.PutUint32(uuid[0:], timeLow) + binary.BigEndian.PutUint16(uuid[4:], timeMid) + binary.BigEndian.PutUint16(uuid[6:], timeHi) + binary.BigEndian.PutUint16(uuid[8:], seq) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go new file mode 100644 index 000000000..7697802e4 --- /dev/null +++ b/vendor/github.com/google/uuid/version4.go @@ -0,0 +1,76 @@ +// Copyright 2016 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "io" + +// New creates a new random UUID or panics. New is equivalent to +// the expression +// +// uuid.Must(uuid.NewRandom()) +func New() UUID { + return Must(NewRandom()) +} + +// NewString creates a new random UUID and returns it as a string or panics. +// NewString is equivalent to the expression +// +// uuid.New().String() +func NewString() string { + return Must(NewRandom()).String() +} + +// NewRandom returns a Random (Version 4) UUID. +// +// The strength of the UUIDs is based on the strength of the crypto/rand +// package. +// +// Uses the randomness pool if it was enabled with EnableRandPool. +// +// A note about uniqueness derived from the UUID Wikipedia entry: +// +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. +func NewRandom() (UUID, error) { + if !poolEnabled { + return NewRandomFromReader(rander) + } + return newRandomFromPool() +} + +// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. +func NewRandomFromReader(r io.Reader) (UUID, error) { + var uuid UUID + _, err := io.ReadFull(r, uuid[:]) + if err != nil { + return Nil, err + } + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} + +func newRandomFromPool() (UUID, error) { + var uuid UUID + poolMu.Lock() + if poolPos == randPoolSize { + _, err := io.ReadFull(rander, pool[:]) + if err != nil { + poolMu.Unlock() + return Nil, err + } + poolPos = 0 + } + copy(uuid[:], pool[poolPos:(poolPos+16)]) + poolPos += 16 + poolMu.Unlock() + + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/hashicorp/consul/api/acl.go b/vendor/github.com/hashicorp/consul/api/acl.go index 7453feb8a..0f44494dd 100644 --- a/vendor/github.com/hashicorp/consul/api/acl.go +++ b/vendor/github.com/hashicorp/consul/api/acl.go @@ -52,12 +52,21 @@ type ACLToken struct { // Namespace is the namespace the ACLToken is associated with. // Namespaces are a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLToken is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // AuthMethodNamespace is the namespace the token's AuthMethod is associated with. + // Namespacing is a Consul Enterprise feature. + AuthMethodNamespace string `json:",omitempty"` } type ACLTokenListEntry struct { CreateIndex uint64 ModifyIndex uint64 AccessorID string + SecretID string Description string Policies []*ACLTokenPolicyLink `json:",omitempty"` Roles []*ACLTokenRoleLink `json:",omitempty"` @@ -73,6 +82,14 @@ type ACLTokenListEntry struct { // Namespace is the namespace the ACLTokenListEntry is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLTokenListEntry is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // AuthMethodNamespace is the namespace the token's AuthMethod is associated with. + // Namespacing is a Consul Enterprise feature. + AuthMethodNamespace string `json:",omitempty"` } // ACLEntry is used to represent a legacy ACL token @@ -97,6 +114,7 @@ type ACLReplicationStatus struct { ReplicatedTokenIndex uint64 LastSuccess time.Time LastError time.Time + LastErrorMessage string } // ACLServiceIdentity represents a high-level grant of all necessary privileges @@ -128,6 +146,10 @@ type ACLPolicy struct { // Namespace is the namespace the ACLPolicy is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLPolicy is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } type ACLPolicyListEntry struct { @@ -142,6 +164,10 @@ type ACLPolicyListEntry struct { // Namespace is the namespace the ACLPolicyListEntry is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLPolicyListEntry is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } type ACLRolePolicyLink = ACLLink @@ -161,6 +187,10 @@ type ACLRole struct { // Namespace is the namespace the ACLRole is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLRole is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } // BindingRuleBindType is the type of binding rule mechanism used. @@ -188,6 +218,10 @@ type ACLBindingRule struct { // Namespace is the namespace the ACLBindingRule is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLBindingRule is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } type ACLAuthMethod struct { @@ -216,6 +250,10 @@ type ACLAuthMethod struct { // Namespace is the namespace the ACLAuthMethod is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLAuthMethod is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } func (m *ACLAuthMethod) MarshalJSON() ([]byte, error) { @@ -270,14 +308,63 @@ type ACLAuthMethodNamespaceRule struct { type ACLAuthMethodListEntry struct { Name string Type string - DisplayName string `json:",omitempty"` - Description string `json:",omitempty"` - CreateIndex uint64 - ModifyIndex uint64 + DisplayName string `json:",omitempty"` + Description string `json:",omitempty"` + MaxTokenTTL time.Duration `json:",omitempty"` + + // TokenLocality defines the kind of token that this auth method produces. + // This can be either 'local' or 'global'. If empty 'local' is assumed. + TokenLocality string `json:",omitempty"` + CreateIndex uint64 + ModifyIndex uint64 // Namespace is the namespace the ACLAuthMethodListEntry is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the ACLAuthMethodListEntry is associated with. + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` +} + +// This is nearly identical to the ACLAuthMethod MarshalJSON +func (m *ACLAuthMethodListEntry) MarshalJSON() ([]byte, error) { + type Alias ACLAuthMethodListEntry + exported := &struct { + MaxTokenTTL string `json:",omitempty"` + *Alias + }{ + MaxTokenTTL: m.MaxTokenTTL.String(), + Alias: (*Alias)(m), + } + if m.MaxTokenTTL == 0 { + exported.MaxTokenTTL = "" + } + + return json.Marshal(exported) +} + +// This is nearly identical to the ACLAuthMethod UnmarshalJSON +func (m *ACLAuthMethodListEntry) UnmarshalJSON(data []byte) error { + type Alias ACLAuthMethodListEntry + aux := &struct { + MaxTokenTTL string + *Alias + }{ + Alias: (*Alias)(m), + } + + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + var err error + if aux.MaxTokenTTL != "" { + if m.MaxTokenTTL, err = time.ParseDuration(aux.MaxTokenTTL); err != nil { + return err + } + } + + return nil } // ParseKubernetesAuthMethodConfig takes a raw config map and returns a parsed @@ -333,6 +420,7 @@ type OIDCAuthMethodConfig struct { OIDCClientID string `json:",omitempty"` OIDCClientSecret string `json:",omitempty"` OIDCScopes []string `json:",omitempty"` + OIDCACRValues []string `json:",omitempty"` AllowedRedirectURIs []string `json:",omitempty"` VerboseOIDCLogging bool `json:",omitempty"` // just for type=jwt @@ -360,6 +448,7 @@ func (c *OIDCAuthMethodConfig) RenderToConfig() map[string]interface{} { "OIDCClientID": c.OIDCClientID, "OIDCClientSecret": c.OIDCClientSecret, "OIDCScopes": c.OIDCScopes, + "OIDCACRValues": c.OIDCACRValues, "AllowedRedirectURIs": c.AllowedRedirectURIs, "VerboseOIDCLogging": c.VerboseOIDCLogging, // just for type=jwt @@ -400,12 +489,14 @@ func (c *Client) ACL() *ACL { // to get the first management token. func (a *ACL) Bootstrap() (*ACLToken, *WriteMeta, error) { r := a.c.newRequest("PUT", "/v1/acl/bootstrap") - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { @@ -421,11 +512,14 @@ func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) r := a.c.newRequest("PUT", "/v1/acl/create") r.setWriteOptions(q) r.obj = acl - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{RequestTime: rtt} var out struct{ ID string } @@ -442,12 +536,14 @@ func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("PUT", "/v1/acl/update") r.setWriteOptions(q) r.obj = acl - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{RequestTime: rtt} return wm, nil } @@ -458,11 +554,14 @@ func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + if err := requireOK(resp); err != nil { + return nil, err + } + closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -474,11 +573,14 @@ func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{RequestTime: rtt} var out struct{ ID string } @@ -494,12 +596,14 @@ func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/info/"+id) r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -520,12 +624,14 @@ func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/list") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -541,12 +647,14 @@ func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { func (a *ACL) Replication(q *QueryOptions) (*ACLReplicationStatus, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/replication") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -564,12 +672,14 @@ func (a *ACL) TokenCreate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMe r := a.c.newRequest("PUT", "/v1/acl/token") r.setWriteOptions(q) r.obj = token - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { @@ -589,12 +699,14 @@ func (a *ACL) TokenUpdate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMe r := a.c.newRequest("PUT", "/v1/acl/token/"+token.AccessorID) r.setWriteOptions(q) r.obj = token - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { @@ -616,12 +728,14 @@ func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (* r := a.c.newRequest("PUT", "/v1/acl/token/"+tokenID+"/clone") r.setWriteOptions(q) r.obj = struct{ Description string }{description} - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { @@ -636,11 +750,14 @@ func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (* func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("DELETE", "/v1/acl/token/"+tokenID) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + if err := requireOK(resp); err != nil { + return nil, err + } + closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -651,12 +768,14 @@ func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) { func (a *ACL) TokenRead(tokenID string, q *QueryOptions) (*ACLToken, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/token/"+tokenID) r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -675,12 +794,14 @@ func (a *ACL) TokenRead(tokenID string, q *QueryOptions) (*ACLToken, *QueryMeta, func (a *ACL) TokenReadSelf(q *QueryOptions) (*ACLToken, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/token/self") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -698,12 +819,14 @@ func (a *ACL) TokenReadSelf(q *QueryOptions) (*ACLToken, *QueryMeta, error) { func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/tokens") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -724,12 +847,14 @@ func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *Wri r := a.c.newRequest("PUT", "/v1/acl/policy") r.setWriteOptions(q) r.obj = policy - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLPolicy if err := decodeBody(resp, &out); err != nil { @@ -749,12 +874,14 @@ func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *Wri r := a.c.newRequest("PUT", "/v1/acl/policy/"+policy.ID) r.setWriteOptions(q) r.obj = policy - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLPolicy if err := decodeBody(resp, &out); err != nil { @@ -768,11 +895,14 @@ func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *Wri func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("DELETE", "/v1/acl/policy/"+policyID) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -782,12 +912,14 @@ func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/policy/"+policyID) r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -804,11 +936,15 @@ func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMe func (a *ACL) PolicyReadByName(policyName string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/policy/name/"+url.QueryEscape(policyName)) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -831,12 +967,14 @@ func (a *ACL) PolicyReadByName(policyName string, q *QueryOptions) (*ACLPolicy, func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/policies") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -855,11 +993,16 @@ func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, er func (a *ACL) RulesTranslate(rules io.Reader) (string, error) { r := a.c.newRequest("POST", "/v1/acl/rules/translate") r.body = rules - rtt, resp, err := requireOK(a.c.doRequest(r)) + r.header.Set("Content-Type", "text/plain") + rtt, resp, err := a.c.doRequest(r) if err != nil { return "", err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", err + } + qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -879,11 +1022,14 @@ func (a *ACL) RulesTranslate(rules io.Reader) (string, error) { // when legacy ACL support is removed. func (a *ACL) RulesTranslateToken(tokenID string) (string, error) { r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+tokenID) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return "", err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -906,12 +1052,14 @@ func (a *ACL) RoleCreate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, r := a.c.newRequest("PUT", "/v1/acl/role") r.setWriteOptions(q) r.obj = role - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLRole if err := decodeBody(resp, &out); err != nil { @@ -931,12 +1079,14 @@ func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, r := a.c.newRequest("PUT", "/v1/acl/role/"+role.ID) r.setWriteOptions(q) r.obj = role - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLRole if err := decodeBody(resp, &out); err != nil { @@ -950,11 +1100,14 @@ func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("DELETE", "/v1/acl/role/"+roleID) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + if err := requireOK(resp); err != nil { + return nil, err + } + closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -964,11 +1117,15 @@ func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) { func (a *ACL) RoleRead(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/role/"+roleID) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -990,11 +1147,15 @@ func (a *ACL) RoleRead(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, er func (a *ACL) RoleReadByName(roleName string, q *QueryOptions) (*ACLRole, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/role/name/"+url.QueryEscape(roleName)) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -1018,12 +1179,14 @@ func (a *ACL) RoleReadByName(roleName string, q *QueryOptions) (*ACLRole, *Query func (a *ACL) RoleList(q *QueryOptions) ([]*ACLRole, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/roles") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -1044,12 +1207,14 @@ func (a *ACL) AuthMethodCreate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuth r := a.c.newRequest("PUT", "/v1/acl/auth-method") r.setWriteOptions(q) r.obj = method - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLAuthMethod if err := decodeBody(resp, &out); err != nil { @@ -1068,12 +1233,14 @@ func (a *ACL) AuthMethodUpdate(method *ACLAuthMethod, q *WriteOptions) (*ACLAuth r := a.c.newRequest("PUT", "/v1/acl/auth-method/"+url.QueryEscape(method.Name)) r.setWriteOptions(q) r.obj = method - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLAuthMethod if err := decodeBody(resp, &out); err != nil { @@ -1091,11 +1258,14 @@ func (a *ACL) AuthMethodDelete(methodName string, q *WriteOptions) (*WriteMeta, r := a.c.newRequest("DELETE", "/v1/acl/auth-method/"+url.QueryEscape(methodName)) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + if err := requireOK(resp); err != nil { + return nil, err + } + closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -1109,11 +1279,15 @@ func (a *ACL) AuthMethodRead(methodName string, q *QueryOptions) (*ACLAuthMethod r := a.c.newRequest("GET", "/v1/acl/auth-method/"+url.QueryEscape(methodName)) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -1137,12 +1311,14 @@ func (a *ACL) AuthMethodRead(methodName string, q *QueryOptions) (*ACLAuthMethod func (a *ACL) AuthMethodList(q *QueryOptions) ([]*ACLAuthMethodListEntry, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/auth-methods") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -1165,12 +1341,14 @@ func (a *ACL) BindingRuleCreate(rule *ACLBindingRule, q *WriteOptions) (*ACLBind r := a.c.newRequest("PUT", "/v1/acl/binding-rule") r.setWriteOptions(q) r.obj = rule - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLBindingRule if err := decodeBody(resp, &out); err != nil { @@ -1190,12 +1368,14 @@ func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBind r := a.c.newRequest("PUT", "/v1/acl/binding-rule/"+rule.ID) r.setWriteOptions(q) r.obj = rule - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLBindingRule if err := decodeBody(resp, &out); err != nil { @@ -1209,11 +1389,14 @@ func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBind func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("DELETE", "/v1/acl/binding-rule/"+bindingRuleID) r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -1223,11 +1406,15 @@ func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMe func (a *ACL) BindingRuleRead(bindingRuleID string, q *QueryOptions) (*ACLBindingRule, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/acl/binding-rule/"+bindingRuleID) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -1252,12 +1439,14 @@ func (a *ACL) BindingRuleList(methodName string, q *QueryOptions) ([]*ACLBinding r.params.Set("authmethod", methodName) } r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -1275,12 +1464,14 @@ func (a *ACL) Login(auth *ACLLoginParams, q *WriteOptions) (*ACLToken, *WriteMet r.setWriteOptions(q) r.obj = auth - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { @@ -1293,11 +1484,14 @@ func (a *ACL) Login(auth *ACLLoginParams, q *WriteOptions) (*ACLToken, *WriteMet func (a *ACL) Logout(q *WriteOptions) (*WriteMeta, error) { r := a.c.newRequest("POST", "/v1/acl/logout") r.setWriteOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + if err := requireOK(resp); err != nil { + return nil, err + } + closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -1313,11 +1507,14 @@ func (a *ACL) OIDCAuthURL(auth *ACLOIDCAuthURLParams, q *WriteOptions) (string, r.setWriteOptions(q) r.obj = auth - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{RequestTime: rtt} var out aclOIDCAuthURLResponse @@ -1348,12 +1545,14 @@ func (a *ACL) OIDCCallback(auth *ACLOIDCCallbackParams, q *WriteOptions) (*ACLTo r.setWriteOptions(q) r.obj = auth - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out ACLToken if err := decodeBody(resp, &out); err != nil { diff --git a/vendor/github.com/hashicorp/consul/api/agent.go b/vendor/github.com/hashicorp/consul/api/agent.go index 3e1136895..e3b5d362a 100644 --- a/vendor/github.com/hashicorp/consul/api/agent.go +++ b/vendor/github.com/hashicorp/consul/api/agent.go @@ -2,7 +2,8 @@ package api import ( "bufio" - "bytes" + "context" + "errors" "fmt" "io" "net/http" @@ -62,8 +63,10 @@ type AgentCheck struct { ServiceID string ServiceName string Type string + ExposedPort int Definition HealthCheckDefinition Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` } // AgentWeights represent optional weights for a service @@ -81,6 +84,7 @@ type AgentService struct { Meta map[string]string Port int Address string + SocketPath string `json:",omitempty"` TaggedAddresses map[string]ServiceAddress `json:",omitempty"` Weights AgentWeights EnableTagOverride bool @@ -93,6 +97,9 @@ type AgentService struct { // to include the Namespace in the hash. When we do, then we are in for lots of fun with tests. // For now though, ignoring it works well enough. Namespace string `json:",omitempty" bexpr:"-" hash:"ignore"` + Partition string `json:",omitempty" bexpr:"-" hash:"ignore"` + // Datacenter is only ever returned and is ignored if presented. + Datacenter string `json:",omitempty" bexpr:"-" hash:"ignore"` } // AgentServiceChecksInfo returns information about a Service and its checks @@ -111,14 +118,17 @@ type AgentServiceConnect struct { // AgentServiceConnectProxyConfig is the proxy configuration in a connect-proxy // ServiceDefinition or response. type AgentServiceConnectProxyConfig struct { - DestinationServiceName string `json:",omitempty"` - DestinationServiceID string `json:",omitempty"` - LocalServiceAddress string `json:",omitempty"` - LocalServicePort int `json:",omitempty"` - Config map[string]interface{} `json:",omitempty" bexpr:"-"` - Upstreams []Upstream `json:",omitempty"` - MeshGateway MeshGatewayConfig `json:",omitempty"` - Expose ExposeConfig `json:",omitempty"` + DestinationServiceName string `json:",omitempty"` + DestinationServiceID string `json:",omitempty"` + LocalServiceAddress string `json:",omitempty"` + LocalServicePort int `json:",omitempty"` + LocalServiceSocketPath string `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy *TransparentProxyConfig `json:",omitempty"` + Config map[string]interface{} `json:",omitempty" bexpr:"-"` + Upstreams []Upstream `json:",omitempty"` + MeshGateway MeshGatewayConfig `json:",omitempty"` + Expose ExposeConfig `json:",omitempty"` } const ( @@ -134,11 +144,23 @@ const ( // that the member represents a Consul server. MemberTagValueRoleServer = "consul" + // MemberTagValueRoleClient is the value of the MemberTagKeyRole used to indicate + // that the member represents a Consul client. + MemberTagValueRoleClient = "node" + + // MemberTagKeyDatacenter is the key used to indicate which datacenter this member is in. + MemberTagKeyDatacenter = "dc" + // MemberTagKeySegment is the key name of the tag used to indicate which network // segment this member is in. // Network Segments are a Consul Enterprise feature. MemberTagKeySegment = "segment" + // MemberTagKeyPartition is the key name of the tag used to indicate which partition + // this member is in. + // Partitions are a Consul Enterprise feature. + MemberTagKeyPartition = "ap" + // MemberTagKeyBootstrap is the key name of the tag used to indicate whether this // agent was started with the "bootstrap" configuration enabled MemberTagKeyBootstrap = "bootstrap" @@ -162,7 +184,7 @@ const ( // MemberTagKeyReadReplica is the key used to indicate that the member is a read // replica server (will remain a Raft non-voter). // Read Replicas are a Consul Enterprise feature. - MemberTagKeyReadReplica = "nonvoter" + MemberTagKeyReadReplica = "read_replica" // MemberTagValueReadReplica is the value of the MemberTagKeyReadReplica key when // the member is in fact a read-replica. Any other value indicates that it is not. // Read Replicas are a Consul Enterprise feature. @@ -187,10 +209,18 @@ const ( // AgentMember represents a cluster member known to the agent type AgentMember struct { - Name string - Addr string - Port uint16 - Tags map[string]string + Name string + Addr string + Port uint16 + Tags map[string]string + // Status of the Member which corresponds to github.com/hashicorp/serf/serf.MemberStatus + // Value is one of: + // + // AgentMemberNone = 0 + // AgentMemberAlive = 1 + // AgentMemberLeaving = 2 + // AgentMemberLeft = 3 + // AgentMemberFailed = 4 Status int ProtocolMin uint8 ProtocolMax uint8 @@ -245,6 +275,7 @@ type AgentServiceRegistration struct { Tags []string `json:",omitempty"` Port int `json:",omitempty"` Address string `json:",omitempty"` + SocketPath string `json:",omitempty"` TaggedAddresses map[string]ServiceAddress `json:",omitempty"` EnableTagOverride bool `json:",omitempty"` Meta map[string]string `json:",omitempty"` @@ -254,14 +285,26 @@ type AgentServiceRegistration struct { Proxy *AgentServiceConnectProxyConfig `json:",omitempty"` Connect *AgentServiceConnect `json:",omitempty"` Namespace string `json:",omitempty" bexpr:"-" hash:"ignore"` + Partition string `json:",omitempty" bexpr:"-" hash:"ignore"` } -//ServiceRegisterOpts is used to pass extra options to the service register. +// ServiceRegisterOpts is used to pass extra options to the service register. type ServiceRegisterOpts struct { - //Missing healthchecks will be deleted from the agent. - //Using this parameter allows to idempotently register a service and its checks without - //having to manually deregister checks. + // Missing healthchecks will be deleted from the agent. + // Using this parameter allows to idempotently register a service and its checks without + // having to manually deregister checks. ReplaceExistingChecks bool + + // ctx is an optional context pass through to the underlying HTTP + // request layer. Use WithContext() to set the context. + ctx context.Context +} + +// WithContext sets the context to be used for the request on a new ServiceRegisterOpts, +// and returns the opts. +func (o ServiceRegisterOpts) WithContext(ctx context.Context) ServiceRegisterOpts { + o.ctx = ctx + return o } // AgentCheckRegistration is used to register a new check @@ -272,6 +315,7 @@ type AgentCheckRegistration struct { ServiceID string `json:",omitempty"` AgentServiceCheck Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` } // AgentServiceCheck is used to define a node or service level check @@ -291,12 +335,16 @@ type AgentServiceCheck struct { TCP string `json:",omitempty"` Status string `json:",omitempty"` Notes string `json:",omitempty"` + TLSServerName string `json:",omitempty"` TLSSkipVerify bool `json:",omitempty"` GRPC string `json:",omitempty"` GRPCUseTLS bool `json:",omitempty"` + H2PING string `json:",omitempty"` + H2PingUseTLS bool `json:",omitempty"` AliasNode string `json:",omitempty"` AliasService string `json:",omitempty"` SuccessBeforePassing int `json:",omitempty"` + FailuresBeforeWarning int `json:",omitempty"` FailuresBeforeCritical int `json:",omitempty"` // In Consul 0.7 and later, checks that are associated with a service @@ -377,13 +425,17 @@ type ConnectProxyConfig struct { // Upstream is the response structure for a proxy upstream configuration. type Upstream struct { DestinationType UpstreamDestType `json:",omitempty"` + DestinationPartition string `json:",omitempty"` DestinationNamespace string `json:",omitempty"` DestinationName string Datacenter string `json:",omitempty"` LocalBindAddress string `json:",omitempty"` LocalBindPort int `json:",omitempty"` + LocalBindSocketPath string `json:",omitempty"` + LocalBindSocketMode string `json:",omitempty"` Config map[string]interface{} `json:",omitempty" bexpr:"-"` MeshGateway MeshGatewayConfig `json:",omitempty"` + CentrallyConfigured bool `json:",omitempty" bexpr:"-"` } // Agent can be used to query the Agent endpoints @@ -403,11 +455,14 @@ func (c *Client) Agent() *Agent { // information about itself func (a *Agent) Self() (map[string]map[string]interface{}, error) { r := a.c.newRequest("GET", "/v1/agent/self") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out map[string]map[string]interface{} if err := decodeBody(resp, &out); err != nil { @@ -421,12 +476,14 @@ func (a *Agent) Self() (map[string]map[string]interface{}, error) { // a operator:read ACL token. func (a *Agent) Host() (map[string]interface{}, error) { r := a.c.newRequest("GET", "/v1/agent/host") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out map[string]interface{} if err := decodeBody(resp, &out); err != nil { return nil, err @@ -438,12 +495,14 @@ func (a *Agent) Host() (map[string]interface{}, error) { // its current internal metric data func (a *Agent) Metrics() (*MetricsInfo, error) { r := a.c.newRequest("GET", "/v1/agent/metrics") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out *MetricsInfo if err := decodeBody(resp, &out); err != nil { return nil, err @@ -451,14 +510,33 @@ func (a *Agent) Metrics() (*MetricsInfo, error) { return out, nil } +// MetricsStream returns an io.ReadCloser which will emit a stream of metrics +// until the context is cancelled. The metrics are json encoded. +// The caller is responsible for closing the returned io.ReadCloser. +func (a *Agent) MetricsStream(ctx context.Context) (io.ReadCloser, error) { + r := a.c.newRequest("GET", "/v1/agent/metrics/stream") + r.ctx = ctx + _, resp, err := a.c.doRequest(r) + if err != nil { + return nil, err + } + if err := requireOK(resp); err != nil { + return nil, err + } + return resp.Body, nil +} + // Reload triggers a configuration reload for the agent we are connected to. func (a *Agent) Reload() error { r := a.c.newRequest("PUT", "/v1/agent/reload") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -484,14 +562,23 @@ func (a *Agent) Checks() (map[string]*AgentCheck, error) { // ChecksWithFilter returns a subset of the locally registered checks that match // the given filter expression func (a *Agent) ChecksWithFilter(filter string) (map[string]*AgentCheck, error) { + return a.ChecksWithFilterOpts(filter, nil) +} + +// ChecksWithFilterOpts returns a subset of the locally registered checks that match +// the given filter expression and QueryOptions. +func (a *Agent) ChecksWithFilterOpts(filter string, q *QueryOptions) (map[string]*AgentCheck, error) { r := a.c.newRequest("GET", "/v1/agent/checks") + r.setQueryOptions(q) r.filterQuery(filter) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out map[string]*AgentCheck if err := decodeBody(resp, &out); err != nil { return nil, err @@ -507,14 +594,23 @@ func (a *Agent) Services() (map[string]*AgentService, error) { // ServicesWithFilter returns a subset of the locally registered services that match // the given filter expression func (a *Agent) ServicesWithFilter(filter string) (map[string]*AgentService, error) { + return a.ServicesWithFilterOpts(filter, nil) +} + +// ServicesWithFilterOpts returns a subset of the locally registered services that match +// the given filter expression and QueryOptions. +func (a *Agent) ServicesWithFilterOpts(filter string, q *QueryOptions) (map[string]*AgentService, error) { r := a.c.newRequest("GET", "/v1/agent/services") + r.setQueryOptions(q) r.filterQuery(filter) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out map[string]*AgentService if err := decodeBody(resp, &out); err != nil { return nil, err @@ -528,15 +624,22 @@ func (a *Agent) ServicesWithFilter(filter string) (map[string]*AgentService, err // - If the service is found, will return (critical|passing|warning), AgentServiceChecksInfo, nil) // - In all other cases, will return an error func (a *Agent) AgentHealthServiceByID(serviceID string) (string, *AgentServiceChecksInfo, error) { + return a.AgentHealthServiceByIDOpts(serviceID, nil) +} + +func (a *Agent) AgentHealthServiceByIDOpts(serviceID string, q *QueryOptions) (string, *AgentServiceChecksInfo, error) { path := fmt.Sprintf("/v1/agent/health/service/id/%v", url.PathEscape(serviceID)) r := a.c.newRequest("GET", path) + r.setQueryOptions(q) r.params.Add("format", "json") r.header.Set("Accept", "application/json") + // not a lot of value in wrapping the doRequest call in a requireHttpCodes call + // we manipulate the resp body and the require calls "swallow" the content on err _, resp, err := a.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) // Service not Found if resp.StatusCode == http.StatusNotFound { return HealthCritical, nil, nil @@ -562,15 +665,22 @@ func (a *Agent) AgentHealthServiceByID(serviceID string) (string, *AgentServiceC // - If the service is found, will return (critical|passing|warning), []api.AgentServiceChecksInfo, nil) // - In all other cases, will return an error func (a *Agent) AgentHealthServiceByName(service string) (string, []AgentServiceChecksInfo, error) { + return a.AgentHealthServiceByNameOpts(service, nil) +} + +func (a *Agent) AgentHealthServiceByNameOpts(service string, q *QueryOptions) (string, []AgentServiceChecksInfo, error) { path := fmt.Sprintf("/v1/agent/health/service/name/%v", url.PathEscape(service)) r := a.c.newRequest("GET", path) + r.setQueryOptions(q) r.params.Add("format", "json") r.header.Set("Accept", "application/json") + // not a lot of value in wrapping the doRequest call in a requireHttpCodes call + // we manipulate the resp body and the require calls "swallow" the content on err _, resp, err := a.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) // Service not Found if resp.StatusCode == http.StatusNotFound { return HealthCritical, nil, nil @@ -599,12 +709,14 @@ func (a *Agent) AgentHealthServiceByName(service string) (string, []AgentService func (a *Agent) Service(serviceID string, q *QueryOptions) (*AgentService, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/agent/service/"+serviceID) r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -624,12 +736,14 @@ func (a *Agent) Members(wan bool) ([]*AgentMember, error) { if wan { r.params.Set("wan", "1") } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out []*AgentMember if err := decodeBody(resp, &out); err != nil { return nil, err @@ -646,12 +760,14 @@ func (a *Agent) MembersOpts(opts MembersOpts) ([]*AgentMember, error) { r.params.Set("wan", "1") } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out []*AgentMember if err := decodeBody(resp, &out); err != nil { return nil, err @@ -678,14 +794,18 @@ func (a *Agent) ServiceRegisterOpts(service *AgentServiceRegistration, opts Serv func (a *Agent) serviceRegister(service *AgentServiceRegistration, opts ServiceRegisterOpts) error { r := a.c.newRequest("PUT", "/v1/agent/service/register") r.obj = service + r.ctx = opts.ctx if opts.ReplaceExistingChecks { r.params.Set("replace-existing-checks", "true") } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -693,11 +813,30 @@ func (a *Agent) serviceRegister(service *AgentServiceRegistration, opts ServiceR // the local agent func (a *Agent) ServiceDeregister(serviceID string) error { r := a.c.newRequest("PUT", "/v1/agent/service/deregister/"+serviceID) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } + return nil +} + +// ServiceDeregisterOpts is used to deregister a service with +// the local agent with QueryOptions. +func (a *Agent) ServiceDeregisterOpts(serviceID string, q *QueryOptions) error { + r := a.c.newRequest("PUT", "/v1/agent/service/deregister/"+serviceID) + r.setQueryOptions(q) + _, resp, err := a.c.doRequest(r) + if err != nil { + return err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -748,11 +887,14 @@ func (a *Agent) updateTTL(checkID, note, status string) error { endpoint := fmt.Sprintf("/v1/agent/check/%s/%s", status, checkID) r := a.c.newRequest("PUT", endpoint) r.params.Set("note", note) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -775,6 +917,10 @@ type checkUpdate struct { // strings for compatibility (though a newer version of Consul will still be // required to use this API). func (a *Agent) UpdateTTL(checkID, output, status string) error { + return a.UpdateTTLOpts(checkID, output, status, nil) +} + +func (a *Agent) UpdateTTLOpts(checkID, output, status string, q *QueryOptions) error { switch status { case "pass", HealthPassing: status = HealthPassing @@ -788,16 +934,20 @@ func (a *Agent) UpdateTTL(checkID, output, status string) error { endpoint := fmt.Sprintf("/v1/agent/check/update/%s", checkID) r := a.c.newRequest("PUT", endpoint) + r.setQueryOptions(q) r.obj = &checkUpdate{ Status: status, Output: output, } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -806,23 +956,36 @@ func (a *Agent) UpdateTTL(checkID, output, status string) error { func (a *Agent) CheckRegister(check *AgentCheckRegistration) error { r := a.c.newRequest("PUT", "/v1/agent/check/register") r.obj = check - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } // CheckDeregister is used to deregister a check with // the local agent func (a *Agent) CheckDeregister(checkID string) error { + return a.CheckDeregisterOpts(checkID, nil) +} + +// CheckDeregisterOpts is used to deregister a check with +// the local agent using query options +func (a *Agent) CheckDeregisterOpts(checkID string, q *QueryOptions) error { r := a.c.newRequest("PUT", "/v1/agent/check/deregister/"+checkID) - _, resp, err := requireOK(a.c.doRequest(r)) + r.setQueryOptions(q) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -833,46 +996,69 @@ func (a *Agent) Join(addr string, wan bool) error { if wan { r.params.Set("wan", "1") } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } // Leave is used to have the agent gracefully leave the cluster and shutdown func (a *Agent) Leave() error { r := a.c.newRequest("PUT", "/v1/agent/leave") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } +type ForceLeaveOpts struct { + // Prune indicates if we should remove a failed agent from the list of + // members in addition to ejecting it. + Prune bool + + // WAN indicates that the request should exclusively target the WAN pool. + WAN bool +} + // ForceLeave is used to have the agent eject a failed node func (a *Agent) ForceLeave(node string) error { - r := a.c.newRequest("PUT", "/v1/agent/force-leave/"+node) - _, resp, err := requireOK(a.c.doRequest(r)) - if err != nil { - return err - } - resp.Body.Close() - return nil + return a.ForceLeaveOpts(node, ForceLeaveOpts{}) } -//ForceLeavePrune is used to have an a failed agent removed -//from the list of members +// ForceLeavePrune is used to have an a failed agent removed +// from the list of members func (a *Agent) ForceLeavePrune(node string) error { + return a.ForceLeaveOpts(node, ForceLeaveOpts{Prune: true}) +} + +// ForceLeaveOpts is used to have the agent eject a failed node or remove it +// completely from the list of members. +func (a *Agent) ForceLeaveOpts(node string, opts ForceLeaveOpts) error { r := a.c.newRequest("PUT", "/v1/agent/force-leave/"+node) - r.params.Set("prune", "1") - _, resp, err := requireOK(a.c.doRequest(r)) + if opts.Prune { + r.params.Set("prune", "1") + } + if opts.WAN { + r.params.Set("wan", "1") + } + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -881,12 +1067,14 @@ func (a *Agent) ForceLeavePrune(node string) error { func (a *Agent) ConnectAuthorize(auth *AgentAuthorizeParams) (*AgentAuthorize, error) { r := a.c.newRequest("POST", "/v1/agent/connect/authorize") r.obj = auth - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out AgentAuthorize if err := decodeBody(resp, &out); err != nil { return nil, err @@ -898,11 +1086,14 @@ func (a *Agent) ConnectAuthorize(auth *AgentAuthorizeParams) (*AgentAuthorize, e func (a *Agent) ConnectCARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/agent/connect/ca/roots") r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -919,12 +1110,14 @@ func (a *Agent) ConnectCARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) func (a *Agent) ConnectCALeaf(serviceID string, q *QueryOptions) (*LeafCert, *QueryMeta, error) { r := a.c.newRequest("GET", "/v1/agent/connect/ca/leaf/"+serviceID) r.setQueryOptions(q) - rtt, resp, err := requireOK(a.c.doRequest(r)) + rtt, resp, err := a.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -939,27 +1132,43 @@ func (a *Agent) ConnectCALeaf(serviceID string, q *QueryOptions) (*LeafCert, *Qu // EnableServiceMaintenance toggles service maintenance mode on // for the given service ID. func (a *Agent) EnableServiceMaintenance(serviceID, reason string) error { + return a.EnableServiceMaintenanceOpts(serviceID, reason, nil) +} + +func (a *Agent) EnableServiceMaintenanceOpts(serviceID, reason string, q *QueryOptions) error { r := a.c.newRequest("PUT", "/v1/agent/service/maintenance/"+serviceID) + r.setQueryOptions(q) r.params.Set("enable", "true") r.params.Set("reason", reason) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } // DisableServiceMaintenance toggles service maintenance mode off // for the given service ID. func (a *Agent) DisableServiceMaintenance(serviceID string) error { + return a.DisableServiceMaintenanceOpts(serviceID, nil) +} + +func (a *Agent) DisableServiceMaintenanceOpts(serviceID string, q *QueryOptions) error { r := a.c.newRequest("PUT", "/v1/agent/service/maintenance/"+serviceID) + r.setQueryOptions(q) r.params.Set("enable", "false") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -969,11 +1178,14 @@ func (a *Agent) EnableNodeMaintenance(reason string) error { r := a.c.newRequest("PUT", "/v1/agent/maintenance") r.params.Set("enable", "true") r.params.Set("reason", reason) - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -982,11 +1194,14 @@ func (a *Agent) EnableNodeMaintenance(reason string) error { func (a *Agent) DisableNodeMaintenance() error { r := a.c.newRequest("PUT", "/v1/agent/maintenance") r.params.Set("enable", "false") - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -1002,6 +1217,7 @@ func (a *Agent) Monitor(loglevel string, stopCh <-chan struct{}, q *QueryOptions func (a *Agent) MonitorJSON(loglevel string, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { return a.monitor(loglevel, true, stopCh, q) } + func (a *Agent) monitor(loglevel string, logJSON bool, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { r := a.c.newRequest("GET", "/v1/agent/monitor") r.setQueryOptions(q) @@ -1011,13 +1227,16 @@ func (a *Agent) monitor(loglevel string, logJSON bool, stopCh <-chan struct{}, q if logJSON { r.params.Set("logjson", "true") } - _, resp, err := requireOK(a.c.doRequest(r)) + _, resp, err := a.c.doRequest(r) if err != nil { return nil, err } + if err := requireOK(resp); err != nil { + return nil, err + } logCh := make(chan string, 64) go func() { - defer resp.Body.Close() + defer closeResponseBody(resp) scanner := bufio.NewScanner(resp.Body) for { select { @@ -1079,25 +1298,33 @@ func (a *Agent) UpdateACLReplicationToken(token string, q *WriteOptions) (*Write // UpdateDefaultACLToken updates the agent's "default" token. See updateToken // for more details func (a *Agent) UpdateDefaultACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("default", "acl_token", token, q) + return a.updateTokenFallback(token, q, "default", "acl_token") } // UpdateAgentACLToken updates the agent's "agent" token. See updateToken // for more details func (a *Agent) UpdateAgentACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("agent", "acl_agent_token", token, q) + return a.updateTokenFallback(token, q, "agent", "acl_agent_token") +} + +// UpdateAgentRecoveryACLToken updates the agent's "agent_recovery" token. See updateToken +// for more details. +func (a *Agent) UpdateAgentRecoveryACLToken(token string, q *WriteOptions) (*WriteMeta, error) { + return a.updateTokenFallback(token, q, "agent_recovery", "agent_master", "acl_agent_master_token") } // UpdateAgentMasterACLToken updates the agent's "agent_master" token. See updateToken -// for more details +// for more details. +// +// DEPRECATED - Prefer UpdateAgentRecoveryACLToken for v1.11 and above. func (a *Agent) UpdateAgentMasterACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("agent_master", "acl_agent_master_token", token, q) + return a.updateTokenFallback(token, q, "agent_master", "acl_agent_master_token") } // UpdateReplicationACLToken updates the agent's "replication" token. See updateToken // for more details func (a *Agent) UpdateReplicationACLToken(token string, q *WriteOptions) (*WriteMeta, error) { - return a.updateTokenFallback("replication", "acl_replication_token", token, q) + return a.updateTokenFallback(token, q, "replication", "acl_replication_token") } // updateToken can be used to update one of an agent's ACL tokens after the agent has @@ -1108,10 +1335,21 @@ func (a *Agent) updateToken(target, token string, q *WriteOptions) (*WriteMeta, return meta, err } -func (a *Agent) updateTokenFallback(target, fallback, token string, q *WriteOptions) (*WriteMeta, error) { - meta, status, err := a.updateTokenOnce(target, token, q) - if err != nil && status == 404 { - meta, _, err = a.updateTokenOnce(fallback, token, q) +func (a *Agent) updateTokenFallback(token string, q *WriteOptions, targets ...string) (*WriteMeta, error) { + if len(targets) == 0 { + panic("targets must not be empty") + } + + var ( + meta *WriteMeta + err error + ) + for _, target := range targets { + var status int + meta, status, err = a.updateTokenOnce(target, token, q) + if err == nil && status != http.StatusNotFound { + return meta, err + } } return meta, err } @@ -1123,17 +1361,16 @@ func (a *Agent) updateTokenOnce(target, token string, q *WriteOptions) (*WriteMe rtt, resp, err := a.c.doRequest(r) if err != nil { - return nil, 0, err + return nil, 500, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} - - if resp.StatusCode != 200 { - var buf bytes.Buffer - io.Copy(&buf, resp.Body) - return wm, resp.StatusCode, fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) + if err := requireOK(resp); err != nil { + var statusE StatusError + if errors.As(err, &statusE) { + return wm, statusE.Code, statusE + } + return nil, 0, err } - return wm, resp.StatusCode, nil } diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go index 38a4e98fb..d97f1879f 100644 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ b/vendor/github.com/hashicorp/consul/api/api.go @@ -14,6 +14,7 @@ import ( "os" "strconv" "strings" + "sync" "time" "github.com/hashicorp/go-cleanhttp" @@ -75,14 +76,31 @@ const ( // HTTPNamespaceEnvVar defines an environment variable name which sets // the HTTP Namespace to be used by default. This can still be overridden. HTTPNamespaceEnvName = "CONSUL_NAMESPACE" + + // HTTPPartitionEnvName defines an environment variable name which sets + // the HTTP Partition to be used by default. This can still be overridden. + HTTPPartitionEnvName = "CONSUL_PARTITION" ) +type StatusError struct { + Code int + Body string +} + +func (e StatusError) Error() string { + return fmt.Sprintf("Unexpected response code: %d (%s)", e.Code, e.Body) +} + // QueryOptions are used to parameterize a query type QueryOptions struct { // Namespace overrides the `default` namespace // Note: Namespaces are available only in Consul Enterprise Namespace string + // Partition overrides the `default` partition + // Note: Partitions are available only in Consul Enterprise + Partition string + // Providing a datacenter overwrites the DC provided // by the Config Datacenter string @@ -190,6 +208,10 @@ type WriteOptions struct { // Note: Namespaces are available only in Consul Enterprise Namespace string + // Partition overrides the `default` partition + // Note: Partitions are available only in Consul Enterprise + Partition string + // Providing a datacenter overwrites the DC provided // by the Config Datacenter string @@ -254,6 +276,16 @@ type QueryMeta struct { // CacheAge is set if request was ?cached and indicates how stale the cached // response is. CacheAge time.Duration + + // DefaultACLPolicy is used to control the ACL interaction when there is no + // defined policy. This can be "allow" which means ACLs are used to + // deny-list, or "deny" which means ACLs are allow-lists. + DefaultACLPolicy string + + // ResultsFilteredByACLs is true when some of the query's results were + // filtered out by enforcing ACLs. It may be false because nothing was + // removed, or because the endpoint does not yet support this flag. + ResultsFilteredByACLs bool } // WriteMeta is used to return meta data about a write @@ -305,9 +337,13 @@ type Config struct { TokenFile string // Namespace is the name of the namespace to send along for the request - // when no other Namespace ispresent in the QueryOptions + // when no other Namespace is present in the QueryOptions Namespace string + // Partition is the name of the partition to send along for the request + // when no other Partition is present in the QueryOptions + Partition string + TLSConfig TLSConfig } @@ -460,6 +496,10 @@ func defaultConfig(logger hclog.Logger, transportFn func() *http.Transport) *Con config.Namespace = v } + if v := os.Getenv(HTTPPartitionEnvName); v != "" { + config.Partition = v + } + return config } @@ -543,9 +583,48 @@ func (c *Config) GenerateEnv() []string { // Client provides a client to the Consul API type Client struct { + modifyLock sync.RWMutex + headers http.Header + config Config } +// Headers gets the current set of headers used for requests. This returns a +// copy; to modify it call AddHeader or SetHeaders. +func (c *Client) Headers() http.Header { + c.modifyLock.RLock() + defer c.modifyLock.RUnlock() + + if c.headers == nil { + return nil + } + + ret := make(http.Header) + for k, v := range c.headers { + for _, val := range v { + ret[k] = append(ret[k], val) + } + } + + return ret +} + +// AddHeader allows a single header key/value pair to be added +// in a race-safe fashion. +func (c *Client) AddHeader(key, value string) { + c.modifyLock.Lock() + defer c.modifyLock.Unlock() + c.headers.Add(key, value) +} + +// SetHeaders clears all previous headers and uses only the given +// ones going forward. +func (c *Client) SetHeaders(headers http.Header) { + c.modifyLock.Lock() + defer c.modifyLock.Unlock() + c.headers = headers +} + // NewClient returns a new client func NewClient(config *Config) (*Client, error) { // bootstrap the config @@ -595,6 +674,14 @@ func NewClient(config *Config) (*Client, error) { } } + if config.Namespace == "" { + config.Namespace = defConfig.Namespace + } + + if config.Partition == "" { + config.Partition = defConfig.Partition + } + parts := strings.SplitN(config.Address, "://", 2) if len(parts) == 2 { switch parts[0] { @@ -635,7 +722,7 @@ func NewClient(config *Config) (*Client, error) { config.Token = defConfig.Token } - return &Client{config: *config}, nil + return &Client{config: *config, headers: make(http.Header)}, nil } // NewHttpClient returns an http client configured with the given Transport and TLS @@ -687,6 +774,9 @@ func (r *request) setQueryOptions(q *QueryOptions) { if q.Namespace != "" { r.params.Set("ns", q.Namespace) } + if q.Partition != "" { + r.params.Set("partition", q.Partition) + } if q.Datacenter != "" { r.params.Set("dc", q.Datacenter) } @@ -789,6 +879,9 @@ func (r *request) setWriteOptions(q *WriteOptions) { if q.Namespace != "" { r.params.Set("ns", q.Namespace) } + if q.Partition != "" { + r.params.Set("partition", q.Partition) + } if q.Datacenter != "" { r.params.Set("dc", q.Datacenter) } @@ -826,6 +919,12 @@ func (r *request) toHTTP() (*http.Request, error) { req.Host = r.url.Host req.Header = r.header + // Content-Type must always be set when a body is present + // See https://github.com/hashicorp/consul/issues/10011 + if req.Body != nil && req.Header.Get("Content-Type") == "" { + req.Header.Set("Content-Type", "application/json") + } + // Setup auth if r.config.HttpAuth != nil { req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password) @@ -848,14 +947,18 @@ func (c *Client) newRequest(method, path string) *request { Path: path, }, params: make(map[string][]string), - header: make(http.Header), + header: c.Headers(), } + if c.config.Datacenter != "" { r.params.Set("dc", c.config.Datacenter) } if c.config.Namespace != "" { r.params.Set("ns", c.config.Namespace) } + if c.config.Partition != "" { + r.params.Set("partition", c.config.Partition) + } if c.config.WaitTime != 0 { r.params.Set("wait", durToMsec(r.config.WaitTime)) } @@ -887,8 +990,10 @@ func (c *Client) query(endpoint string, out interface{}, q *QueryOptions) (*Quer if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt @@ -905,11 +1010,14 @@ func (c *Client) write(endpoint string, in, out interface{}, q *WriteOptions) (* r := c.newRequest("PUT", endpoint) r.setWriteOptions(q) r.obj = in - rtt, resp, err := requireOK(c.doRequest(r)) + rtt, resp, err := c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{RequestTime: rtt} if out != nil { @@ -962,6 +1070,20 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error { q.AddressTranslationEnabled = false } + // Parse X-Consul-Default-ACL-Policy + switch v := header.Get("X-Consul-Default-ACL-Policy"); v { + case "allow", "deny": + q.DefaultACLPolicy = v + } + + // Parse the X-Consul-Results-Filtered-By-ACLs + switch header.Get("X-Consul-Results-Filtered-By-ACLs") { + case "true": + q.ResultsFilteredByACLs = true + default: + q.ResultsFilteredByACLs = false + } + // Parse Cache info if cacheStr := header.Get("X-Cache"); cacheStr != "" { q.CacheHit = strings.EqualFold(cacheStr, "HIT") @@ -994,17 +1116,30 @@ func encodeBody(obj interface{}) (io.Reader, error) { } // requireOK is used to wrap doRequest and check for a 200 -func requireOK(d time.Duration, resp *http.Response, e error) (time.Duration, *http.Response, error) { - if e != nil { - if resp != nil { - resp.Body.Close() +func requireOK(resp *http.Response) error { + return requireHttpCodes(resp, 200) +} + +// requireHttpCodes checks for the "allowable" http codes for a response +func requireHttpCodes(resp *http.Response, httpCodes ...int) error { + // if there is an http code that we require, return w no error + for _, httpCode := range httpCodes { + if resp.StatusCode == httpCode { + return nil } - return d, nil, e } - if resp.StatusCode != 200 { - return d, nil, generateUnexpectedResponseCodeError(resp) - } - return d, resp, nil + + // if we reached here, then none of the http codes in resp matched any that we expected + // so err out + return generateUnexpectedResponseCodeError(resp) +} + +// closeResponseBody reads resp.Body until EOF, and then closes it. The read +// is necessary to ensure that the http.Client's underlying RoundTripper is able +// to re-use the TCP connection. See godoc on net/http.Client.Do. +func closeResponseBody(resp *http.Response) error { + _, _ = io.Copy(ioutil.Discard, resp.Body) + return resp.Body.Close() } func (req *request) filterQuery(filter string) { @@ -1021,23 +1156,19 @@ func (req *request) filterQuery(filter string) { func generateUnexpectedResponseCodeError(resp *http.Response) error { var buf bytes.Buffer io.Copy(&buf, resp.Body) - resp.Body.Close() - return fmt.Errorf("Unexpected response code: %d (%s)", resp.StatusCode, buf.Bytes()) + closeResponseBody(resp) + + trimmed := strings.TrimSpace(string(buf.Bytes())) + return StatusError{Code: resp.StatusCode, Body: trimmed} } -func requireNotFoundOrOK(d time.Duration, resp *http.Response, e error) (bool, time.Duration, *http.Response, error) { - if e != nil { - if resp != nil { - resp.Body.Close() - } - return false, d, nil, e - } +func requireNotFoundOrOK(resp *http.Response) (bool, *http.Response, error) { switch resp.StatusCode { case 200: - return true, d, resp, nil + return true, resp, nil case 404: - return false, d, resp, nil + return false, resp, nil default: - return false, d, nil, generateUnexpectedResponseCodeError(resp) + return false, nil, generateUnexpectedResponseCodeError(resp) } } diff --git a/vendor/github.com/hashicorp/consul/api/catalog.go b/vendor/github.com/hashicorp/consul/api/catalog.go index 607d5d065..80ae325ea 100644 --- a/vendor/github.com/hashicorp/consul/api/catalog.go +++ b/vendor/github.com/hashicorp/consul/api/catalog.go @@ -19,6 +19,7 @@ type Node struct { Meta map[string]string CreateIndex uint64 ModifyIndex uint64 + Partition string `json:",omitempty"` } type ServiceAddress struct { @@ -47,6 +48,7 @@ type CatalogService struct { Checks HealthChecks ModifyIndex uint64 Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` } type CatalogNode struct { @@ -70,6 +72,7 @@ type CatalogRegistration struct { Check *AgentCheck Checks HealthChecks SkipNodeUpdate bool + Partition string `json:",omitempty"` } type CatalogDeregistration struct { @@ -79,6 +82,7 @@ type CatalogDeregistration struct { ServiceID string CheckID string Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` } type CompoundServiceName struct { @@ -86,6 +90,8 @@ type CompoundServiceName struct { // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + // Partitions are a Consul Enterprise feature. + Partition string `json:",omitempty"` } // GatewayService associates a gateway with a linked service. @@ -118,11 +124,14 @@ func (c *Catalog) Register(reg *CatalogRegistration, q *WriteOptions) (*WriteMet r := c.c.newRequest("PUT", "/v1/catalog/register") r.setWriteOptions(q) r.obj = reg - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -134,11 +143,14 @@ func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*Wr r := c.c.newRequest("PUT", "/v1/catalog/deregister") r.setWriteOptions(q) r.obj = dereg - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -149,11 +161,14 @@ func (c *Catalog) Deregister(dereg *CatalogDeregistration, q *WriteOptions) (*Wr // Datacenters is used to query for all the known datacenters func (c *Catalog) Datacenters() ([]string, error) { r := c.c.newRequest("GET", "/v1/catalog/datacenters") - _, resp, err := requireOK(c.c.doRequest(r)) + _, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out []string if err := decodeBody(resp, &out); err != nil { @@ -166,11 +181,14 @@ func (c *Catalog) Datacenters() ([]string, error) { func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/catalog/nodes") r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -187,11 +205,14 @@ func (c *Catalog) Nodes(q *QueryOptions) ([]*Node, *QueryMeta, error) { func (c *Catalog) Services(q *QueryOptions) (map[string][]string, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/catalog/services") r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -244,11 +265,14 @@ func (c *Catalog) service(service string, tags []string, q *QueryOptions, connec r.params.Add("tag", tag) } } - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -265,11 +289,14 @@ func (c *Catalog) service(service string, tags []string, q *QueryOptions, connec func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/catalog/node/"+node) r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -289,11 +316,14 @@ func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, func (c *Catalog) NodeServiceList(node string, q *QueryOptions) (*CatalogNodeServiceList, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/catalog/node-services/"+node) r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -310,11 +340,14 @@ func (c *Catalog) NodeServiceList(node string, q *QueryOptions) (*CatalogNodeSer func (c *Catalog) GatewayServices(gateway string, q *QueryOptions) ([]*GatewayService, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/catalog/gateway-services/"+gateway) r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/consul/api/config_entry.go b/vendor/github.com/hashicorp/consul/api/config_entry.go index a234f6eb2..91c407bb5 100644 --- a/vendor/github.com/hashicorp/consul/api/config_entry.go +++ b/vendor/github.com/hashicorp/consul/api/config_entry.go @@ -7,6 +7,7 @@ import ( "io" "strconv" "strings" + "time" "github.com/mitchellh/mapstructure" ) @@ -19,13 +20,20 @@ const ( ServiceResolver string = "service-resolver" IngressGateway string = "ingress-gateway" TerminatingGateway string = "terminating-gateway" + ServiceIntentions string = "service-intentions" + MeshConfig string = "mesh" + ExportedServices string = "exported-services" ProxyConfigGlobal string = "global" + MeshConfigMesh string = "mesh" ) type ConfigEntry interface { GetKind() string GetName() string + GetPartition() string + GetNamespace() string + GetMeta() map[string]string GetCreateIndex() uint64 GetModifyIndex() uint64 } @@ -42,8 +50,8 @@ const ( // should be direct and not flow through a mesh gateway. MeshGatewayModeNone MeshGatewayMode = "none" - // MeshGatewayModeLocal represents that the Upstrea Connect connections - // should be made to a mesh gateway in the local datacenter. This is + // MeshGatewayModeLocal represents that the Upstream Connect connections + // should be made to a mesh gateway in the local datacenter. MeshGatewayModeLocal MeshGatewayMode = "local" // MeshGatewayModeRemote represents that the Upstream Connect connections @@ -58,6 +66,33 @@ type MeshGatewayConfig struct { Mode MeshGatewayMode `json:",omitempty"` } +type ProxyMode string + +const ( + // ProxyModeDefault represents no specific mode and should + // be used to indicate that a different layer of the configuration + // chain should take precedence + ProxyModeDefault ProxyMode = "" + + // ProxyModeTransparent represents that inbound and outbound application + // traffic is being captured and redirected through the proxy. + ProxyModeTransparent ProxyMode = "transparent" + + // ProxyModeDirect represents that the proxy's listeners must be dialed directly + // by the local application and other proxies. + ProxyModeDirect ProxyMode = "direct" +) + +type TransparentProxyConfig struct { + // The port of the listener where outbound application traffic is being redirected to. + OutboundListenerPort int `json:",omitempty" alias:"outbound_listener_port"` + + // DialedDirectly indicates whether transparent proxies can dial this proxy instance directly. + // The discovery chain is not considered when dialing a service instance directly. + // This setting is useful when addressing stateful services, such as a database cluster with a leader node. + DialedDirectly bool `json:",omitempty" alias:"dialed_directly"` +} + // ExposeConfig describes HTTP paths to expose through Envoy outside of Connect. // Users can expose individual paths and/or all HTTP/GRPC paths for checks. type ExposeConfig struct { @@ -87,62 +122,140 @@ type ExposePath struct { ParsedFromCheck bool } -type ServiceConfigEntry struct { - Kind string - Name string - Namespace string `json:",omitempty"` - Protocol string `json:",omitempty"` - MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` - Expose ExposeConfig `json:",omitempty"` - ExternalSNI string `json:",omitempty" alias:"external_sni"` - Meta map[string]string `json:",omitempty"` - CreateIndex uint64 - ModifyIndex uint64 -} +type UpstreamConfiguration struct { + // Overrides is a slice of per-service configuration. The name field is + // required. + Overrides []*UpstreamConfig `json:",omitempty"` -func (s *ServiceConfigEntry) GetKind() string { - return s.Kind + // Defaults contains default configuration for all upstreams of a given + // service. The name field must be empty. + Defaults *UpstreamConfig `json:",omitempty"` } -func (s *ServiceConfigEntry) GetName() string { - return s.Name +type UpstreamConfig struct { + // Name is only accepted within a service-defaults config entry. + Name string `json:",omitempty"` + + // Partition is only accepted within a service-defaults config entry. + Partition string `json:",omitempty"` + + // Namespace is only accepted within a service-defaults config entry. + Namespace string `json:",omitempty"` + + // EnvoyListenerJSON is a complete override ("escape hatch") for the upstream's + // listener. + // + // Note: This escape hatch is NOT compatible with the discovery chain and + // will be ignored if a discovery chain is active. + EnvoyListenerJSON string `json:",omitempty" alias:"envoy_listener_json"` + + // EnvoyClusterJSON is a complete override ("escape hatch") for the upstream's + // cluster. The Connect client TLS certificate and context will be injected + // overriding any TLS settings present. + // + // Note: This escape hatch is NOT compatible with the discovery chain and + // will be ignored if a discovery chain is active. + EnvoyClusterJSON string `json:",omitempty" alias:"envoy_cluster_json"` + + // Protocol describes the upstream's service protocol. Valid values are "tcp", + // "http" and "grpc". Anything else is treated as tcp. The enables protocol + // aware features like per-request metrics and connection pooling, tracing, + // routing etc. + Protocol string `json:",omitempty"` + + // ConnectTimeoutMs is the number of milliseconds to timeout making a new + // connection to this upstream. Defaults to 5000 (5 seconds) if not set. + ConnectTimeoutMs int `json:",omitempty" alias:"connect_timeout_ms"` + + // Limits are the set of limits that are applied to the proxy for a specific upstream of a + // service instance. + Limits *UpstreamLimits `json:",omitempty"` + + // PassiveHealthCheck configuration determines how upstream proxy instances will + // be monitored for removal from the load balancing pool. + PassiveHealthCheck *PassiveHealthCheck `json:",omitempty" alias:"passive_health_check"` + + // MeshGatewayConfig controls how Mesh Gateways are configured and used + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway" ` } -func (s *ServiceConfigEntry) GetCreateIndex() uint64 { - return s.CreateIndex +type PassiveHealthCheck struct { + // Interval between health check analysis sweeps. Each sweep may remove + // hosts or return hosts to the pool. + Interval time.Duration `json:",omitempty"` + + // MaxFailures is the count of consecutive failures that results in a host + // being removed from the pool. + MaxFailures uint32 `alias:"max_failures"` } -func (s *ServiceConfigEntry) GetModifyIndex() uint64 { - return s.ModifyIndex +// UpstreamLimits describes the limits that are associated with a specific +// upstream of a service instance. +type UpstreamLimits struct { + // MaxConnections is the maximum number of connections the local proxy can + // make to the upstream service. + MaxConnections *int `alias:"max_connections"` + + // MaxPendingRequests is the maximum number of requests that will be queued + // waiting for an available connection. This is mostly applicable to HTTP/1.1 + // clusters since all HTTP/2 requests are streamed over a single + // connection. + MaxPendingRequests *int `alias:"max_pending_requests"` + + // MaxConcurrentRequests is the maximum number of in-flight requests that will be allowed + // to the upstream cluster at a point in time. This is mostly applicable to HTTP/2 + // clusters since all HTTP/1.1 requests are limited by MaxConnections. + MaxConcurrentRequests *int `alias:"max_concurrent_requests"` } -type ProxyConfigEntry struct { - Kind string - Name string - Namespace string `json:",omitempty"` - Config map[string]interface{} `json:",omitempty"` - MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` - Expose ExposeConfig `json:",omitempty"` - Meta map[string]string `json:",omitempty"` +type ServiceConfigEntry struct { + Kind string + Name string + Partition string `json:",omitempty"` + Namespace string `json:",omitempty"` + Protocol string `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy *TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` + Expose ExposeConfig `json:",omitempty"` + ExternalSNI string `json:",omitempty" alias:"external_sni"` + UpstreamConfig *UpstreamConfiguration `json:",omitempty" alias:"upstream_config"` + + Meta map[string]string `json:",omitempty"` CreateIndex uint64 ModifyIndex uint64 } -func (p *ProxyConfigEntry) GetKind() string { - return p.Kind -} +func (s *ServiceConfigEntry) GetKind() string { return s.Kind } +func (s *ServiceConfigEntry) GetName() string { return s.Name } +func (s *ServiceConfigEntry) GetPartition() string { return s.Partition } +func (s *ServiceConfigEntry) GetNamespace() string { return s.Namespace } +func (s *ServiceConfigEntry) GetMeta() map[string]string { return s.Meta } +func (s *ServiceConfigEntry) GetCreateIndex() uint64 { return s.CreateIndex } +func (s *ServiceConfigEntry) GetModifyIndex() uint64 { return s.ModifyIndex } -func (p *ProxyConfigEntry) GetName() string { - return p.Name -} - -func (p *ProxyConfigEntry) GetCreateIndex() uint64 { - return p.CreateIndex +type ProxyConfigEntry struct { + Kind string + Name string + Partition string `json:",omitempty"` + Namespace string `json:",omitempty"` + Mode ProxyMode `json:",omitempty"` + TransparentProxy *TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"` + Config map[string]interface{} `json:",omitempty"` + MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"` + Expose ExposeConfig `json:",omitempty"` + Meta map[string]string `json:",omitempty"` + CreateIndex uint64 + ModifyIndex uint64 } -func (p *ProxyConfigEntry) GetModifyIndex() uint64 { - return p.ModifyIndex -} +func (p *ProxyConfigEntry) GetKind() string { return p.Kind } +func (p *ProxyConfigEntry) GetName() string { return p.Name } +func (p *ProxyConfigEntry) GetPartition() string { return p.Partition } +func (p *ProxyConfigEntry) GetNamespace() string { return p.Namespace } +func (p *ProxyConfigEntry) GetMeta() map[string]string { return p.Meta } +func (p *ProxyConfigEntry) GetCreateIndex() uint64 { return p.CreateIndex } +func (p *ProxyConfigEntry) GetModifyIndex() uint64 { return p.ModifyIndex } func makeConfigEntry(kind, name string) (ConfigEntry, error) { switch kind { @@ -160,6 +273,12 @@ func makeConfigEntry(kind, name string) (ConfigEntry, error) { return &IngressGatewayConfigEntry{Kind: kind, Name: name}, nil case TerminatingGateway: return &TerminatingGatewayConfigEntry{Kind: kind, Name: name}, nil + case ServiceIntentions: + return &ServiceIntentionsConfigEntry{Kind: kind, Name: name}, nil + case MeshConfig: + return &MeshConfigEntry{}, nil + case ExportedServices: + return &ExportedServicesConfigEntry{Name: name}, nil default: return nil, fmt.Errorf("invalid config entry kind: %s", kind) } @@ -202,7 +321,10 @@ func DecodeConfigEntry(raw map[string]interface{}) (ConfigEntry, error) { } decodeConf := &mapstructure.DecoderConfig{ - DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + DecodeHook: mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToTimeDurationHookFunc(), + mapstructure.StringToTimeHookFunc(time.RFC3339), + ), Result: &entry, WeaklyTypedInput: true, } @@ -258,12 +380,14 @@ func (conf *ConfigEntries) Get(kind string, name string, q *QueryOptions) (Confi r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s/%s", kind, name)) r.setQueryOptions(q) - rtt, resp, err := requireOK(conf.c.doRequest(r)) + rtt, resp, err := conf.c.doRequest(r) if err != nil { return nil, nil, err } - - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -283,12 +407,14 @@ func (conf *ConfigEntries) List(kind string, q *QueryOptions) ([]ConfigEntry, *Q r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s", kind)) r.setQueryOptions(q) - rtt, resp, err := requireOK(conf.c.doRequest(r)) + rtt, resp, err := conf.c.doRequest(r) if err != nil { return nil, nil, err } - - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -322,11 +448,14 @@ func (conf *ConfigEntries) set(entry ConfigEntry, params map[string]string, w *W r.params.Set(param, value) } r.obj = entry - rtt, resp, err := requireOK(conf.c.doRequest(r)) + rtt, resp, err := conf.c.doRequest(r) if err != nil { return false, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return false, nil, err + } var buf bytes.Buffer if _, err := io.Copy(&buf, resp.Body); err != nil { @@ -339,17 +468,45 @@ func (conf *ConfigEntries) set(entry ConfigEntry, params map[string]string, w *W } func (conf *ConfigEntries) Delete(kind string, name string, w *WriteOptions) (*WriteMeta, error) { + _, wm, err := conf.delete(kind, name, nil, w) + return wm, err +} + +// DeleteCAS performs a Check-And-Set deletion of the given config entry, and +// returns true if it was successful. If the provided index no longer matches +// the entry's ModifyIndex (i.e. it was modified by another process) then the +// operation will fail and return false. +func (conf *ConfigEntries) DeleteCAS(kind, name string, index uint64, w *WriteOptions) (bool, *WriteMeta, error) { + return conf.delete(kind, name, map[string]string{"cas": strconv.FormatUint(index, 10)}, w) +} + +func (conf *ConfigEntries) delete(kind, name string, params map[string]string, w *WriteOptions) (bool, *WriteMeta, error) { if kind == "" || name == "" { - return nil, fmt.Errorf("Both kind and name parameters must not be empty") + return false, nil, fmt.Errorf("Both kind and name parameters must not be empty") } r := conf.c.newRequest("DELETE", fmt.Sprintf("/v1/config/%s/%s", kind, name)) r.setWriteOptions(w) - rtt, resp, err := requireOK(conf.c.doRequest(r)) + for param, value := range params { + r.params.Set(param, value) + } + + rtt, resp, err := conf.c.doRequest(r) if err != nil { - return nil, err + return false, nil, err } - resp.Body.Close() + defer closeResponseBody(resp) + + if err := requireOK(resp); err != nil { + return false, nil, err + } + + var buf bytes.Buffer + if _, err := io.Copy(&buf, resp.Body); err != nil { + return false, nil, fmt.Errorf("Failed to read response: %v", err) + } + + res := strings.Contains(buf.String(), "true") wm := &WriteMeta{RequestTime: rtt} - return wm, nil + return res, wm, nil } diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go b/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go index 209106339..dfb2bcc10 100644 --- a/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go +++ b/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go @@ -8,6 +8,7 @@ import ( type ServiceRouterConfigEntry struct { Kind string Name string + Partition string `json:",omitempty"` Namespace string `json:",omitempty"` Routes []ServiceRoute `json:",omitempty"` @@ -17,10 +18,13 @@ type ServiceRouterConfigEntry struct { ModifyIndex uint64 } -func (e *ServiceRouterConfigEntry) GetKind() string { return e.Kind } -func (e *ServiceRouterConfigEntry) GetName() string { return e.Name } -func (e *ServiceRouterConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } -func (e *ServiceRouterConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } +func (e *ServiceRouterConfigEntry) GetKind() string { return e.Kind } +func (e *ServiceRouterConfigEntry) GetName() string { return e.Name } +func (e *ServiceRouterConfigEntry) GetPartition() string { return e.Partition } +func (e *ServiceRouterConfigEntry) GetNamespace() string { return e.Namespace } +func (e *ServiceRouterConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ServiceRouterConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *ServiceRouterConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } type ServiceRoute struct { Match *ServiceRouteMatch `json:",omitempty"` @@ -59,14 +63,17 @@ type ServiceRouteHTTPMatchQueryParam struct { } type ServiceRouteDestination struct { - Service string `json:",omitempty"` - ServiceSubset string `json:",omitempty" alias:"service_subset"` - Namespace string `json:",omitempty"` - PrefixRewrite string `json:",omitempty" alias:"prefix_rewrite"` - RequestTimeout time.Duration `json:",omitempty" alias:"request_timeout"` - NumRetries uint32 `json:",omitempty" alias:"num_retries"` - RetryOnConnectFailure bool `json:",omitempty" alias:"retry_on_connect_failure"` - RetryOnStatusCodes []uint32 `json:",omitempty" alias:"retry_on_status_codes"` + Service string `json:",omitempty"` + ServiceSubset string `json:",omitempty" alias:"service_subset"` + Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` + PrefixRewrite string `json:",omitempty" alias:"prefix_rewrite"` + RequestTimeout time.Duration `json:",omitempty" alias:"request_timeout"` + NumRetries uint32 `json:",omitempty" alias:"num_retries"` + RetryOnConnectFailure bool `json:",omitempty" alias:"retry_on_connect_failure"` + RetryOnStatusCodes []uint32 `json:",omitempty" alias:"retry_on_status_codes"` + RequestHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"request_headers"` + ResponseHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"response_headers"` } func (e *ServiceRouteDestination) MarshalJSON() ([]byte, error) { @@ -108,6 +115,7 @@ func (e *ServiceRouteDestination) UnmarshalJSON(data []byte) error { type ServiceSplitterConfigEntry struct { Kind string Name string + Partition string `json:",omitempty"` Namespace string `json:",omitempty"` Splits []ServiceSplit `json:",omitempty"` @@ -117,21 +125,28 @@ type ServiceSplitterConfigEntry struct { ModifyIndex uint64 } -func (e *ServiceSplitterConfigEntry) GetKind() string { return e.Kind } -func (e *ServiceSplitterConfigEntry) GetName() string { return e.Name } -func (e *ServiceSplitterConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } -func (e *ServiceSplitterConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } +func (e *ServiceSplitterConfigEntry) GetKind() string { return e.Kind } +func (e *ServiceSplitterConfigEntry) GetName() string { return e.Name } +func (e *ServiceSplitterConfigEntry) GetPartition() string { return e.Partition } +func (e *ServiceSplitterConfigEntry) GetNamespace() string { return e.Namespace } +func (e *ServiceSplitterConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ServiceSplitterConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *ServiceSplitterConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } type ServiceSplit struct { - Weight float32 - Service string `json:",omitempty"` - ServiceSubset string `json:",omitempty" alias:"service_subset"` - Namespace string `json:",omitempty"` + Weight float32 + Service string `json:",omitempty"` + ServiceSubset string `json:",omitempty" alias:"service_subset"` + Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` + RequestHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"request_headers"` + ResponseHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"response_headers"` } type ServiceResolverConfigEntry struct { Kind string Name string + Partition string `json:",omitempty"` Namespace string `json:",omitempty"` DefaultSubset string `json:",omitempty" alias:"default_subset"` @@ -140,6 +155,10 @@ type ServiceResolverConfigEntry struct { Failover map[string]ServiceResolverFailover `json:",omitempty"` ConnectTimeout time.Duration `json:",omitempty" alias:"connect_timeout"` + // LoadBalancer determines the load balancing policy and configuration for services + // issuing requests to this upstream service. + LoadBalancer *LoadBalancer `json:",omitempty" alias:"load_balancer"` + Meta map[string]string `json:",omitempty"` CreateIndex uint64 ModifyIndex uint64 @@ -181,10 +200,13 @@ func (e *ServiceResolverConfigEntry) UnmarshalJSON(data []byte) error { return nil } -func (e *ServiceResolverConfigEntry) GetKind() string { return e.Kind } -func (e *ServiceResolverConfigEntry) GetName() string { return e.Name } -func (e *ServiceResolverConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } -func (e *ServiceResolverConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } +func (e *ServiceResolverConfigEntry) GetKind() string { return e.Kind } +func (e *ServiceResolverConfigEntry) GetName() string { return e.Name } +func (e *ServiceResolverConfigEntry) GetPartition() string { return e.Partition } +func (e *ServiceResolverConfigEntry) GetNamespace() string { return e.Namespace } +func (e *ServiceResolverConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ServiceResolverConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *ServiceResolverConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } type ServiceResolverSubset struct { Filter string `json:",omitempty"` @@ -195,12 +217,105 @@ type ServiceResolverRedirect struct { Service string `json:",omitempty"` ServiceSubset string `json:",omitempty" alias:"service_subset"` Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` Datacenter string `json:",omitempty"` } type ServiceResolverFailover struct { - Service string `json:",omitempty"` - ServiceSubset string `json:",omitempty" alias:"service_subset"` - Namespace string `json:",omitempty"` - Datacenters []string `json:",omitempty"` + Service string `json:",omitempty"` + ServiceSubset string `json:",omitempty" alias:"service_subset"` + // Referencing other partitions is not supported. + Namespace string `json:",omitempty"` + Datacenters []string `json:",omitempty"` +} + +// LoadBalancer determines the load balancing policy and configuration for services +// issuing requests to this upstream service. +type LoadBalancer struct { + // Policy is the load balancing policy used to select a host + Policy string `json:",omitempty"` + + // RingHashConfig contains configuration for the "ring_hash" policy type + RingHashConfig *RingHashConfig `json:",omitempty" alias:"ring_hash_config"` + + // LeastRequestConfig contains configuration for the "least_request" policy type + LeastRequestConfig *LeastRequestConfig `json:",omitempty" alias:"least_request_config"` + + // HashPolicies is a list of hash policies to use for hashing load balancing algorithms. + // Hash policies are evaluated individually and combined such that identical lists + // result in the same hash. + // If no hash policies are present, or none are successfully evaluated, + // then a random backend host will be selected. + HashPolicies []HashPolicy `json:",omitempty" alias:"hash_policies"` +} + +// RingHashConfig contains configuration for the "ring_hash" policy type +type RingHashConfig struct { + // MinimumRingSize determines the minimum number of entries in the hash ring + MinimumRingSize uint64 `json:",omitempty" alias:"minimum_ring_size"` + + // MaximumRingSize determines the maximum number of entries in the hash ring + MaximumRingSize uint64 `json:",omitempty" alias:"maximum_ring_size"` +} + +// LeastRequestConfig contains configuration for the "least_request" policy type +type LeastRequestConfig struct { + // ChoiceCount determines the number of random healthy hosts from which to select the one with the least requests. + ChoiceCount uint32 `json:",omitempty" alias:"choice_count"` +} + +// HashPolicy defines which attributes will be hashed by hash-based LB algorithms +type HashPolicy struct { + // Field is the attribute type to hash on. + // Must be one of "header","cookie", or "query_parameter". + // Cannot be specified along with SourceIP. + Field string `json:",omitempty"` + + // FieldValue is the value to hash. + // ie. header name, cookie name, URL query parameter name + // Cannot be specified along with SourceIP. + FieldValue string `json:",omitempty" alias:"field_value"` + + // CookieConfig contains configuration for the "cookie" hash policy type. + CookieConfig *CookieConfig `json:",omitempty" alias:"cookie_config"` + + // SourceIP determines whether the hash should be of the source IP rather than of a field and field value. + // Cannot be specified along with Field or FieldValue. + SourceIP bool `json:",omitempty" alias:"source_ip"` + + // Terminal will short circuit the computation of the hash when multiple hash policies are present. + // If a hash is computed when a Terminal policy is evaluated, + // then that hash will be used and subsequent hash policies will be ignored. + Terminal bool `json:",omitempty"` +} + +// CookieConfig contains configuration for the "cookie" hash policy type. +// This is specified to have Envoy generate a cookie for a client on its first request. +type CookieConfig struct { + // Generates a session cookie with no expiration. + Session bool `json:",omitempty"` + + // TTL for generated cookies. Cannot be specified for session cookies. + TTL time.Duration `json:",omitempty"` + + // The path to set for the cookie + Path string `json:",omitempty"` +} + +// HTTPHeaderModifiers is a set of rules for HTTP header modification that +// should be performed by proxies as the request passes through them. It can +// operate on either request or response headers depending on the context in +// which it is used. +type HTTPHeaderModifiers struct { + // Add is a set of name -> value pairs that should be appended to the request + // or response (i.e. allowing duplicates if the same header already exists). + Add map[string]string `json:",omitempty"` + + // Set is a set of name -> value pairs that should be added to the request or + // response, overwriting any existing header values of the same name. + Set map[string]string `json:",omitempty"` + + // Remove is the set of header names that should be stripped from the request + // or response. + Remove []string `json:",omitempty"` } diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_exports.go b/vendor/github.com/hashicorp/consul/api/config_entry_exports.go new file mode 100644 index 000000000..ae9cb2ff6 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/config_entry_exports.go @@ -0,0 +1,72 @@ +package api + +import "encoding/json" + +// ExportedServicesConfigEntry manages the exported services for a single admin partition. +// Admin Partitions are a Consul Enterprise feature. +type ExportedServicesConfigEntry struct { + // Name is the name of the partition the ExportedServicesConfigEntry applies to. + // Partitioning is a Consul Enterprise feature. + Name string `json:",omitempty"` + + // Partition is the partition where the ExportedServicesConfigEntry is stored. + // If the partition does not match the name, the name will overwrite the partition. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Services is a list of services to be exported and the list of partitions + // to expose them to. + Services []ExportedService + + Meta map[string]string `json:",omitempty"` + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 +} + +// ExportedService manages the exporting of a service in the local partition to +// other partitions. +type ExportedService struct { + // Name is the name of the service to be exported. + Name string + + // Namespace is the namespace to export the service from. + Namespace string `json:",omitempty"` + + // Consumers is a list of downstream consumers of the service to be exported. + Consumers []ServiceConsumer +} + +// ServiceConsumer represents a downstream consumer of the service to be exported. +type ServiceConsumer struct { + // Partition is the admin partition to export the service to. + Partition string +} + +func (e *ExportedServicesConfigEntry) GetKind() string { return ExportedServices } +func (e *ExportedServicesConfigEntry) GetName() string { return e.Name } +func (e *ExportedServicesConfigEntry) GetPartition() string { return e.Name } +func (e *ExportedServicesConfigEntry) GetNamespace() string { return IntentionDefaultNamespace } +func (e *ExportedServicesConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ExportedServicesConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *ExportedServicesConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } + +// MarshalJSON adds the Kind field so that the JSON can be decoded back into the +// correct type. +func (e *ExportedServicesConfigEntry) MarshalJSON() ([]byte, error) { + type Alias ExportedServicesConfigEntry + source := &struct { + Kind string + *Alias + }{ + Kind: ExportedServices, + Alias: (*Alias)(e), + } + return json.Marshal(source) +} diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_gateways.go b/vendor/github.com/hashicorp/consul/api/config_entry_gateways.go index e259427d8..0792ad824 100644 --- a/vendor/github.com/hashicorp/consul/api/config_entry_gateways.go +++ b/vendor/github.com/hashicorp/consul/api/config_entry_gateways.go @@ -10,7 +10,11 @@ type IngressGatewayConfigEntry struct { // service. This should match the name provided in the service definition. Name string - // Namespace is the namespace the IngressGateway is associated with + // Partition is the partition the IngressGateway is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the IngressGateway is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` @@ -34,8 +38,21 @@ type IngressGatewayConfigEntry struct { } type GatewayTLSConfig struct { - // Indicates that TLS should be enabled for this gateway service + // Indicates that TLS should be enabled for this gateway service. Enabled bool + + // SDS allows configuring TLS certificate from an SDS service. + SDS *GatewayTLSSDSConfig `json:",omitempty"` +} + +type GatewayServiceTLSConfig struct { + // SDS allows configuring TLS certificate from an SDS service. + SDS *GatewayTLSSDSConfig `json:",omitempty"` +} + +type GatewayTLSSDSConfig struct { + ClusterName string `json:",omitempty" alias:"cluster_name"` + CertResource string `json:",omitempty" alias:"cert_resource"` } // IngressListener manages the configuration for a listener on a specific port. @@ -55,6 +72,9 @@ type IngressListener struct { // For "tcp" protocol listeners, only a single service is allowed. // For "http" listeners, multiple services can be declared. Services []IngressService + + // TLS allows specifying some TLS configuration per listener. + TLS *GatewayTLSConfig `json:",omitempty"` } // IngressService manages configuration for services that are exposed to @@ -67,7 +87,7 @@ type IngressService struct { // protocol and means that the listener will forward traffic to all services. // // A name can be specified on multiple listeners, and will be exposed on both - // of the listeners + // of the listeners. Name string // Hosts is a list of hostnames which should be associated to this service on @@ -86,23 +106,26 @@ type IngressService struct { // Namespace is the namespace where the service is located. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` -} -func (i *IngressGatewayConfigEntry) GetKind() string { - return i.Kind -} + // Partition is the partition where the service is located. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` -func (i *IngressGatewayConfigEntry) GetName() string { - return i.Name -} + // TLS allows specifying some TLS configuration per listener. + TLS *GatewayServiceTLSConfig `json:",omitempty"` -func (i *IngressGatewayConfigEntry) GetCreateIndex() uint64 { - return i.CreateIndex + // Allow HTTP header manipulation to be configured. + RequestHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"request_headers"` + ResponseHeaders *HTTPHeaderModifiers `json:",omitempty" alias:"response_headers"` } -func (i *IngressGatewayConfigEntry) GetModifyIndex() uint64 { - return i.ModifyIndex -} +func (i *IngressGatewayConfigEntry) GetKind() string { return i.Kind } +func (i *IngressGatewayConfigEntry) GetName() string { return i.Name } +func (i *IngressGatewayConfigEntry) GetPartition() string { return i.Partition } +func (i *IngressGatewayConfigEntry) GetNamespace() string { return i.Namespace } +func (i *IngressGatewayConfigEntry) GetMeta() map[string]string { return i.Meta } +func (i *IngressGatewayConfigEntry) GetCreateIndex() uint64 { return i.CreateIndex } +func (i *IngressGatewayConfigEntry) GetModifyIndex() uint64 { return i.ModifyIndex } // TerminatingGatewayConfigEntry manages the configuration for a terminating gateway // with the given name. @@ -128,47 +151,45 @@ type TerminatingGatewayConfigEntry struct { // queries. ModifyIndex uint64 - // Namespace is the namespace the config entry is associated with + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` } // A LinkedService is a service represented by a terminating gateway type LinkedService struct { - // The namespace the service is registered in + // Referencing other partitions is not supported. + + // Namespace is where the service is registered. Namespace string `json:",omitempty"` - // Name is the name of the service, as defined in Consul's catalog + // Name is the name of the service, as defined in Consul's catalog. Name string `json:",omitempty"` // CAFile is the optional path to a CA certificate to use for TLS connections - // from the gateway to the linked service + // from the gateway to the linked service. CAFile string `json:",omitempty" alias:"ca_file"` // CertFile is the optional path to a client certificate to use for TLS connections - // from the gateway to the linked service + // from the gateway to the linked service. CertFile string `json:",omitempty" alias:"cert_file"` // KeyFile is the optional path to a private key to use for TLS connections - // from the gateway to the linked service + // from the gateway to the linked service. KeyFile string `json:",omitempty" alias:"key_file"` - // SNI is the optional name to specify during the TLS handshake with a linked service + // SNI is the optional name to specify during the TLS handshake with a linked service. SNI string `json:",omitempty"` } -func (g *TerminatingGatewayConfigEntry) GetKind() string { - return g.Kind -} - -func (g *TerminatingGatewayConfigEntry) GetName() string { - return g.Name -} - -func (g *TerminatingGatewayConfigEntry) GetCreateIndex() uint64 { - return g.CreateIndex -} - -func (g *TerminatingGatewayConfigEntry) GetModifyIndex() uint64 { - return g.ModifyIndex -} +func (g *TerminatingGatewayConfigEntry) GetKind() string { return g.Kind } +func (g *TerminatingGatewayConfigEntry) GetName() string { return g.Name } +func (g *TerminatingGatewayConfigEntry) GetPartition() string { return g.Partition } +func (g *TerminatingGatewayConfigEntry) GetNamespace() string { return g.Namespace } +func (g *TerminatingGatewayConfigEntry) GetMeta() map[string]string { return g.Meta } +func (g *TerminatingGatewayConfigEntry) GetCreateIndex() uint64 { return g.CreateIndex } +func (g *TerminatingGatewayConfigEntry) GetModifyIndex() uint64 { return g.ModifyIndex } diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_intentions.go b/vendor/github.com/hashicorp/consul/api/config_entry_intentions.go new file mode 100644 index 000000000..3741e0a59 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/config_entry_intentions.go @@ -0,0 +1,66 @@ +package api + +import "time" + +type ServiceIntentionsConfigEntry struct { + Kind string + Name string + Partition string `json:",omitempty"` + Namespace string `json:",omitempty"` + + Sources []*SourceIntention + + Meta map[string]string `json:",omitempty"` + + CreateIndex uint64 + ModifyIndex uint64 +} + +type SourceIntention struct { + Name string + Partition string `json:",omitempty"` + Namespace string `json:",omitempty"` + Action IntentionAction `json:",omitempty"` + Permissions []*IntentionPermission `json:",omitempty"` + Precedence int + Type IntentionSourceType + Description string `json:",omitempty"` + + LegacyID string `json:",omitempty" alias:"legacy_id"` + LegacyMeta map[string]string `json:",omitempty" alias:"legacy_meta"` + LegacyCreateTime *time.Time `json:",omitempty" alias:"legacy_create_time"` + LegacyUpdateTime *time.Time `json:",omitempty" alias:"legacy_update_time"` +} + +func (e *ServiceIntentionsConfigEntry) GetKind() string { return e.Kind } +func (e *ServiceIntentionsConfigEntry) GetName() string { return e.Name } +func (e *ServiceIntentionsConfigEntry) GetPartition() string { return e.Partition } +func (e *ServiceIntentionsConfigEntry) GetNamespace() string { return e.Namespace } +func (e *ServiceIntentionsConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *ServiceIntentionsConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *ServiceIntentionsConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } + +type IntentionPermission struct { + Action IntentionAction + HTTP *IntentionHTTPPermission `json:",omitempty"` +} + +type IntentionHTTPPermission struct { + PathExact string `json:",omitempty" alias:"path_exact"` + PathPrefix string `json:",omitempty" alias:"path_prefix"` + PathRegex string `json:",omitempty" alias:"path_regex"` + + Header []IntentionHTTPHeaderPermission `json:",omitempty"` + + Methods []string `json:",omitempty"` +} + +type IntentionHTTPHeaderPermission struct { + Name string + Present bool `json:",omitempty"` + Exact string `json:",omitempty"` + Prefix string `json:",omitempty"` + Suffix string `json:",omitempty"` + Regex string `json:",omitempty"` + Invert bool `json:",omitempty"` +} diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_mesh.go b/vendor/github.com/hashicorp/consul/api/config_entry_mesh.go new file mode 100644 index 000000000..f58fabc17 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/config_entry_mesh.go @@ -0,0 +1,56 @@ +package api + +import "encoding/json" + +// MeshConfigEntry manages the global configuration for all service mesh +// proxies. +type MeshConfigEntry struct { + // Partition is the partition the MeshConfigEntry applies to. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the MeshConfigEntry applies to. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` + + // TransparentProxy applies configuration specific to proxies + // in transparent mode. + TransparentProxy TransparentProxyMeshConfig `alias:"transparent_proxy"` + + Meta map[string]string `json:",omitempty"` + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 +} + +type TransparentProxyMeshConfig struct { + MeshDestinationsOnly bool `alias:"mesh_destinations_only"` +} + +func (e *MeshConfigEntry) GetKind() string { return MeshConfig } +func (e *MeshConfigEntry) GetName() string { return MeshConfigMesh } +func (e *MeshConfigEntry) GetPartition() string { return e.Partition } +func (e *MeshConfigEntry) GetNamespace() string { return e.Namespace } +func (e *MeshConfigEntry) GetMeta() map[string]string { return e.Meta } +func (e *MeshConfigEntry) GetCreateIndex() uint64 { return e.CreateIndex } +func (e *MeshConfigEntry) GetModifyIndex() uint64 { return e.ModifyIndex } + +// MarshalJSON adds the Kind field so that the JSON can be decoded back into the +// correct type. +func (e *MeshConfigEntry) MarshalJSON() ([]byte, error) { + type Alias MeshConfigEntry + source := &struct { + Kind string + *Alias + }{ + Kind: MeshConfig, + Alias: (*Alias)(e), + } + return json.Marshal(source) +} diff --git a/vendor/github.com/hashicorp/consul/api/connect_ca.go b/vendor/github.com/hashicorp/consul/api/connect_ca.go index 26a7bfb1d..69c652dac 100644 --- a/vendor/github.com/hashicorp/consul/api/connect_ca.go +++ b/vendor/github.com/hashicorp/consul/api/connect_ca.go @@ -23,6 +23,14 @@ type CAConfig struct { // configuration is an error. State map[string]string + // ForceWithoutCrossSigning indicates that the CA reconfiguration should go + // ahead even if the current CA is unable to cross sign certificates. This + // risks temporary connection failures during the rollout as new leafs will be + // rejected by proxies that have not yet observed the new root cert but is the + // only option if a CA that doesn't support cross signing needs to be + // reconfigured or mirated away from. + ForceWithoutCrossSigning bool + CreateIndex uint64 ModifyIndex uint64 } @@ -30,6 +38,7 @@ type CAConfig struct { // CommonCAProviderConfig is the common options available to all CA providers. type CommonCAProviderConfig struct { LeafCertTTL time.Duration + RootCertTTL time.Duration SkipValidate bool CSRMaxPerSecond float32 CSRMaxConcurrent int @@ -41,7 +50,6 @@ type ConsulCAProviderConfig struct { PrivateKey string RootCert string - RotationPeriod time.Duration IntermediateCertTTL time.Duration } @@ -126,11 +134,14 @@ type LeafCert struct { func (h *Connect) CARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/connect/ca/roots") r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -147,11 +158,14 @@ func (h *Connect) CARoots(q *QueryOptions) (*CARootList, *QueryMeta, error) { func (h *Connect) CAGetConfig(q *QueryOptions) (*CAConfig, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/connect/ca/configuration") r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -169,11 +183,14 @@ func (h *Connect) CASetConfig(conf *CAConfig, q *WriteOptions) (*WriteMeta, erro r := h.c.newRequest("PUT", "/v1/connect/ca/configuration") r.setWriteOptions(q) r.obj = conf - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt diff --git a/vendor/github.com/hashicorp/consul/api/connect_intention.go b/vendor/github.com/hashicorp/consul/api/connect_intention.go index 3db177c7b..734d4ab0f 100644 --- a/vendor/github.com/hashicorp/consul/api/connect_intention.go +++ b/vendor/github.com/hashicorp/consul/api/connect_intention.go @@ -12,12 +12,12 @@ import ( // Connect. type Intention struct { // ID is the UUID-based ID for the intention, always generated by Consul. - ID string + ID string `json:",omitempty"` // Description is a human-friendly description of this intention. // It is opaque to Consul and is only stored and transferred in API // requests. - Description string + Description string `json:",omitempty"` // SourceNS, SourceName are the namespace and name, respectively, of // the source service. Either of these may be the wildcard "*", but only @@ -30,20 +30,34 @@ type Intention struct { SourceNS, SourceName string DestinationNS, DestinationName string + // SourcePartition and DestinationPartition cannot be wildcards "*" and + // are not compatible with legacy intentions. + SourcePartition string `json:",omitempty"` + DestinationPartition string `json:",omitempty"` + // SourceType is the type of the value for the source. SourceType IntentionSourceType // Action is whether this is an allowlist or denylist intention. - Action IntentionAction + Action IntentionAction `json:",omitempty"` + + // Permissions is the list of additional L7 attributes that extend the + // intention definition. + // + // NOTE: This field is not editable unless editing the underlying + // service-intentions config entry directly. + Permissions []*IntentionPermission `json:",omitempty"` - // DefaultAddr, DefaultPort of the local listening proxy (if any) to - // make this connection. - DefaultAddr string - DefaultPort int + // DefaultAddr is not used. + // Deprecated: DefaultAddr is not used and may be removed in a future version. + DefaultAddr string `json:",omitempty"` + // DefaultPort is not used. + // Deprecated: DefaultPort is not used and may be removed in a future version. + DefaultPort int `json:",omitempty"` // Meta is arbitrary metadata associated with the intention. This is // opaque to Consul but is served in API responses. - Meta map[string]string + Meta map[string]string `json:",omitempty"` // Precedence is the order that the intention will be applied, with // larger numbers being applied first. This is a read-only field, on @@ -59,7 +73,7 @@ type Intention struct { // This is needed mainly for replication purposes. When replicating from // one DC to another keeping the content Hash will allow us to detect // content changes more efficiently than checking every single field - Hash []byte + Hash []byte `json:",omitempty"` CreateIndex uint64 ModifyIndex uint64 @@ -67,10 +81,20 @@ type Intention struct { // String returns human-friendly output describing ths intention. func (i *Intention) String() string { + var detail string + switch n := len(i.Permissions); n { + case 0: + detail = string(i.Action) + case 1: + detail = "1 permission" + default: + detail = fmt.Sprintf("%d permissions", len(i.Permissions)) + } + return fmt.Sprintf("%s => %s (%s)", i.SourceString(), i.DestinationString(), - i.Action) + detail) } // SourceString returns the namespace/name format for the source, or @@ -147,11 +171,14 @@ type IntentionCheck struct { func (h *Connect) Intentions(q *QueryOptions) ([]*Intention, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/connect/intentions") r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -164,7 +191,42 @@ func (h *Connect) Intentions(q *QueryOptions) ([]*Intention, *QueryMeta, error) return out, qm, nil } +// IntentionGetExact retrieves a single intention by its unique name instead of +// its ID. +func (h *Connect) IntentionGetExact(source, destination string, q *QueryOptions) (*Intention, *QueryMeta, error) { + r := h.c.newRequest("GET", "/v1/connect/intentions/exact") + r.setQueryOptions(q) + r.params.Set("source", source) + r.params.Set("destination", destination) + rtt, resp, err := h.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + if resp.StatusCode == 404 { + return nil, qm, nil + } else if resp.StatusCode != 200 { + var buf bytes.Buffer + io.Copy(&buf, resp.Body) + return nil, nil, fmt.Errorf( + "Unexpected response %d: %s", resp.StatusCode, buf.String()) + } + + var out Intention + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return &out, qm, nil +} + // IntentionGet retrieves a single intention. +// +// Deprecated: use IntentionGetExact instead func (h *Connect) IntentionGet(id string, q *QueryOptions) (*Intention, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/connect/intentions/"+id) r.setQueryOptions(q) @@ -172,7 +234,7 @@ func (h *Connect) IntentionGet(id string, q *QueryOptions) (*Intention, *QueryMe if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -194,15 +256,42 @@ func (h *Connect) IntentionGet(id string, q *QueryOptions) (*Intention, *QueryMe return &out, qm, nil } +// IntentionDeleteExact deletes a single intention by its unique name instead of its ID. +func (h *Connect) IntentionDeleteExact(source, destination string, q *WriteOptions) (*WriteMeta, error) { + r := h.c.newRequest("DELETE", "/v1/connect/intentions/exact") + r.setWriteOptions(q) + r.params.Set("source", source) + r.params.Set("destination", destination) + + rtt, resp, err := h.c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } + + qm := &WriteMeta{} + qm.RequestTime = rtt + + return qm, nil +} + // IntentionDelete deletes a single intention. +// +// Deprecated: use IntentionDeleteExact instead func (h *Connect) IntentionDelete(id string, q *WriteOptions) (*WriteMeta, error) { r := h.c.newRequest("DELETE", "/v1/connect/intentions/"+id) r.setWriteOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } qm := &WriteMeta{} qm.RequestTime = rtt @@ -224,11 +313,14 @@ func (h *Connect) IntentionMatch(args *IntentionMatch, q *QueryOptions) (map[str for _, name := range args.Names { r.params.Add("name", name) } - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -251,11 +343,14 @@ func (h *Connect) IntentionCheck(args *IntentionCheck, q *QueryOptions) (bool, * if args.SourceType != "" { r.params.Set("source-type", string(args.SourceType)) } - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return false, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return false, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -268,18 +363,58 @@ func (h *Connect) IntentionCheck(args *IntentionCheck, q *QueryOptions) (bool, * return out.Allowed, qm, nil } +// IntentionUpsert will update an existing intention. The Source & Destination parameters +// in the structure must be non-empty. The ID must be empty. +func (c *Connect) IntentionUpsert(ixn *Intention, q *WriteOptions) (*WriteMeta, error) { + r := c.c.newRequest("PUT", "/v1/connect/intentions/exact") + r.setWriteOptions(q) + r.params.Set("source", maybePrefixNamespaceAndPartition(ixn.SourcePartition, ixn.SourceNS, ixn.SourceName)) + r.params.Set("destination", maybePrefixNamespaceAndPartition(ixn.DestinationPartition, ixn.DestinationNS, ixn.DestinationName)) + r.obj = ixn + rtt, resp, err := c.c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } + + wm := &WriteMeta{} + wm.RequestTime = rtt + return wm, nil +} + +func maybePrefixNamespaceAndPartition(part, ns, name string) string { + switch { + case part == "" && ns == "": + return name + case part == "" && ns != "": + return ns + "/" + name + case part != "" && ns == "": + return part + "/" + IntentionDefaultNamespace + "/" + name + default: + return part + "/" + ns + "/" + name + } +} + // IntentionCreate will create a new intention. The ID in the given // structure must be empty and a generate ID will be returned on // success. +// +// Deprecated: use IntentionUpsert instead func (c *Connect) IntentionCreate(ixn *Intention, q *WriteOptions) (string, *WriteMeta, error) { r := c.c.newRequest("POST", "/v1/connect/intentions") r.setWriteOptions(q) r.obj = ixn - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -293,15 +428,20 @@ func (c *Connect) IntentionCreate(ixn *Intention, q *WriteOptions) (string, *Wri // IntentionUpdate will update an existing intention. The ID in the given // structure must be non-empty. +// +// Deprecated: use IntentionUpsert instead func (c *Connect) IntentionUpdate(ixn *Intention, q *WriteOptions) (*WriteMeta, error) { r := c.c.newRequest("PUT", "/v1/connect/intentions/"+ixn.ID) r.setWriteOptions(q) r.obj = ixn - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt diff --git a/vendor/github.com/hashicorp/consul/api/coordinate.go b/vendor/github.com/hashicorp/consul/api/coordinate.go index 776630f67..7ef6ce274 100644 --- a/vendor/github.com/hashicorp/consul/api/coordinate.go +++ b/vendor/github.com/hashicorp/consul/api/coordinate.go @@ -6,9 +6,10 @@ import ( // CoordinateEntry represents a node and its associated network coordinate. type CoordinateEntry struct { - Node string - Segment string - Coord *coordinate.Coordinate + Node string + Segment string + Partition string `json:",omitempty"` + Coord *coordinate.Coordinate } // CoordinateDatacenterMap has the coordinates for servers in a given datacenter @@ -33,11 +34,14 @@ func (c *Client) Coordinate() *Coordinate { // pool. func (c *Coordinate) Datacenters() ([]*CoordinateDatacenterMap, error) { r := c.c.newRequest("GET", "/v1/coordinate/datacenters") - _, resp, err := requireOK(c.c.doRequest(r)) + _, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out []*CoordinateDatacenterMap if err := decodeBody(resp, &out); err != nil { @@ -50,11 +54,14 @@ func (c *Coordinate) Datacenters() ([]*CoordinateDatacenterMap, error) { func (c *Coordinate) Nodes(q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/coordinate/nodes") r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -72,11 +79,14 @@ func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta r := c.c.newRequest("PUT", "/v1/coordinate/update") r.setWriteOptions(q) r.obj = coord - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -88,11 +98,14 @@ func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta func (c *Coordinate) Node(node string, q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) { r := c.c.newRequest("GET", "/v1/coordinate/node/"+node) r.setQueryOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/consul/api/debug.go b/vendor/github.com/hashicorp/consul/api/debug.go index 238046853..0dfbfd846 100644 --- a/vendor/github.com/hashicorp/consul/api/debug.go +++ b/vendor/github.com/hashicorp/consul/api/debug.go @@ -1,7 +1,9 @@ package api import ( + "context" "fmt" + "io" "io/ioutil" "strconv" ) @@ -27,7 +29,10 @@ func (d *Debug) Heap() ([]byte, error) { if err != nil { return nil, fmt.Errorf("error making request: %s", err) } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } // We return a raw response because we're just passing through a response // from the pprof handlers @@ -50,7 +55,10 @@ func (d *Debug) Profile(seconds int) ([]byte, error) { if err != nil { return nil, fmt.Errorf("error making request: %s", err) } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } // We return a raw response because we're just passing through a response // from the pprof handlers @@ -62,6 +70,25 @@ func (d *Debug) Profile(seconds int) ([]byte, error) { return body, nil } +// PProf returns a pprof profile for the specified number of seconds. The caller +// is responsible for closing the returned io.ReadCloser once all bytes are read. +func (d *Debug) PProf(ctx context.Context, name string, seconds int) (io.ReadCloser, error) { + r := d.c.newRequest("GET", "/debug/pprof/"+name) + r.ctx = ctx + + // Capture a profile for the specified number of seconds + r.params.Set("seconds", strconv.Itoa(seconds)) + + _, resp, err := d.c.doRequest(r) + if err != nil { + return nil, fmt.Errorf("error making request: %s", err) + } + if err := requireOK(resp); err != nil { + return nil, err + } + return resp.Body, nil +} + // Trace returns an execution trace func (d *Debug) Trace(seconds int) ([]byte, error) { r := d.c.newRequest("GET", "/debug/pprof/trace") @@ -73,7 +100,10 @@ func (d *Debug) Trace(seconds int) ([]byte, error) { if err != nil { return nil, fmt.Errorf("error making request: %s", err) } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } // We return a raw response because we're just passing through a response // from the pprof handlers @@ -93,7 +123,10 @@ func (d *Debug) Goroutine() ([]byte, error) { if err != nil { return nil, fmt.Errorf("error making request: %s", err) } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } // We return a raw response because we're just passing through a response // from the pprof handlers diff --git a/vendor/github.com/hashicorp/consul/api/discovery_chain.go b/vendor/github.com/hashicorp/consul/api/discovery_chain.go index 75fdbaee2..29bda8591 100644 --- a/vendor/github.com/hashicorp/consul/api/discovery_chain.go +++ b/vendor/github.com/hashicorp/consul/api/discovery_chain.go @@ -38,12 +38,14 @@ func (d *DiscoveryChain) Get(name string, opts *DiscoveryChainOptions, q *QueryO if method == "POST" { r.obj = opts } - - rtt, resp, err := requireOK(d.c.doRequest(r)) + rtt, resp, err := d.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -147,6 +149,9 @@ type DiscoveryGraphNode struct { // fields for Type==resolver Resolver *DiscoveryResolver + + // shared by Type==resolver || Type==splitter + LoadBalancer *LoadBalancer `json:",omitempty"` } // compiled form of ServiceRoute diff --git a/vendor/github.com/hashicorp/consul/api/event.go b/vendor/github.com/hashicorp/consul/api/event.go index 85b5b069b..ceded6598 100644 --- a/vendor/github.com/hashicorp/consul/api/event.go +++ b/vendor/github.com/hashicorp/consul/api/event.go @@ -45,12 +45,16 @@ func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, er if params.Payload != nil { r.body = bytes.NewReader(params.Payload) } + r.header.Set("Content-Type", "application/octet-stream") - rtt, resp, err := requireOK(e.c.doRequest(r)) + rtt, resp, err := e.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{RequestTime: rtt} var out UserEvent @@ -70,11 +74,14 @@ func (e *Event) List(name string, q *QueryOptions) ([]*UserEvent, *QueryMeta, er if name != "" { r.params.Set("name", name) } - rtt, resp, err := requireOK(e.c.doRequest(r)) + rtt, resp, err := e.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/consul/api/go.mod b/vendor/github.com/hashicorp/consul/api/go.mod index d9902d403..6a37c10dd 100644 --- a/vendor/github.com/hashicorp/consul/api/go.mod +++ b/vendor/github.com/hashicorp/consul/api/go.mod @@ -5,12 +5,12 @@ go 1.12 replace github.com/hashicorp/consul/sdk => ../sdk require ( - github.com/hashicorp/consul/sdk v0.6.0 + github.com/hashicorp/consul/sdk v0.8.0 github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/go-hclog v0.12.0 github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/go-uuid v1.0.1 - github.com/hashicorp/serf v0.9.3 + github.com/hashicorp/serf v0.9.6 github.com/mitchellh/mapstructure v1.1.2 github.com/stretchr/testify v1.4.0 ) diff --git a/vendor/github.com/hashicorp/consul/api/go.sum b/vendor/github.com/hashicorp/consul/api/go.sum index 3c26420cd..16706f53f 100644 --- a/vendor/github.com/hashicorp/consul/api/go.sum +++ b/vendor/github.com/hashicorp/consul/api/go.sum @@ -7,7 +7,6 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -23,7 +22,6 @@ github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxB github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= @@ -38,32 +36,29 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.3 h1:AVF6JDQQens6nMHT9OGERBvK0f8rPrAGILnsKLr6lzM= -github.com/hashicorp/serf v0.9.3/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -83,49 +78,47 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 h1:4qWs8cYYH6PoEFy4dfhDFgoMGkwAcETd+MmPdCPMzUc= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/hashicorp/consul/api/health.go b/vendor/github.com/hashicorp/consul/api/health.go index 99b9ac257..2785c4c91 100644 --- a/vendor/github.com/hashicorp/consul/api/health.go +++ b/vendor/github.com/hashicorp/consul/api/health.go @@ -44,6 +44,7 @@ type HealthCheck struct { ServiceTags []string Type string Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` Definition HealthCheckDefinition @@ -58,6 +59,7 @@ type HealthCheckDefinition struct { Header map[string][]string Method string Body string + TLSServerName string TLSSkipVerify bool TCP string IntervalDuration time.Duration `json:"-"` @@ -229,11 +231,14 @@ func (c *Client) Health() *Health { func (h *Health) Node(node string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/health/node/"+node) r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -250,11 +255,14 @@ func (h *Health) Node(node string, q *QueryOptions) (HealthChecks, *QueryMeta, e func (h *Health) Checks(service string, q *QueryOptions) (HealthChecks, *QueryMeta, error) { r := h.c.newRequest("GET", "/v1/health/checks/"+service) r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -327,11 +335,14 @@ func (h *Health) service(service string, tags []string, passingOnly bool, q *Que if passingOnly { r.params.Set(HealthPassing, "1") } - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -357,11 +368,14 @@ func (h *Health) State(state string, q *QueryOptions) (HealthChecks, *QueryMeta, } r := h.c.newRequest("GET", "/v1/health/state/"+state) r.setQueryOptions(q) - rtt, resp, err := requireOK(h.c.doRequest(r)) + rtt, resp, err := h.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/consul/api/kv.go b/vendor/github.com/hashicorp/consul/api/kv.go index 351d287d6..85a9d7750 100644 --- a/vendor/github.com/hashicorp/consul/api/kv.go +++ b/vendor/github.com/hashicorp/consul/api/kv.go @@ -44,6 +44,10 @@ type KVPair struct { // Namespace is the namespace the KVPair is associated with // Namespacing is a Consul Enterprise feature. Namespace string `json:",omitempty"` + + // Partition is the partition the KVPair is associated with + // Admin Partition is a Consul Enterprise feature. + Partition string `json:",omitempty"` } // KVPairs is a list of KVPair objects @@ -69,7 +73,7 @@ func (k *KV) Get(key string, q *QueryOptions) (*KVPair, *QueryMeta, error) { if resp == nil { return nil, qm, nil } - defer resp.Body.Close() + defer closeResponseBody(resp) var entries []*KVPair if err := decodeBody(resp, &entries); err != nil { @@ -90,7 +94,7 @@ func (k *KV) List(prefix string, q *QueryOptions) (KVPairs, *QueryMeta, error) { if resp == nil { return nil, qm, nil } - defer resp.Body.Close() + defer closeResponseBody(resp) var entries []*KVPair if err := decodeBody(resp, &entries); err != nil { @@ -113,7 +117,7 @@ func (k *KV) Keys(prefix, separator string, q *QueryOptions) ([]string, *QueryMe if resp == nil { return nil, qm, nil } - defer resp.Body.Close() + defer closeResponseBody(resp) var entries []string if err := decodeBody(resp, &entries); err != nil { @@ -133,17 +137,20 @@ func (k *KV) getInternal(key string, params map[string]string, q *QueryOptions) return nil, nil, err } + err = requireHttpCodes(resp, 200, 404) + if err != nil { + return nil, nil, err + } + qm := &QueryMeta{} parseQueryMeta(resp, qm) qm.RequestTime = rtt if resp.StatusCode == 404 { - resp.Body.Close() + closeResponseBody(resp) return nil, qm, nil - } else if resp.StatusCode != 200 { - resp.Body.Close() - return nil, nil, fmt.Errorf("Unexpected response code: %d", resp.StatusCode) } + return resp, qm, nil } @@ -205,11 +212,15 @@ func (k *KV) put(key string, params map[string]string, body []byte, q *WriteOpti r.params.Set(param, val) } r.body = bytes.NewReader(body) - rtt, resp, err := requireOK(k.c.doRequest(r)) + r.header.Set("Content-Type", "application/octet-stream") + rtt, resp, err := k.c.doRequest(r) if err != nil { return false, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return false, nil, err + } qm := &WriteMeta{} qm.RequestTime = rtt @@ -249,11 +260,14 @@ func (k *KV) deleteInternal(key string, params map[string]string, q *WriteOption for param, val := range params { r.params.Set(param, val) } - rtt, resp, err := requireOK(k.c.doRequest(r)) + rtt, resp, err := k.c.doRequest(r) if err != nil { return false, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return false, nil, err + } qm := &WriteMeta{} qm.RequestTime = rtt diff --git a/vendor/github.com/hashicorp/consul/api/lock.go b/vendor/github.com/hashicorp/consul/api/lock.go index 5cacee8f7..221a7add3 100644 --- a/vendor/github.com/hashicorp/consul/api/lock.go +++ b/vendor/github.com/hashicorp/consul/api/lock.go @@ -79,6 +79,7 @@ type LockOptions struct { MonitorRetryTime time.Duration // Optional, defaults to DefaultMonitorRetryTime LockWaitTime time.Duration // Optional, defaults to DefaultLockWaitTime LockTryOnce bool // Optional, defaults to false which means try forever + LockDelay time.Duration // Optional, defaults to 15s Namespace string `json:",omitempty"` // Optional, defaults to API client config, namespace of ACL token, or "default" namespace } @@ -351,8 +352,9 @@ func (l *Lock) createSession() (string, error) { se := l.opts.SessionOpts if se == nil { se = &SessionEntry{ - Name: l.opts.SessionName, - TTL: l.opts.SessionTTL, + Name: l.opts.SessionName, + TTL: l.opts.SessionTTL, + LockDelay: l.opts.LockDelay, } } w := WriteOptions{Namespace: l.opts.Namespace} diff --git a/vendor/github.com/hashicorp/consul/api/namespace.go b/vendor/github.com/hashicorp/consul/api/namespace.go index 875af105f..213cd8cf4 100644 --- a/vendor/github.com/hashicorp/consul/api/namespace.go +++ b/vendor/github.com/hashicorp/consul/api/namespace.go @@ -26,7 +26,10 @@ type Namespace struct { // DeletedAt is the time when the Namespace was marked for deletion // This is nullable so that we can omit if empty when encoding in JSON - DeletedAt *time.Time `json:"DeletedAt,omitempty"` + DeletedAt *time.Time `json:"DeletedAt,omitempty" alias:"deleted_at"` + + // Partition which contains the Namespace. + Partition string `json:"Partition,omitempty"` // CreateIndex is the Raft index at which the Namespace was created CreateIndex uint64 `json:"CreateIndex,omitempty"` @@ -39,10 +42,10 @@ type Namespace struct { type NamespaceACLConfig struct { // PolicyDefaults is the list of policies that should be used for the parent authorizer // of all tokens in the associated namespace. - PolicyDefaults []ACLLink `json:"PolicyDefaults"` + PolicyDefaults []ACLLink `json:"PolicyDefaults" alias:"policy_defaults"` // RoleDefaults is the list of roles that should be used for the parent authorizer // of all tokens in the associated namespace. - RoleDefaults []ACLLink `json:"RoleDefaults"` + RoleDefaults []ACLLink `json:"RoleDefaults" alias:"role_defaults"` } // Namespaces can be used to manage Namespaces in Consul Enterprise.. @@ -63,11 +66,14 @@ func (n *Namespaces) Create(ns *Namespace, q *WriteOptions) (*Namespace, *WriteM r := n.c.newRequest("PUT", "/v1/namespace") r.setWriteOptions(q) r.obj = ns - rtt, resp, err := requireOK(n.c.doRequest(r)) + rtt, resp, err := n.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out Namespace @@ -86,11 +92,14 @@ func (n *Namespaces) Update(ns *Namespace, q *WriteOptions) (*Namespace, *WriteM r := n.c.newRequest("PUT", "/v1/namespace/"+ns.Name) r.setWriteOptions(q) r.obj = ns - rtt, resp, err := requireOK(n.c.doRequest(r)) + rtt, resp, err := n.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{RequestTime: rtt} var out Namespace @@ -105,11 +114,15 @@ func (n *Namespaces) Read(name string, q *QueryOptions) (*Namespace, *QueryMeta, var out Namespace r := n.c.newRequest("GET", "/v1/namespace/"+name) r.setQueryOptions(q) - found, rtt, resp, err := requireNotFoundOrOK(n.c.doRequest(r)) + rtt, resp, err := n.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) if err != nil { return nil, nil, err } - defer resp.Body.Close() qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -128,11 +141,14 @@ func (n *Namespaces) Read(name string, q *QueryOptions) (*Namespace, *QueryMeta, func (n *Namespaces) Delete(name string, q *WriteOptions) (*WriteMeta, error) { r := n.c.newRequest("DELETE", "/v1/namespace/"+name) r.setWriteOptions(q) - rtt, resp, err := requireOK(n.c.doRequest(r)) + rtt, resp, err := n.c.doRequest(r) if err != nil { return nil, err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{RequestTime: rtt} return wm, nil @@ -142,11 +158,14 @@ func (n *Namespaces) List(q *QueryOptions) ([]*Namespace, *QueryMeta, error) { var out []*Namespace r := n.c.newRequest("GET", "/v1/namespaces") r.setQueryOptions(q) - rtt, resp, err := requireOK(n.c.doRequest(r)) + rtt, resp, err := n.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/consul/api/operator_area.go b/vendor/github.com/hashicorp/consul/api/operator_area.go index 5cf7e4973..f9fa1339e 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_area.go +++ b/vendor/github.com/hashicorp/consul/api/operator_area.go @@ -89,11 +89,14 @@ func (op *Operator) AreaCreate(area *Area, q *WriteOptions) (string, *WriteMeta, r := op.c.newRequest("POST", "/v1/operator/area") r.setWriteOptions(q) r.obj = area - rtt, resp, err := requireOK(op.c.doRequest(r)) + rtt, resp, err := op.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -110,11 +113,14 @@ func (op *Operator) AreaUpdate(areaID string, area *Area, q *WriteOptions) (stri r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID) r.setWriteOptions(q) r.obj = area - rtt, resp, err := requireOK(op.c.doRequest(r)) + rtt, resp, err := op.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -150,11 +156,14 @@ func (op *Operator) AreaList(q *QueryOptions) ([]*Area, *QueryMeta, error) { func (op *Operator) AreaDelete(areaID string, q *WriteOptions) (*WriteMeta, error) { r := op.c.newRequest("DELETE", "/v1/operator/area/"+areaID) r.setWriteOptions(q) - rtt, resp, err := requireOK(op.c.doRequest(r)) + rtt, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -167,11 +176,14 @@ func (op *Operator) AreaJoin(areaID string, addresses []string, q *WriteOptions) r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID+"/join") r.setWriteOptions(q) r.obj = addresses - rtt, resp, err := requireOK(op.c.doRequest(r)) + rtt, resp, err := op.c.doRequest(r) if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt diff --git a/vendor/github.com/hashicorp/consul/api/operator_autopilot.go b/vendor/github.com/hashicorp/consul/api/operator_autopilot.go index 0e4ef2464..6ab576970 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_autopilot.go +++ b/vendor/github.com/hashicorp/consul/api/operator_autopilot.go @@ -58,6 +58,23 @@ type AutopilotConfiguration struct { ModifyIndex uint64 } +// Defines default values for the AutopilotConfiguration type, consistent with +// https://www.consul.io/api-docs/operator/autopilot#parameters-1 +func NewAutopilotConfiguration() AutopilotConfiguration { + cfg := AutopilotConfiguration{ + CleanupDeadServers: true, + LastContactThreshold: NewReadableDuration(200 * time.Millisecond), + MaxTrailingLogs: 250, + MinQuorum: 0, + ServerStabilizationTime: NewReadableDuration(10 * time.Second), + RedundancyZoneTag: "", + DisableUpgradeMigration: false, + UpgradeVersionTag: "", + } + + return cfg +} + // ServerHealth is the health (from the leader's point of view) of a server. type ServerHealth struct { // ID is the raft ID of the server. @@ -111,6 +128,122 @@ type OperatorHealthReply struct { Servers []ServerHealth } +type AutopilotState struct { + Healthy bool + FailureTolerance int + OptimisticFailureTolerance int + + Servers map[string]AutopilotServer + Leader string + Voters []string + ReadReplicas []string `json:",omitempty"` + RedundancyZones map[string]AutopilotZone `json:",omitempty"` + Upgrade *AutopilotUpgrade `json:",omitempty"` +} + +type AutopilotServer struct { + ID string + Name string + Address string + NodeStatus string + Version string + LastContact *ReadableDuration + LastTerm uint64 + LastIndex uint64 + Healthy bool + StableSince time.Time + RedundancyZone string `json:",omitempty"` + UpgradeVersion string `json:",omitempty"` + ReadReplica bool + Status AutopilotServerStatus + Meta map[string]string + NodeType AutopilotServerType +} + +type AutopilotServerStatus string + +const ( + AutopilotServerNone AutopilotServerStatus = "none" + AutopilotServerLeader AutopilotServerStatus = "leader" + AutopilotServerVoter AutopilotServerStatus = "voter" + AutopilotServerNonVoter AutopilotServerStatus = "non-voter" + AutopilotServerStaging AutopilotServerStatus = "staging" +) + +type AutopilotServerType string + +const ( + AutopilotTypeVoter AutopilotServerType = "voter" + AutopilotTypeReadReplica AutopilotServerType = "read-replica" + AutopilotTypeZoneVoter AutopilotServerType = "zone-voter" + AutopilotTypeZoneExtraVoter AutopilotServerType = "zone-extra-voter" + AutopilotTypeZoneStandby AutopilotServerType = "zone-standby" +) + +type AutopilotZone struct { + Servers []string + Voters []string + FailureTolerance int +} + +type AutopilotZoneUpgradeVersions struct { + TargetVersionVoters []string `json:",omitempty"` + TargetVersionNonVoters []string `json:",omitempty"` + OtherVersionVoters []string `json:",omitempty"` + OtherVersionNonVoters []string `json:",omitempty"` +} + +type AutopilotUpgrade struct { + Status AutopilotUpgradeStatus + TargetVersion string `json:",omitempty"` + TargetVersionVoters []string `json:",omitempty"` + TargetVersionNonVoters []string `json:",omitempty"` + TargetVersionReadReplicas []string `json:",omitempty"` + OtherVersionVoters []string `json:",omitempty"` + OtherVersionNonVoters []string `json:",omitempty"` + OtherVersionReadReplicas []string `json:",omitempty"` + RedundancyZones map[string]AutopilotZoneUpgradeVersions `json:",omitempty"` +} + +type AutopilotUpgradeStatus string + +const ( + // AutopilotUpgradeIdle is the status when no upgrade is in progress. + AutopilotUpgradeIdle AutopilotUpgradeStatus = "idle" + + // AutopilotUpgradeAwaitNewVoters is the status when more servers of + // the target version must be added in order to start the promotion + // phase of the upgrade + AutopilotUpgradeAwaitNewVoters AutopilotUpgradeStatus = "await-new-voters" + + // AutopilotUpgradePromoting is the status when autopilot is promoting + // servers of the target version. + AutopilotUpgradePromoting AutopilotUpgradeStatus = "promoting" + + // AutopilotUpgradeDemoting is the status when autopilot is demoting + // servers not on the target version + AutopilotUpgradeDemoting AutopilotUpgradeStatus = "demoting" + + // AutopilotUpgradeLeaderTransfer is the status when autopilot is transferring + // leadership from a server running an older version to a server + // using the target version. + AutopilotUpgradeLeaderTransfer AutopilotUpgradeStatus = "leader-transfer" + + // AutopilotUpgradeAwaitNewServers is the status when autpilot has finished + // transferring leadership and has demoted all the other versioned + // servers but wants to indicate that more target version servers + // are needed to replace all the existing other version servers. + AutopilotUpgradeAwaitNewServers AutopilotUpgradeStatus = "await-new-servers" + + // AutopilotUpgradeAwaitServerRemoval is the status when autopilot is waiting + // for the servers on non-target versions to be removed + AutopilotUpgradeAwaitServerRemoval AutopilotUpgradeStatus = "await-server-removal" + + // AutopilotUpgradeDisabled is the status when automated ugprades are + // disabled in the autopilot configuration + AutopilotUpgradeDisabled AutopilotUpgradeStatus = "disabled" +) + // ReadableDuration is a duration type that is serialized to JSON in human readable format. type ReadableDuration time.Duration @@ -164,11 +297,14 @@ func (d *ReadableDuration) UnmarshalJSON(raw []byte) (err error) { func (op *Operator) AutopilotGetConfiguration(q *QueryOptions) (*AutopilotConfiguration, error) { r := op.c.newRequest("GET", "/v1/operator/autopilot/configuration") r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out AutopilotConfiguration if err := decodeBody(resp, &out); err != nil { @@ -183,11 +319,14 @@ func (op *Operator) AutopilotSetConfiguration(conf *AutopilotConfiguration, q *W r := op.c.newRequest("PUT", "/v1/operator/autopilot/configuration") r.setWriteOptions(q) r.obj = conf - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -199,11 +338,14 @@ func (op *Operator) AutopilotCASConfiguration(conf *AutopilotConfiguration, q *W r.setWriteOptions(q) r.params.Set("cas", strconv.FormatUint(conf.ModifyIndex, 10)) r.obj = conf - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return false, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return false, err + } var buf bytes.Buffer if _, err := io.Copy(&buf, resp.Body); err != nil { @@ -218,11 +360,18 @@ func (op *Operator) AutopilotCASConfiguration(conf *AutopilotConfiguration, q *W func (op *Operator) AutopilotServerHealth(q *QueryOptions) (*OperatorHealthReply, error) { r := op.c.newRequest("GET", "/v1/operator/autopilot/health") r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) + + // we use 429 status to indicate unhealthiness + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + err = requireHttpCodes(resp, 200, 429) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) var out OperatorHealthReply if err := decodeBody(resp, &out); err != nil { @@ -230,3 +379,23 @@ func (op *Operator) AutopilotServerHealth(q *QueryOptions) (*OperatorHealthReply } return &out, nil } + +func (op *Operator) AutopilotState(q *QueryOptions) (*AutopilotState, error) { + r := op.c.newRequest("GET", "/v1/operator/autopilot/state") + r.setQueryOptions(q) + _, resp, err := op.c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } + + var out AutopilotState + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + + return &out, nil +} diff --git a/vendor/github.com/hashicorp/consul/api/operator_keyring.go b/vendor/github.com/hashicorp/consul/api/operator_keyring.go index 5b80f9f91..6db31a252 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_keyring.go +++ b/vendor/github.com/hashicorp/consul/api/operator_keyring.go @@ -16,6 +16,9 @@ type KeyringResponse struct { // Segment has the network segment this request corresponds to. Segment string + // Partition has the admin partition this request corresponds to. + Partition string `json:",omitempty"` + // Messages has information or errors from serf Messages map[string]string `json:",omitempty"` @@ -36,11 +39,14 @@ func (op *Operator) KeyringInstall(key string, q *WriteOptions) error { r.obj = keyringRequest{ Key: key, } - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -48,11 +54,14 @@ func (op *Operator) KeyringInstall(key string, q *WriteOptions) error { func (op *Operator) KeyringList(q *QueryOptions) ([]*KeyringResponse, error) { r := op.c.newRequest("GET", "/v1/operator/keyring") r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out []*KeyringResponse if err := decodeBody(resp, &out); err != nil { @@ -68,11 +77,14 @@ func (op *Operator) KeyringRemove(key string, q *WriteOptions) error { r.obj = keyringRequest{ Key: key, } - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -83,10 +95,13 @@ func (op *Operator) KeyringUse(key string, q *WriteOptions) error { r.obj = keyringRequest{ Key: key, } - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } diff --git a/vendor/github.com/hashicorp/consul/api/operator_license.go b/vendor/github.com/hashicorp/consul/api/operator_license.go index 51b64cef4..7b654317c 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_license.go +++ b/vendor/github.com/hashicorp/consul/api/operator_license.go @@ -62,11 +62,14 @@ func (op *Operator) LicenseGetSigned(q *QueryOptions) (string, error) { r := op.c.newRequest("GET", "/v1/operator/license") r.params.Set("signed", "1") r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return "", err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", err + } data, err := ioutil.ReadAll(resp.Body) if err != nil { @@ -78,33 +81,44 @@ func (op *Operator) LicenseGetSigned(q *QueryOptions) (string, error) { // LicenseReset will reset the license to the builtin one if it is still valid. // If the builtin license is invalid, the current license stays active. +// +// DEPRECATED: Consul 1.10 removes the corresponding HTTP endpoint as licenses +// are now set via agent configuration instead of through the API func (op *Operator) LicenseReset(opts *WriteOptions) (*LicenseReply, error) { var reply LicenseReply r := op.c.newRequest("DELETE", "/v1/operator/license") r.setWriteOptions(opts) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() - + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } if err := decodeBody(resp, &reply); err != nil { return nil, err } - return &reply, nil } +// LicensePut will configure the Consul Enterprise license for the target datacenter +// +// DEPRECATED: Consul 1.10 removes the corresponding HTTP endpoint as licenses +// are now set via agent configuration instead of through the API func (op *Operator) LicensePut(license string, opts *WriteOptions) (*LicenseReply, error) { var reply LicenseReply r := op.c.newRequest("PUT", "/v1/operator/license") r.setWriteOptions(opts) r.body = strings.NewReader(license) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } if err := decodeBody(resp, &reply); err != nil { return nil, err diff --git a/vendor/github.com/hashicorp/consul/api/operator_raft.go b/vendor/github.com/hashicorp/consul/api/operator_raft.go index c6d7165d4..1b48fdcd9 100644 --- a/vendor/github.com/hashicorp/consul/api/operator_raft.go +++ b/vendor/github.com/hashicorp/consul/api/operator_raft.go @@ -40,11 +40,14 @@ type RaftConfiguration struct { func (op *Operator) RaftGetConfiguration(q *QueryOptions) (*RaftConfiguration, error) { r := op.c.newRequest("GET", "/v1/operator/raft/configuration") r.setQueryOptions(q) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var out RaftConfiguration if err := decodeBody(resp, &out); err != nil { @@ -62,12 +65,14 @@ func (op *Operator) RaftRemovePeerByAddress(address string, q *WriteOptions) err r.params.Set("address", address) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } @@ -79,11 +84,13 @@ func (op *Operator) RaftRemovePeerByID(id string, q *WriteOptions) error { r.params.Set("id", id) - _, resp, err := requireOK(op.c.doRequest(r)) + _, resp, err := op.c.doRequest(r) if err != nil { return err } - - resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return err + } return nil } diff --git a/vendor/github.com/hashicorp/consul/api/partition.go b/vendor/github.com/hashicorp/consul/api/partition.go new file mode 100644 index 000000000..88edfb7b0 --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/partition.go @@ -0,0 +1,164 @@ +package api + +import ( + "context" + "fmt" + "time" +) + +// Partition is the configuration of a single admin partition. Admin Partitions are a Consul Enterprise feature. +type Partition struct { + // Name is the name of the Partition. + Name string `json:"Name"` + + // Description is where the user puts any information they want + // about the admin partition. It is not used internally. + Description string `json:"Description,omitempty"` + + // DeletedAt is the time when the Partition was marked for deletion + // This is nullable so that we can omit if empty when encoding in JSON + DeletedAt *time.Time `json:"DeletedAt,omitempty" alias:"deleted_at"` + + // CreateIndex is the Raft index at which the Partition was created + CreateIndex uint64 `json:"CreateIndex,omitempty"` + + // ModifyIndex is the latest Raft index at which the Partition was modified. + ModifyIndex uint64 `json:"ModifyIndex,omitempty"` +} + +// PartitionDefaultName is the default partition value. +const PartitionDefaultName = "default" + +// Partitions can be used to manage Partitions in Consul Enterprise. +type Partitions struct { + c *Client +} + +// Operator returns a handle to the operator endpoints. +func (c *Client) Partitions() *Partitions { + return &Partitions{c} +} + +func (p *Partitions) Create(ctx context.Context, partition *Partition, q *WriteOptions) (*Partition, *WriteMeta, error) { + if partition.Name == "" { + return nil, nil, fmt.Errorf("Must specify a Name for Partition creation") + } + + r := p.c.newRequest("PUT", "/v1/partition") + r.setWriteOptions(q) + r.ctx = ctx + r.obj = partition + rtt, resp, err := p.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + + wm := &WriteMeta{RequestTime: rtt} + var out Partition + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + + return &out, wm, nil +} + +func (p *Partitions) Update(ctx context.Context, partition *Partition, q *WriteOptions) (*Partition, *WriteMeta, error) { + if partition.Name == "" { + return nil, nil, fmt.Errorf("Must specify a Name for Partition updating") + } + + r := p.c.newRequest("PUT", "/v1/partition/"+partition.Name) + r.setWriteOptions(q) + r.ctx = ctx + r.obj = partition + rtt, resp, err := p.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + + wm := &WriteMeta{RequestTime: rtt} + var out Partition + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + + return &out, wm, nil +} + +func (p *Partitions) Read(ctx context.Context, name string, q *QueryOptions) (*Partition, *QueryMeta, error) { + var out Partition + r := p.c.newRequest("GET", "/v1/partition/"+name) + r.setQueryOptions(q) + r.ctx = ctx + rtt, resp, err := p.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + found, resp, err := requireNotFoundOrOK(resp) + if err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + if !found { + return nil, qm, nil + } + + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return &out, qm, nil +} + +func (p *Partitions) Delete(ctx context.Context, name string, q *WriteOptions) (*WriteMeta, error) { + r := p.c.newRequest("DELETE", "/v1/partition/"+name) + r.setWriteOptions(q) + r.ctx = ctx + rtt, resp, err := p.c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } + + wm := &WriteMeta{RequestTime: rtt} + return wm, nil +} + +func (p *Partitions) List(ctx context.Context, q *QueryOptions) ([]*Partition, *QueryMeta, error) { + var out []*Partition + r := p.c.newRequest("GET", "/v1/partitions") + r.setQueryOptions(q) + r.ctx = ctx + rtt, resp, err := p.c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + if err := decodeBody(resp, &out); err != nil { + return nil, nil, err + } + return out, qm, nil +} diff --git a/vendor/github.com/hashicorp/consul/api/prepared_query.go b/vendor/github.com/hashicorp/consul/api/prepared_query.go index 5ac2535c7..b3dd7be6f 100644 --- a/vendor/github.com/hashicorp/consul/api/prepared_query.go +++ b/vendor/github.com/hashicorp/consul/api/prepared_query.go @@ -154,11 +154,14 @@ func (c *PreparedQuery) Create(query *PreparedQueryDefinition, q *WriteOptions) r := c.c.newRequest("POST", "/v1/query") r.setWriteOptions(q) r.obj = query - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return "", nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt @@ -200,11 +203,14 @@ func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDe func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) { r := c.c.newRequest("DELETE", "/v1/query/"+queryID) r.setWriteOptions(q) - rtt, resp, err := requireOK(c.c.doRequest(r)) + rtt, resp, err := c.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } wm := &WriteMeta{} wm.RequestTime = rtt diff --git a/vendor/github.com/hashicorp/consul/api/session.go b/vendor/github.com/hashicorp/consul/api/session.go index 157ad53f5..3f61acfbb 100644 --- a/vendor/github.com/hashicorp/consul/api/session.go +++ b/vendor/github.com/hashicorp/consul/api/session.go @@ -141,7 +141,7 @@ func (s *Session) Renew(id string, q *WriteOptions) (*SessionEntry, *WriteMeta, if err != nil { return nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) wm := &WriteMeta{RequestTime: rtt} diff --git a/vendor/github.com/hashicorp/consul/api/snapshot.go b/vendor/github.com/hashicorp/consul/api/snapshot.go index e902377dd..b526b79c3 100644 --- a/vendor/github.com/hashicorp/consul/api/snapshot.go +++ b/vendor/github.com/hashicorp/consul/api/snapshot.go @@ -23,10 +23,13 @@ func (s *Snapshot) Save(q *QueryOptions) (io.ReadCloser, *QueryMeta, error) { r := s.c.newRequest("GET", "/v1/snapshot") r.setQueryOptions(q) - rtt, resp, err := requireOK(s.c.doRequest(r)) + rtt, resp, err := s.c.doRequest(r) if err != nil { return nil, nil, err } + if err := requireOK(resp); err != nil { + return nil, nil, err + } qm := &QueryMeta{} parseQueryMeta(resp, qm) @@ -38,10 +41,14 @@ func (s *Snapshot) Save(q *QueryOptions) (io.ReadCloser, *QueryMeta, error) { func (s *Snapshot) Restore(q *WriteOptions, in io.Reader) error { r := s.c.newRequest("PUT", "/v1/snapshot") r.body = in + r.header.Set("Content-Type", "application/octet-stream") r.setWriteOptions(q) - _, _, err := requireOK(s.c.doRequest(r)) + _, resp, err := s.c.doRequest(r) if err != nil { return err } + if err := requireOK(resp); err != nil { + return err + } return nil } diff --git a/vendor/github.com/hashicorp/consul/api/status.go b/vendor/github.com/hashicorp/consul/api/status.go index 74ef61a67..86f943bc7 100644 --- a/vendor/github.com/hashicorp/consul/api/status.go +++ b/vendor/github.com/hashicorp/consul/api/status.go @@ -11,13 +11,21 @@ func (c *Client) Status() *Status { } // Leader is used to query for a known leader -func (s *Status) Leader() (string, error) { +func (s *Status) LeaderWithQueryOptions(q *QueryOptions) (string, error) { r := s.c.newRequest("GET", "/v1/status/leader") - _, resp, err := requireOK(s.c.doRequest(r)) + + if q != nil { + r.setQueryOptions(q) + } + + _, resp, err := s.c.doRequest(r) if err != nil { return "", err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return "", err + } var leader string if err := decodeBody(resp, &leader); err != nil { @@ -26,14 +34,26 @@ func (s *Status) Leader() (string, error) { return leader, nil } +func (s *Status) Leader() (string, error) { + return s.LeaderWithQueryOptions(nil) +} + // Peers is used to query for a known raft peers -func (s *Status) Peers() ([]string, error) { +func (s *Status) PeersWithQueryOptions(q *QueryOptions) ([]string, error) { r := s.c.newRequest("GET", "/v1/status/peers") - _, resp, err := requireOK(s.c.doRequest(r)) + + if q != nil { + r.setQueryOptions(q) + } + + _, resp, err := s.c.doRequest(r) if err != nil { return nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } var peers []string if err := decodeBody(resp, &peers); err != nil { @@ -41,3 +61,7 @@ func (s *Status) Peers() ([]string, error) { } return peers, nil } + +func (s *Status) Peers() ([]string, error) { + return s.PeersWithQueryOptions(nil) +} diff --git a/vendor/github.com/hashicorp/consul/api/txn.go b/vendor/github.com/hashicorp/consul/api/txn.go index ef06bcbfe..59fd1c0d9 100644 --- a/vendor/github.com/hashicorp/consul/api/txn.go +++ b/vendor/github.com/hashicorp/consul/api/txn.go @@ -82,6 +82,7 @@ type KVTxnOp struct { Index uint64 Session string Namespace string `json:",omitempty"` + Partition string `json:",omitempty"` } // KVTxnOps defines a set of operations to be performed inside a single @@ -221,7 +222,7 @@ func (c *Client) txn(txn TxnOps, q *QueryOptions) (bool, *TxnResponse, *QueryMet if err != nil { return false, nil, nil, err } - defer resp.Body.Close() + defer closeResponseBody(resp) qm := &QueryMeta{} parseQueryMeta(resp, qm) diff --git a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go index 8d306bf51..fe28d15b6 100644 --- a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go +++ b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go @@ -32,6 +32,7 @@ func DefaultPooledTransport() *http.Transport { IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, + ForceAttemptHTTP2: true, MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, } return transport diff --git a/vendor/github.com/hashicorp/go-cleanhttp/go.mod b/vendor/github.com/hashicorp/go-cleanhttp/go.mod index 310f07569..005ccdef9 100644 --- a/vendor/github.com/hashicorp/go-cleanhttp/go.mod +++ b/vendor/github.com/hashicorp/go-cleanhttp/go.mod @@ -1 +1,3 @@ module github.com/hashicorp/go-cleanhttp + +go 1.13 diff --git a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go index 08a6677eb..631baf2f0 100644 --- a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go @@ -18,8 +18,13 @@ type interceptLogger struct { } func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and interceptLogger.log + l.callerOffset += 2 + } intercept := &interceptLogger{ - Logger: New(opts), + Logger: l, mu: new(sync.Mutex), sinkCount: new(int32), Sinks: make(map[SinkAdapter]struct{}), @@ -31,6 +36,14 @@ func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { } func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { + i.log(level, msg, args...) +} + +// log is used to make the caller stack frame lookup consistent. If Warn,Info,etc +// all called Log then direct calls to Log would have a different stack frame +// depth. By having all the methods call the same helper we ensure the stack +// frame depth is the same. +func (i *interceptLogger) log(level Level, msg string, args ...interface{}) { i.Logger.Log(level, msg, args...) if atomic.LoadInt32(i.sinkCount) == 0 { return @@ -45,72 +58,27 @@ func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { // Emit the message and args at TRACE level to log and sinks func (i *interceptLogger) Trace(msg string, args ...interface{}) { - i.Logger.Trace(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Trace, msg, i.retrieveImplied(args...)...) - } + i.log(Trace, msg, args...) } // Emit the message and args at DEBUG level to log and sinks func (i *interceptLogger) Debug(msg string, args ...interface{}) { - i.Logger.Debug(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Debug, msg, i.retrieveImplied(args...)...) - } + i.log(Debug, msg, args...) } // Emit the message and args at INFO level to log and sinks func (i *interceptLogger) Info(msg string, args ...interface{}) { - i.Logger.Info(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Info, msg, i.retrieveImplied(args...)...) - } + i.log(Info, msg, args...) } // Emit the message and args at WARN level to log and sinks func (i *interceptLogger) Warn(msg string, args ...interface{}) { - i.Logger.Warn(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Warn, msg, i.retrieveImplied(args...)...) - } + i.log(Warn, msg, args...) } // Emit the message and args at ERROR level to log and sinks func (i *interceptLogger) Error(msg string, args ...interface{}) { - i.Logger.Error(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Error, msg, i.retrieveImplied(args...)...) - } + i.log(Error, msg, args...) } func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { @@ -123,17 +91,11 @@ func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { return cp } -// Create a new sub-Logger that a name decending from the current name. +// Create a new sub-Logger that a name descending from the current name. // This is used to create a subsystem specific Logger. // Registered sinks will subscribe to these messages as well. func (i *interceptLogger) Named(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.Named(name) - - return &sub + return i.NamedIntercept(name) } // Create a new sub-Logger with an explicit name. This ignores the current @@ -141,13 +103,7 @@ func (i *interceptLogger) Named(name string) Logger { // within the normal hierarchy. Registered sinks will subscribe // to these messages as well. func (i *interceptLogger) ResetNamed(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.ResetNamed(name) - - return &sub + return i.ResetNamedIntercept(name) } // Create a new sub-Logger that a name decending from the current name. @@ -157,9 +113,7 @@ func (i *interceptLogger) NamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.Named(name) - return &sub } @@ -171,9 +125,7 @@ func (i *interceptLogger) ResetNamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.ResetNamed(name) - return &sub } @@ -210,18 +162,23 @@ func (i *interceptLogger) DeregisterSink(sink SinkAdapter) { atomic.AddInt32(i.sinkCount, -1) } -// Create a *log.Logger that will send it's data through this Logger. This -// allows packages that expect to be using the standard library to log to -// actually use this logger, which will also send to any registered sinks. func (i *interceptLogger) StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger { + return i.StandardLogger(opts) +} + +func (i *interceptLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { if opts == nil { opts = &StandardLoggerOptions{} } - return log.New(i.StandardWriterIntercept(opts), "", 0) + return log.New(i.StandardWriter(opts), "", 0) } func (i *interceptLogger) StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer { + return i.StandardWriter(opts) +} + +func (i *interceptLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { return &stdlogAdapter{ log: i, inferLevels: opts.InferLevels, diff --git a/vendor/github.com/hashicorp/go-hclog/intlogger.go b/vendor/github.com/hashicorp/go-hclog/intlogger.go index 7158125de..fd51af141 100644 --- a/vendor/github.com/hashicorp/go-hclog/intlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/intlogger.go @@ -10,7 +10,6 @@ import ( "log" "os" "reflect" - "regexp" "runtime" "sort" "strconv" @@ -22,10 +21,14 @@ import ( "github.com/fatih/color" ) -// TimeFormat to use for logging. This is a version of RFC3339 that contains -// contains millisecond precision +// TimeFormat is the time format to use for plain (non-JSON) output. +// This is a version of RFC3339 that contains millisecond precision. const TimeFormat = "2006-01-02T15:04:05.000Z0700" +// TimeFormatJSON is the time format to use for JSON output. +// This is a version of RFC3339 that contains microsecond precision. +const TimeFormatJSON = "2006-01-02T15:04:05.000000Z07:00" + // errJsonUnsupportedTypeMsg is included in log json entries, if an arg cannot be serialized to json const errJsonUnsupportedTypeMsg = "logging contained values that don't serialize to json" @@ -53,10 +56,11 @@ var _ Logger = &intLogger{} // intLogger is an internal logger implementation. Internal in that it is // defined entirely by this package. type intLogger struct { - json bool - caller bool - name string - timeFormat string + json bool + callerOffset int + name string + timeFormat string + disableTime bool // This is an interface so that it's shared by any derived loggers, since // those derived loggers share the bufio.Writer as well. @@ -67,6 +71,9 @@ type intLogger struct { implied []interface{} exclude func(level Level, msg string, args ...interface{}) bool + + // create subloggers with their own level setting + independentLevels bool } // New returns a configured logger. @@ -77,7 +84,12 @@ func New(opts *LoggerOptions) Logger { // NewSinkAdapter returns a SinkAdapter with configured settings // defined by LoggerOptions func NewSinkAdapter(opts *LoggerOptions) SinkAdapter { - return newLogger(opts) + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and SinkAdapter.Accept + l.callerOffset += 2 + } + return l } func newLogger(opts *LoggerOptions) *intLogger { @@ -101,29 +113,38 @@ func newLogger(opts *LoggerOptions) *intLogger { } l := &intLogger{ - json: opts.JSONFormat, - caller: opts.IncludeLocation, - name: opts.Name, - timeFormat: TimeFormat, - mutex: mutex, - writer: newWriter(output, opts.Color), - level: new(int32), - exclude: opts.Exclude, + json: opts.JSONFormat, + name: opts.Name, + timeFormat: TimeFormat, + disableTime: opts.DisableTime, + mutex: mutex, + writer: newWriter(output, opts.Color), + level: new(int32), + exclude: opts.Exclude, + independentLevels: opts.IndependentLevels, + } + if opts.IncludeLocation { + l.callerOffset = offsetIntLogger + opts.AdditionalLocationOffset } - l.setColorization(opts) - - if opts.DisableTime { - l.timeFormat = "" - } else if opts.TimeFormat != "" { + if l.json { + l.timeFormat = TimeFormatJSON + } + if opts.TimeFormat != "" { l.timeFormat = opts.TimeFormat } + l.setColorization(opts) + atomic.StoreInt32(l.level, int32(level)) return l } +// offsetIntLogger is the stack frame offset in the call stack for the caller to +// one of the Warn,Info,Log,etc methods. +const offsetIntLogger = 3 + // Log a message and a set of key/value pairs if the given level is at // or more severe that the threshold configured in the Logger. func (l *intLogger) log(name string, level Level, msg string, args ...interface{}) { @@ -178,11 +199,28 @@ func trimCallerPath(path string) string { return path[idx+1:] } -var logImplFile = regexp.MustCompile(`.+intlogger.go|.+interceptlogger.go$`) +// isNormal indicates if the rune is one allowed to exist as an unquoted +// string value. This is a subset of ASCII, `-` through `~`. +func isNormal(r rune) bool { + return 0x2D <= r && r <= 0x7E // - through ~ +} + +// needsQuoting returns false if all the runes in string are normal, according +// to isNormal +func needsQuoting(str string) bool { + for _, r := range str { + if !isNormal(r) { + return true + } + } + + return false +} // Non-JSON logging format function func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, args ...interface{}) { - if len(l.timeFormat) > 0 { + + if !l.disableTime { l.writer.WriteString(t.Format(l.timeFormat)) l.writer.WriteByte(' ') } @@ -194,18 +232,8 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, l.writer.WriteString("[?????]") } - offset := 3 - if l.caller { - // Check if the caller is inside our package and inside - // a logger implementation file - if _, file, _, ok := runtime.Caller(3); ok { - match := logImplFile.MatchString(file) - if match { - offset = 4 - } - } - - if _, file, line, ok := runtime.Caller(offset); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset); ok { l.writer.WriteByte(' ') l.writer.WriteString(trimCallerPath(file)) l.writer.WriteByte(':') @@ -251,6 +279,9 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, switch st := args[i+1].(type) { case string: val = st + if st == "" { + val = `""` + } case int: val = strconv.FormatInt(int64(st), 10) case int64: @@ -282,6 +313,9 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, continue FOR case Format: val = fmt.Sprintf(st[0].(string), st[1:]...) + case Quote: + raw = true + val = strconv.Quote(string(st)) default: v := reflect.ValueOf(st) if v.Kind() == reflect.Slice { @@ -292,20 +326,30 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, } } - l.writer.WriteByte(' ') + var key string + switch st := args[i].(type) { case string: - l.writer.WriteString(st) + key = st default: - l.writer.WriteString(fmt.Sprintf("%s", st)) + key = fmt.Sprintf("%s", st) } - l.writer.WriteByte('=') - if !raw && strings.ContainsAny(val, " \t\n\r") { - l.writer.WriteByte('"') - l.writer.WriteString(val) - l.writer.WriteByte('"') + if strings.Contains(val, "\n") { + l.writer.WriteString("\n ") + l.writer.WriteString(key) + l.writer.WriteString("=\n") + writeIndent(l.writer, val, " | ") + l.writer.WriteString(" ") + } else if !raw && needsQuoting(val) { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + l.writer.WriteByte('=') + l.writer.WriteString(strconv.Quote(val)) } else { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + l.writer.WriteByte('=') l.writer.WriteString(val) } } @@ -315,6 +359,26 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, if stacktrace != "" { l.writer.WriteString(string(stacktrace)) + l.writer.WriteString("\n") + } +} + +func writeIndent(w *writer, str string, indent string) { + for { + nl := strings.IndexByte(str, "\n"[0]) + if nl == -1 { + if str != "" { + w.WriteString(indent) + w.WriteString(str) + w.WriteString("\n") + } + return + } + + w.WriteString(indent) + w.WriteString(str[:nl]) + w.WriteString("\n") + str = str[nl+1:] } } @@ -334,22 +398,19 @@ func (l *intLogger) renderSlice(v reflect.Value) string { switch sv.Kind() { case reflect.String: - val = sv.String() + val = strconv.Quote(sv.String()) case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: val = strconv.FormatInt(sv.Int(), 10) case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: val = strconv.FormatUint(sv.Uint(), 10) default: val = fmt.Sprintf("%v", sv.Interface()) + if strings.ContainsAny(val, " \t\n\r") { + val = strconv.Quote(val) + } } - if strings.ContainsAny(val, " \t\n\r") { - buf.WriteByte('"') - buf.WriteString(val) - buf.WriteByte('"') - } else { - buf.WriteString(val) - } + buf.WriteString(val) } buf.WriteRune(']') @@ -415,8 +476,10 @@ func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, a func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg string) map[string]interface{} { vals := map[string]interface{}{ - "@message": msg, - "@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"), + "@message": msg, + } + if !l.disableTime { + vals["@timestamp"] = t.Format(l.timeFormat) } var levelStr string @@ -441,8 +504,8 @@ func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg strin vals["@module"] = name } - if l.caller { - if _, file, line, ok := runtime.Caller(4); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset + 1); ok { vals["@caller"] = fmt.Sprintf("%s:%d", file, line) } } @@ -517,7 +580,7 @@ func (l *intLogger) With(args ...interface{}) Logger { args = args[:len(args)-1] } - sl := *l + sl := l.copy() result := make(map[string]interface{}, len(l.implied)+len(args)) keys := make([]string, 0, len(l.implied)+len(args)) @@ -551,13 +614,13 @@ func (l *intLogger) With(args ...interface{}) Logger { sl.implied = append(sl.implied, MissingKey, extra) } - return &sl + return sl } // Create a new sub-Logger that a name decending from the current name. // This is used to create a subsystem specific Logger. func (l *intLogger) Named(name string) Logger { - sl := *l + sl := l.copy() if sl.name != "" { sl.name = sl.name + "." + name @@ -565,18 +628,18 @@ func (l *intLogger) Named(name string) Logger { sl.name = name } - return &sl + return sl } // Create a new sub-Logger with an explicit name. This ignores the current // name. This is used to create a standalone logger that doesn't fall // within the normal hierarchy. func (l *intLogger) ResetNamed(name string) Logger { - sl := *l + sl := l.copy() sl.name = name - return &sl + return sl } func (l *intLogger) ResetOutput(opts *LoggerOptions) error { @@ -632,8 +695,15 @@ func (l *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { } func (l *intLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { + newLog := *l + if l.callerOffset > 0 { + // the stack is + // logger.printf() -> l.Output() ->l.out.writer(hclog:stdlogAdaptor.write) -> hclog:stdlogAdaptor.dispatch() + // So plus 4. + newLog.callerOffset = l.callerOffset + 4 + } return &stdlogAdapter{ - log: l, + log: &newLog, inferLevels: opts.InferLevels, forceLevel: opts.ForceLevel, } @@ -663,3 +733,16 @@ func (i *intLogger) ImpliedArgs() []interface{} { func (i *intLogger) Name() string { return i.name } + +// copy returns a shallow copy of the intLogger, replacing the level pointer +// when necessary +func (l *intLogger) copy() *intLogger { + sl := *l + + if l.independentLevels { + sl.level = new(int32) + *sl.level = *l.level + } + + return &sl +} diff --git a/vendor/github.com/hashicorp/go-hclog/logger.go b/vendor/github.com/hashicorp/go-hclog/logger.go index 8d5eed76e..6a4665ba9 100644 --- a/vendor/github.com/hashicorp/go-hclog/logger.go +++ b/vendor/github.com/hashicorp/go-hclog/logger.go @@ -38,6 +38,9 @@ const ( // Error information about unrecoverable events. Error Level = 5 + + // Off disables all logging output. + Off Level = 6 ) // Format is a simple convience type for when formatting is required. When @@ -64,6 +67,12 @@ type Octal int // text output. For example: L.Info("bits", Binary(17)) type Binary int +// A simple shortcut to format strings with Go quoting. Control and +// non-printable characters will be escaped with their backslash equivalents in +// output. Intended for untrusted or multiline strings which should be logged +// as concisely as possible. +type Quote string + // ColorOption expresses how the output should be colored, if at all. type ColorOption uint8 @@ -96,6 +105,8 @@ func LevelFromString(levelStr string) Level { return Warn case "error": return Error + case "off": + return Off default: return NoLevel } @@ -115,6 +126,8 @@ func (l Level) String() string { return "error" case NoLevel: return "none" + case Off: + return "off" default: return "unknown" } @@ -179,7 +192,8 @@ type Logger interface { // the current name as well. ResetNamed(name string) Logger - // Updates the level. This should affect all sub-loggers as well. If an + // Updates the level. This should affect all related loggers as well, + // unless they were created with IndependentLevels. If an // implementation cannot update the level on the fly, it should no-op. SetLevel(level Level) @@ -227,6 +241,10 @@ type LoggerOptions struct { // Include file and line information in each log line IncludeLocation bool + // AdditionalLocationOffset is the number of additional stack levels to skip + // when finding the file and line information for the log line + AdditionalLocationOffset int + // The time format to use instead of the default TimeFormat string @@ -243,6 +261,12 @@ type LoggerOptions struct { // This is useful when interacting with a system that you wish to suppress the log // message for (because it's too noisy, etc) Exclude func(level Level, msg string, args ...interface{}) bool + + // IndependentLevels causes subloggers to be created with an independent + // copy of this logger's level. This means that using SetLevel on this + // logger will not effect any subloggers, and SetLevel on any subloggers + // will not effect the parent or sibling loggers. + IndependentLevels bool } // InterceptLogger describes the interface for using a logger @@ -271,10 +295,10 @@ type InterceptLogger interface { // the current name as well. ResetNamedIntercept(name string) InterceptLogger - // Return a value that conforms to the stdlib log.Logger interface + // Deprecated: use StandardLogger StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger - // Return a value that conforms to io.Writer, which can be passed into log.SetOutput() + // Deprecated: use StandardWriter StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer } diff --git a/vendor/github.com/hashicorp/go-hclog/stdlog.go b/vendor/github.com/hashicorp/go-hclog/stdlog.go index f35d875d3..271d546d5 100644 --- a/vendor/github.com/hashicorp/go-hclog/stdlog.go +++ b/vendor/github.com/hashicorp/go-hclog/stdlog.go @@ -64,7 +64,7 @@ func (s *stdlogAdapter) pickLevel(str string) (Level, string) { case strings.HasPrefix(str, "[INFO]"): return Info, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[WARN]"): - return Warn, strings.TrimSpace(str[7:]) + return Warn, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[ERROR]"): return Error, strings.TrimSpace(str[7:]) case strings.HasPrefix(str, "[ERR]"): diff --git a/vendor/github.com/hashicorp/go-immutable-radix/CHANGELOG.md b/vendor/github.com/hashicorp/go-immutable-radix/CHANGELOG.md index 6331af921..86c6d03fb 100644 --- a/vendor/github.com/hashicorp/go-immutable-radix/CHANGELOG.md +++ b/vendor/github.com/hashicorp/go-immutable-radix/CHANGELOG.md @@ -1,3 +1,5 @@ +# UNRELEASED + # 1.3.0 (September 17th, 2020) FEATURES diff --git a/vendor/github.com/hashicorp/go-immutable-radix/iter.go b/vendor/github.com/hashicorp/go-immutable-radix/iter.go index cd16d3bea..f17d0a644 100644 --- a/vendor/github.com/hashicorp/go-immutable-radix/iter.go +++ b/vendor/github.com/hashicorp/go-immutable-radix/iter.go @@ -20,7 +20,7 @@ func (i *Iterator) SeekPrefixWatch(prefix []byte) (watch <-chan struct{}) { watch = n.mutateCh search := prefix for { - // Check for key exhaution + // Check for key exhaustion if len(search) == 0 { i.node = n return @@ -60,10 +60,13 @@ func (i *Iterator) recurseMin(n *Node) *Node { if n.leaf != nil { return n } - if len(n.edges) > 0 { + nEdges := len(n.edges) + if nEdges > 1 { // Add all the other edges to the stack (the min node will be added as // we recurse) i.stack = append(i.stack, n.edges[1:]) + } + if nEdges > 0 { return i.recurseMin(n.edges[0].node) } // Shouldn't be possible @@ -77,16 +80,32 @@ func (i *Iterator) recurseMin(n *Node) *Node { func (i *Iterator) SeekLowerBound(key []byte) { // Wipe the stack. Unlike Prefix iteration, we need to build the stack as we // go because we need only a subset of edges of many nodes in the path to the - // leaf with the lower bound. + // leaf with the lower bound. Note that the iterator will still recurse into + // children that we don't traverse on the way to the reverse lower bound as it + // walks the stack. i.stack = []edges{} + // i.node starts off in the common case as pointing to the root node of the + // tree. By the time we return we have either found a lower bound and setup + // the stack to traverse all larger keys, or we have not and the stack and + // node should both be nil to prevent the iterator from assuming it is just + // iterating the whole tree from the root node. Either way this needs to end + // up as nil so just set it here. n := i.node + i.node = nil search := key found := func(n *Node) { - i.node = n i.stack = append(i.stack, edges{edge{node: n}}) } + findMin := func(n *Node) { + n = i.recurseMin(n) + if n != nil { + found(n) + return + } + } + for { // Compare current prefix with the search key's same-length prefix. var prefixCmp int @@ -100,10 +119,7 @@ func (i *Iterator) SeekLowerBound(key []byte) { // Prefix is larger, that means the lower bound is greater than the search // and from now on we need to follow the minimum path to the smallest // leaf under this subtree. - n = i.recurseMin(n) - if n != nil { - found(n) - } + findMin(n) return } @@ -115,27 +131,29 @@ func (i *Iterator) SeekLowerBound(key []byte) { } // Prefix is equal, we are still heading for an exact match. If this is a - // leaf we're done. - if n.leaf != nil { - if bytes.Compare(n.leaf.key, key) < 0 { - i.node = nil - return - } + // leaf and an exact match we're done. + if n.leaf != nil && bytes.Equal(n.leaf.key, key) { found(n) return } - // Consume the search prefix - if len(n.prefix) > len(search) { - search = []byte{} - } else { - search = search[len(n.prefix):] + // Consume the search prefix if the current node has one. Note that this is + // safe because if n.prefix is longer than the search slice prefixCmp would + // have been > 0 above and the method would have already returned. + search = search[len(n.prefix):] + + if len(search) == 0 { + // We've exhausted the search key, but the current node is not an exact + // match or not a leaf. That means that the leaf value if it exists, and + // all child nodes must be strictly greater, the smallest key in this + // subtree must be the lower bound. + findMin(n) + return } // Otherwise, take the lower bound next edge. idx, lbNode := n.getLowerBoundEdge(search[0]) if lbNode == nil { - i.node = nil return } @@ -144,7 +162,6 @@ func (i *Iterator) SeekLowerBound(key []byte) { i.stack = append(i.stack, n.edges[idx+1:]) } - i.node = lbNode // Recurse n = lbNode } diff --git a/vendor/github.com/hashicorp/go-immutable-radix/reverse_iter.go b/vendor/github.com/hashicorp/go-immutable-radix/reverse_iter.go index 762471bc3..554fa7129 100644 --- a/vendor/github.com/hashicorp/go-immutable-radix/reverse_iter.go +++ b/vendor/github.com/hashicorp/go-immutable-radix/reverse_iter.go @@ -8,6 +8,16 @@ import ( // in reverse in-order type ReverseIterator struct { i *Iterator + + // expandedParents stores the set of parent nodes whose relevant children have + // already been pushed into the stack. This can happen during seek or during + // iteration. + // + // Unlike forward iteration we need to recurse into children before we can + // output the value stored in an internal leaf since all children are greater. + // We use this to track whether we have already ensured all the children are + // in the stack. + expandedParents map[*Node]struct{} } // NewReverseIterator returns a new ReverseIterator at a node @@ -28,22 +38,6 @@ func (ri *ReverseIterator) SeekPrefix(prefix []byte) { ri.i.SeekPrefixWatch(prefix) } -func (ri *ReverseIterator) recurseMax(n *Node) *Node { - // Traverse to the maximum child - if n.leaf != nil { - return n - } - if len(n.edges) > 0 { - // Add all the other edges to the stack (the max node will be added as - // we recurse) - m := len(n.edges) - ri.i.stack = append(ri.i.stack, n.edges[:m-1]) - return ri.recurseMax(n.edges[m-1].node) - } - // Shouldn't be possible - return nil -} - // SeekReverseLowerBound is used to seek the iterator to the largest key that is // lower or equal to the given key. There is no watch variant as it's hard to // predict based on the radix structure which node(s) changes might affect the @@ -51,14 +45,32 @@ func (ri *ReverseIterator) recurseMax(n *Node) *Node { func (ri *ReverseIterator) SeekReverseLowerBound(key []byte) { // Wipe the stack. Unlike Prefix iteration, we need to build the stack as we // go because we need only a subset of edges of many nodes in the path to the - // leaf with the lower bound. + // leaf with the lower bound. Note that the iterator will still recurse into + // children that we don't traverse on the way to the reverse lower bound as it + // walks the stack. ri.i.stack = []edges{} + // ri.i.node starts off in the common case as pointing to the root node of the + // tree. By the time we return we have either found a lower bound and setup + // the stack to traverse all larger keys, or we have not and the stack and + // node should both be nil to prevent the iterator from assuming it is just + // iterating the whole tree from the root node. Either way this needs to end + // up as nil so just set it here. n := ri.i.node + ri.i.node = nil search := key + if ri.expandedParents == nil { + ri.expandedParents = make(map[*Node]struct{}) + } + found := func(n *Node) { - ri.i.node = n ri.i.stack = append(ri.i.stack, edges{edge{node: n}}) + // We need to mark this node as expanded in advance too otherwise the + // iterator will attempt to walk all of its children even though they are + // greater than the lower bound we have found. We've expanded it in the + // sense that all of its children that we want to walk are already in the + // stack (i.e. none of them). + ri.expandedParents[n] = struct{}{} } for { @@ -71,41 +83,73 @@ func (ri *ReverseIterator) SeekReverseLowerBound(key []byte) { } if prefixCmp < 0 { - // Prefix is smaller than search prefix, that means there is no lower bound. - // But we are looking in reverse, so the reverse lower bound will be the - // largest leaf under this subtree, since it is the value that would come - // right before the current search prefix if it were in the tree. So we need - // to follow the maximum path in this subtree to find it. - n = ri.recurseMax(n) - if n != nil { - found(n) - } + // Prefix is smaller than search prefix, that means there is no exact + // match for the search key. But we are looking in reverse, so the reverse + // lower bound will be the largest leaf under this subtree, since it is + // the value that would come right before the current search key if it + // were in the tree. So we need to follow the maximum path in this subtree + // to find it. Note that this is exactly what the iterator will already do + // if it finds a node in the stack that has _not_ been marked as expanded + // so in this one case we don't call `found` and instead let the iterator + // do the expansion and recursion through all the children. + ri.i.stack = append(ri.i.stack, edges{edge{node: n}}) return } if prefixCmp > 0 { - // Prefix is larger than search prefix, that means there is no reverse lower - // bound since nothing comes before our current search prefix. - ri.i.node = nil + // Prefix is larger than search prefix, or there is no prefix but we've + // also exhausted the search key. Either way, that means there is no + // reverse lower bound since nothing comes before our current search + // prefix. return } - // Prefix is equal, we are still heading for an exact match. If this is a - // leaf we're done. - if n.leaf != nil { - if bytes.Compare(n.leaf.key, key) < 0 { - ri.i.node = nil + // If this is a leaf, something needs to happen! Note that if it's a leaf + // and prefixCmp was zero (which it must be to get here) then the leaf value + // is either an exact match for the search, or it's lower. It can't be + // greater. + if n.isLeaf() { + + // Firstly, if it's an exact match, we're done! + if bytes.Equal(n.leaf.key, key) { + found(n) return } - found(n) - return + + // It's not so this node's leaf value must be lower and could still be a + // valid contender for reverse lower bound. + + // If it has no children then we are also done. + if len(n.edges) == 0 { + // This leaf is the lower bound. + found(n) + return + } + + // Finally, this leaf is internal (has children) so we'll keep searching, + // but we need to add it to the iterator's stack since it has a leaf value + // that needs to be iterated over. It needs to be added to the stack + // before its children below as it comes first. + ri.i.stack = append(ri.i.stack, edges{edge{node: n}}) + // We also need to mark it as expanded since we'll be adding any of its + // relevant children below and so don't want the iterator to re-add them + // on its way back up the stack. + ri.expandedParents[n] = struct{}{} } - // Consume the search prefix - if len(n.prefix) > len(search) { - search = []byte{} - } else { - search = search[len(n.prefix):] + // Consume the search prefix. Note that this is safe because if n.prefix is + // longer than the search slice prefixCmp would have been > 0 above and the + // method would have already returned. + search = search[len(n.prefix):] + + if len(search) == 0 { + // We've exhausted the search key but we are not at a leaf. That means all + // children are greater than the search key so a reverse lower bound + // doesn't exist in this subtree. Note that there might still be one in + // the whole radix tree by following a different path somewhere further + // up. If that's the case then the iterator's stack will contain all the + // smaller nodes already and Previous will walk through them correctly. + return } // Otherwise, take the lower bound next edge. @@ -125,14 +169,12 @@ func (ri *ReverseIterator) SeekReverseLowerBound(key []byte) { ri.i.stack = append(ri.i.stack, n.edges[:idx]) } - // Exit if there's not lower bound edge. The stack will have the - // previous nodes already. + // Exit if there's no lower bound edge. The stack will have the previous + // nodes already. if lbNode == nil { - ri.i.node = nil return } - ri.i.node = lbNode // Recurse n = lbNode } @@ -149,6 +191,10 @@ func (ri *ReverseIterator) Previous() ([]byte, interface{}, bool) { } } + if ri.expandedParents == nil { + ri.expandedParents = make(map[*Node]struct{}) + } + for len(ri.i.stack) > 0 { // Inspect the last element of the stack n := len(ri.i.stack) @@ -156,22 +202,38 @@ func (ri *ReverseIterator) Previous() ([]byte, interface{}, bool) { m := len(last) elem := last[m-1].node - // Update the stack + _, alreadyExpanded := ri.expandedParents[elem] + + // If this is an internal node and we've not seen it already, we need to + // leave it in the stack so we can return its possible leaf value _after_ + // we've recursed through all its children. + if len(elem.edges) > 0 && !alreadyExpanded { + // record that we've seen this node! + ri.expandedParents[elem] = struct{}{} + // push child edges onto stack and skip the rest of the loop to recurse + // into the largest one. + ri.i.stack = append(ri.i.stack, elem.edges) + continue + } + + // Remove the node from the stack if m > 1 { ri.i.stack[n-1] = last[:m-1] } else { ri.i.stack = ri.i.stack[:n-1] } - - // Push the edges onto the frontier - if len(elem.edges) > 0 { - ri.i.stack = append(ri.i.stack, elem.edges) + // We don't need this state any more as it's no longer in the stack so we + // won't visit it again + if alreadyExpanded { + delete(ri.expandedParents, elem) } - // Return the leaf values if any + // If this is a leaf, return it if elem.leaf != nil { return elem.leaf.key, elem.leaf.val, true } + + // it's not a leaf so keep walking the stack to find the previous leaf } return nil, nil, false } diff --git a/vendor/github.com/hashicorp/go-multierror/.travis.yml b/vendor/github.com/hashicorp/go-multierror/.travis.yml deleted file mode 100644 index 24b80388f..000000000 --- a/vendor/github.com/hashicorp/go-multierror/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.x - -branches: - only: - - master - -script: env GO111MODULE=on make test testrace diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md index e92fa614c..71dd308ed 100644 --- a/vendor/github.com/hashicorp/go-multierror/README.md +++ b/vendor/github.com/hashicorp/go-multierror/README.md @@ -1,10 +1,11 @@ # go-multierror -[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] -[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] +[![CircleCI](https://img.shields.io/circleci/build/github/hashicorp/go-multierror/master)](https://circleci.com/gh/hashicorp/go-multierror) +[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-multierror.svg)](https://pkg.go.dev/github.com/hashicorp/go-multierror) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hashicorp/go-multierror) -[travis]: https://travis-ci.org/hashicorp/go-multierror -[godocs]: https://godoc.org/github.com/hashicorp/go-multierror +[circleci]: https://app.circleci.com/pipelines/github/hashicorp/go-multierror +[godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror `go-multierror` is a package for Go that provides a mechanism for representing a list of `error` values as a single `error`. @@ -24,7 +25,25 @@ for introspecting on error values. Install using `go get github.com/hashicorp/go-multierror`. Full documentation is available at -http://godoc.org/github.com/hashicorp/go-multierror +https://pkg.go.dev/github.com/hashicorp/go-multierror + +### Requires go version 1.13 or newer + +`go-multierror` requires go version 1.13 or newer. Go 1.13 introduced +[error wrapping](https://golang.org/doc/go1.13#error_wrapping), which +this library takes advantage of. + +If you need to use an earlier version of go, you can use the +[v1.0.0](https://github.com/hashicorp/go-multierror/tree/v1.0.0) +tag, which doesn't rely on features in go 1.13. + +If you see compile errors that look like the below, it's likely that +you're on an older version of go: + +``` +/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As +/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.Is +``` ## Usage diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go index 775b6e753..3e2589bfd 100644 --- a/vendor/github.com/hashicorp/go-multierror/append.go +++ b/vendor/github.com/hashicorp/go-multierror/append.go @@ -6,6 +6,8 @@ package multierror // If err is not a multierror.Error, then it will be turned into // one. If any of the errs are multierr.Error, they will be flattened // one level into err. +// Any nil errors within errs will be ignored. If err is nil, a new +// *Error will be returned. func Append(err error, errs ...error) *Error { switch err := err.(type) { case *Error: diff --git a/vendor/github.com/hashicorp/go-multierror/go.mod b/vendor/github.com/hashicorp/go-multierror/go.mod index 0afe8e6f9..141cc4ccb 100644 --- a/vendor/github.com/hashicorp/go-multierror/go.mod +++ b/vendor/github.com/hashicorp/go-multierror/go.mod @@ -1,5 +1,5 @@ module github.com/hashicorp/go-multierror -go 1.14 +go 1.13 require github.com/hashicorp/errwrap v1.0.0 diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go index d05dd9269..f54574326 100644 --- a/vendor/github.com/hashicorp/go-multierror/multierror.go +++ b/vendor/github.com/hashicorp/go-multierror/multierror.go @@ -40,14 +40,17 @@ func (e *Error) GoString() string { return fmt.Sprintf("*%#v", *e) } -// WrappedErrors returns the list of errors that this Error is wrapping. -// It is an implementation of the errwrap.Wrapper interface so that -// multierror.Error can be used with that library. +// WrappedErrors returns the list of errors that this Error is wrapping. It is +// an implementation of the errwrap.Wrapper interface so that multierror.Error +// can be used with that library. // -// This method is not safe to be called concurrently and is no different -// than accessing the Errors field directly. It is implemented only to -// satisfy the errwrap.Wrapper interface. +// This method is not safe to be called concurrently. Unlike accessing the +// Errors field directly, this function also checks if the multierror is nil to +// prevent a null-pointer panic. It satisfies the errwrap.Wrapper interface. func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } return e.Errors } diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go new file mode 100644 index 000000000..7c038d12a --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go @@ -0,0 +1,789 @@ +package printer + +import ( + "bytes" + "fmt" + "sort" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/token" +) + +const ( + blank = byte(' ') + newline = byte('\n') + tab = byte('\t') + infinity = 1 << 30 // offset or line +) + +var ( + unindent = []byte("\uE123") // in the private use space +) + +type printer struct { + cfg Config + prev token.Pos + + comments []*ast.CommentGroup // may be nil, contains all comments + standaloneComments []*ast.CommentGroup // contains all standalone comments (not assigned to any node) + + enableTrace bool + indentTrace int +} + +type ByPosition []*ast.CommentGroup + +func (b ByPosition) Len() int { return len(b) } +func (b ByPosition) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b ByPosition) Less(i, j int) bool { return b[i].Pos().Before(b[j].Pos()) } + +// collectComments comments all standalone comments which are not lead or line +// comment +func (p *printer) collectComments(node ast.Node) { + // first collect all comments. This is already stored in + // ast.File.(comments) + ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { + switch t := nn.(type) { + case *ast.File: + p.comments = t.Comments + return nn, false + } + return nn, true + }) + + standaloneComments := make(map[token.Pos]*ast.CommentGroup, 0) + for _, c := range p.comments { + standaloneComments[c.Pos()] = c + } + + // next remove all lead and line comments from the overall comment map. + // This will give us comments which are standalone, comments which are not + // assigned to any kind of node. + ast.Walk(node, func(nn ast.Node) (ast.Node, bool) { + switch t := nn.(type) { + case *ast.LiteralType: + if t.LeadComment != nil { + for _, comment := range t.LeadComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + + if t.LineComment != nil { + for _, comment := range t.LineComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + case *ast.ObjectItem: + if t.LeadComment != nil { + for _, comment := range t.LeadComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + + if t.LineComment != nil { + for _, comment := range t.LineComment.List { + if _, ok := standaloneComments[comment.Pos()]; ok { + delete(standaloneComments, comment.Pos()) + } + } + } + } + + return nn, true + }) + + for _, c := range standaloneComments { + p.standaloneComments = append(p.standaloneComments, c) + } + + sort.Sort(ByPosition(p.standaloneComments)) +} + +// output prints creates b printable HCL output and returns it. +func (p *printer) output(n interface{}) []byte { + var buf bytes.Buffer + + switch t := n.(type) { + case *ast.File: + // File doesn't trace so we add the tracing here + defer un(trace(p, "File")) + return p.output(t.Node) + case *ast.ObjectList: + defer un(trace(p, "ObjectList")) + + var index int + for { + // Determine the location of the next actual non-comment + // item. If we're at the end, the next item is at "infinity" + var nextItem token.Pos + if index != len(t.Items) { + nextItem = t.Items[index].Pos() + } else { + nextItem = token.Pos{Offset: infinity, Line: infinity} + } + + // Go through the standalone comments in the file and print out + // the comments that we should be for this object item. + for _, c := range p.standaloneComments { + // Go through all the comments in the group. The group + // should be printed together, not separated by double newlines. + printed := false + newlinePrinted := false + for _, comment := range c.List { + // We only care about comments after the previous item + // we've printed so that comments are printed in the + // correct locations (between two objects for example). + // And before the next item. + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // if we hit the end add newlines so we can print the comment + // we don't do this if prev is invalid which means the + // beginning of the file since the first comment should + // be at the first line. + if !newlinePrinted && p.prev.IsValid() && index == len(t.Items) { + buf.Write([]byte{newline, newline}) + newlinePrinted = true + } + + // Write the actual comment. + buf.WriteString(comment.Text) + buf.WriteByte(newline) + + // Set printed to true to note that we printed something + printed = true + } + } + + // If we're not at the last item, write a new line so + // that there is a newline separating this comment from + // the next object. + if printed && index != len(t.Items) { + buf.WriteByte(newline) + } + } + + if index == len(t.Items) { + break + } + + buf.Write(p.output(t.Items[index])) + if index != len(t.Items)-1 { + // Always write a newline to separate us from the next item + buf.WriteByte(newline) + + // Need to determine if we're going to separate the next item + // with a blank line. The logic here is simple, though there + // are a few conditions: + // + // 1. The next object is more than one line away anyways, + // so we need an empty line. + // + // 2. The next object is not a "single line" object, so + // we need an empty line. + // + // 3. This current object is not a single line object, + // so we need an empty line. + current := t.Items[index] + next := t.Items[index+1] + if next.Pos().Line != t.Items[index].Pos().Line+1 || + !p.isSingleLineObject(next) || + !p.isSingleLineObject(current) { + buf.WriteByte(newline) + } + } + index++ + } + case *ast.ObjectKey: + buf.WriteString(t.Token.Text) + case *ast.ObjectItem: + p.prev = t.Pos() + buf.Write(p.objectItem(t)) + case *ast.LiteralType: + buf.Write(p.literalType(t)) + case *ast.ListType: + buf.Write(p.list(t)) + case *ast.ObjectType: + buf.Write(p.objectType(t)) + default: + fmt.Printf(" unknown type: %T\n", n) + } + + return buf.Bytes() +} + +func (p *printer) literalType(lit *ast.LiteralType) []byte { + result := []byte(lit.Token.Text) + switch lit.Token.Type { + case token.HEREDOC: + // Clear the trailing newline from heredocs + if result[len(result)-1] == '\n' { + result = result[:len(result)-1] + } + + // Poison lines 2+ so that we don't indent them + result = p.heredocIndent(result) + case token.STRING: + // If this is a multiline string, poison lines 2+ so we don't + // indent them. + if bytes.IndexRune(result, '\n') >= 0 { + result = p.heredocIndent(result) + } + } + + return result +} + +// objectItem returns the printable HCL form of an object item. An object type +// starts with one/multiple keys and has a value. The value might be of any +// type. +func (p *printer) objectItem(o *ast.ObjectItem) []byte { + defer un(trace(p, fmt.Sprintf("ObjectItem: %s", o.Keys[0].Token.Text))) + var buf bytes.Buffer + + if o.LeadComment != nil { + for _, comment := range o.LeadComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + // If key and val are on different lines, treat line comments like lead comments. + if o.LineComment != nil && o.Val.Pos().Line != o.Keys[0].Pos().Line { + for _, comment := range o.LineComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + for i, k := range o.Keys { + buf.WriteString(k.Token.Text) + buf.WriteByte(blank) + + // reach end of key + if o.Assign.IsValid() && i == len(o.Keys)-1 && len(o.Keys) == 1 { + buf.WriteString("=") + buf.WriteByte(blank) + } + } + + buf.Write(p.output(o.Val)) + + if o.LineComment != nil && o.Val.Pos().Line == o.Keys[0].Pos().Line { + buf.WriteByte(blank) + for _, comment := range o.LineComment.List { + buf.WriteString(comment.Text) + } + } + + return buf.Bytes() +} + +// objectType returns the printable HCL form of an object type. An object type +// begins with a brace and ends with a brace. +func (p *printer) objectType(o *ast.ObjectType) []byte { + defer un(trace(p, "ObjectType")) + var buf bytes.Buffer + buf.WriteString("{") + + var index int + var nextItem token.Pos + var commented, newlinePrinted bool + for { + // Determine the location of the next actual non-comment + // item. If we're at the end, the next item is the closing brace + if index != len(o.List.Items) { + nextItem = o.List.Items[index].Pos() + } else { + nextItem = o.Rbrace + } + + // Go through the standalone comments in the file and print out + // the comments that we should be for this object item. + for _, c := range p.standaloneComments { + printed := false + var lastCommentPos token.Pos + for _, comment := range c.List { + // We only care about comments after the previous item + // we've printed so that comments are printed in the + // correct locations (between two objects for example). + // And before the next item. + if comment.Pos().After(p.prev) && comment.Pos().Before(nextItem) { + // If there are standalone comments and the initial newline has not + // been printed yet, do it now. + if !newlinePrinted { + newlinePrinted = true + buf.WriteByte(newline) + } + + // add newline if it's between other printed nodes + if index > 0 { + commented = true + buf.WriteByte(newline) + } + + // Store this position + lastCommentPos = comment.Pos() + + // output the comment itself + buf.Write(p.indent(p.heredocIndent([]byte(comment.Text)))) + + // Set printed to true to note that we printed something + printed = true + + /* + if index != len(o.List.Items) { + buf.WriteByte(newline) // do not print on the end + } + */ + } + } + + // Stuff to do if we had comments + if printed { + // Always write a newline + buf.WriteByte(newline) + + // If there is another item in the object and our comment + // didn't hug it directly, then make sure there is a blank + // line separating them. + if nextItem != o.Rbrace && nextItem.Line != lastCommentPos.Line+1 { + buf.WriteByte(newline) + } + } + } + + if index == len(o.List.Items) { + p.prev = o.Rbrace + break + } + + // At this point we are sure that it's not a totally empty block: print + // the initial newline if it hasn't been printed yet by the previous + // block about standalone comments. + if !newlinePrinted { + buf.WriteByte(newline) + newlinePrinted = true + } + + // check if we have adjacent one liner items. If yes we'll going to align + // the comments. + var aligned []*ast.ObjectItem + for _, item := range o.List.Items[index:] { + // we don't group one line lists + if len(o.List.Items) == 1 { + break + } + + // one means a oneliner with out any lead comment + // two means a oneliner with lead comment + // anything else might be something else + cur := lines(string(p.objectItem(item))) + if cur > 2 { + break + } + + curPos := item.Pos() + + nextPos := token.Pos{} + if index != len(o.List.Items)-1 { + nextPos = o.List.Items[index+1].Pos() + } + + prevPos := token.Pos{} + if index != 0 { + prevPos = o.List.Items[index-1].Pos() + } + + // fmt.Println("DEBUG ----------------") + // fmt.Printf("prev = %+v prevPos: %s\n", prev, prevPos) + // fmt.Printf("cur = %+v curPos: %s\n", cur, curPos) + // fmt.Printf("next = %+v nextPos: %s\n", next, nextPos) + + if curPos.Line+1 == nextPos.Line { + aligned = append(aligned, item) + index++ + continue + } + + if curPos.Line-1 == prevPos.Line { + aligned = append(aligned, item) + index++ + + // finish if we have a new line or comment next. This happens + // if the next item is not adjacent + if curPos.Line+1 != nextPos.Line { + break + } + continue + } + + break + } + + // put newlines if the items are between other non aligned items. + // newlines are also added if there is a standalone comment already, so + // check it too + if !commented && index != len(aligned) { + buf.WriteByte(newline) + } + + if len(aligned) >= 1 { + p.prev = aligned[len(aligned)-1].Pos() + + items := p.alignedItems(aligned) + buf.Write(p.indent(items)) + } else { + p.prev = o.List.Items[index].Pos() + + buf.Write(p.indent(p.objectItem(o.List.Items[index]))) + index++ + } + + buf.WriteByte(newline) + } + + buf.WriteString("}") + return buf.Bytes() +} + +func (p *printer) alignedItems(items []*ast.ObjectItem) []byte { + var buf bytes.Buffer + + // find the longest key and value length, needed for alignment + var longestKeyLen int // longest key length + var longestValLen int // longest value length + for _, item := range items { + key := len(item.Keys[0].Token.Text) + val := len(p.output(item.Val)) + + if key > longestKeyLen { + longestKeyLen = key + } + + if val > longestValLen { + longestValLen = val + } + } + + for i, item := range items { + if item.LeadComment != nil { + for _, comment := range item.LeadComment.List { + buf.WriteString(comment.Text) + buf.WriteByte(newline) + } + } + + for i, k := range item.Keys { + keyLen := len(k.Token.Text) + buf.WriteString(k.Token.Text) + for i := 0; i < longestKeyLen-keyLen+1; i++ { + buf.WriteByte(blank) + } + + // reach end of key + if i == len(item.Keys)-1 && len(item.Keys) == 1 { + buf.WriteString("=") + buf.WriteByte(blank) + } + } + + val := p.output(item.Val) + valLen := len(val) + buf.Write(val) + + if item.Val.Pos().Line == item.Keys[0].Pos().Line && item.LineComment != nil { + for i := 0; i < longestValLen-valLen+1; i++ { + buf.WriteByte(blank) + } + + for _, comment := range item.LineComment.List { + buf.WriteString(comment.Text) + } + } + + // do not print for the last item + if i != len(items)-1 { + buf.WriteByte(newline) + } + } + + return buf.Bytes() +} + +// list returns the printable HCL form of an list type. +func (p *printer) list(l *ast.ListType) []byte { + if p.isSingleLineList(l) { + return p.singleLineList(l) + } + + var buf bytes.Buffer + buf.WriteString("[") + buf.WriteByte(newline) + + var longestLine int + for _, item := range l.List { + // for now we assume that the list only contains literal types + if lit, ok := item.(*ast.LiteralType); ok { + lineLen := len(lit.Token.Text) + if lineLen > longestLine { + longestLine = lineLen + } + } + } + + haveEmptyLine := false + for i, item := range l.List { + // If we have a lead comment, then we want to write that first + leadComment := false + if lit, ok := item.(*ast.LiteralType); ok && lit.LeadComment != nil { + leadComment = true + + // Ensure an empty line before every element with a + // lead comment (except the first item in a list). + if !haveEmptyLine && i != 0 { + buf.WriteByte(newline) + } + + for _, comment := range lit.LeadComment.List { + buf.Write(p.indent([]byte(comment.Text))) + buf.WriteByte(newline) + } + } + + // also indent each line + val := p.output(item) + curLen := len(val) + buf.Write(p.indent(val)) + + // if this item is a heredoc, then we output the comma on + // the next line. This is the only case this happens. + comma := []byte{','} + if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { + buf.WriteByte(newline) + comma = p.indent(comma) + } + + buf.Write(comma) + + if lit, ok := item.(*ast.LiteralType); ok && lit.LineComment != nil { + // if the next item doesn't have any comments, do not align + buf.WriteByte(blank) // align one space + for i := 0; i < longestLine-curLen; i++ { + buf.WriteByte(blank) + } + + for _, comment := range lit.LineComment.List { + buf.WriteString(comment.Text) + } + } + + buf.WriteByte(newline) + + // Ensure an empty line after every element with a + // lead comment (except the first item in a list). + haveEmptyLine = leadComment && i != len(l.List)-1 + if haveEmptyLine { + buf.WriteByte(newline) + } + } + + buf.WriteString("]") + return buf.Bytes() +} + +// isSingleLineList returns true if: +// * they were previously formatted entirely on one line +// * they consist entirely of literals +// * there are either no heredoc strings or the list has exactly one element +// * there are no line comments +func (printer) isSingleLineList(l *ast.ListType) bool { + for _, item := range l.List { + if item.Pos().Line != l.Lbrack.Line { + return false + } + + lit, ok := item.(*ast.LiteralType) + if !ok { + return false + } + + if lit.Token.Type == token.HEREDOC && len(l.List) != 1 { + return false + } + + if lit.LineComment != nil { + return false + } + } + + return true +} + +// singleLineList prints a simple single line list. +// For a definition of "simple", see isSingleLineList above. +func (p *printer) singleLineList(l *ast.ListType) []byte { + buf := &bytes.Buffer{} + + buf.WriteString("[") + for i, item := range l.List { + if i != 0 { + buf.WriteString(", ") + } + + // Output the item itself + buf.Write(p.output(item)) + + // The heredoc marker needs to be at the end of line. + if lit, ok := item.(*ast.LiteralType); ok && lit.Token.Type == token.HEREDOC { + buf.WriteByte(newline) + } + } + + buf.WriteString("]") + return buf.Bytes() +} + +// indent indents the lines of the given buffer for each non-empty line +func (p *printer) indent(buf []byte) []byte { + var prefix []byte + if p.cfg.SpacesWidth != 0 { + for i := 0; i < p.cfg.SpacesWidth; i++ { + prefix = append(prefix, blank) + } + } else { + prefix = []byte{tab} + } + + var res []byte + bol := true + for _, c := range buf { + if bol && c != '\n' { + res = append(res, prefix...) + } + + res = append(res, c) + bol = c == '\n' + } + return res +} + +// unindent removes all the indentation from the tombstoned lines +func (p *printer) unindent(buf []byte) []byte { + var res []byte + for i := 0; i < len(buf); i++ { + skip := len(buf)-i <= len(unindent) + if !skip { + skip = !bytes.Equal(unindent, buf[i:i+len(unindent)]) + } + if skip { + res = append(res, buf[i]) + continue + } + + // We have a marker. we have to backtrace here and clean out + // any whitespace ahead of our tombstone up to a \n + for j := len(res) - 1; j >= 0; j-- { + if res[j] == '\n' { + break + } + + res = res[:j] + } + + // Skip the entire unindent marker + i += len(unindent) - 1 + } + + return res +} + +// heredocIndent marks all the 2nd and further lines as unindentable +func (p *printer) heredocIndent(buf []byte) []byte { + var res []byte + bol := false + for _, c := range buf { + if bol && c != '\n' { + res = append(res, unindent...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// isSingleLineObject tells whether the given object item is a single +// line object such as "obj {}". +// +// A single line object: +// +// * has no lead comments (hence multi-line) +// * has no assignment +// * has no values in the stanza (within {}) +// +func (p *printer) isSingleLineObject(val *ast.ObjectItem) bool { + // If there is a lead comment, can't be one line + if val.LeadComment != nil { + return false + } + + // If there is assignment, we always break by line + if val.Assign.IsValid() { + return false + } + + // If it isn't an object type, then its not a single line object + ot, ok := val.Val.(*ast.ObjectType) + if !ok { + return false + } + + // If the object has no items, it is single line! + return len(ot.List.Items) == 0 +} + +func lines(txt string) int { + endline := 1 + for i := 0; i < len(txt); i++ { + if txt[i] == '\n' { + endline++ + } + } + return endline +} + +// ---------------------------------------------------------------------------- +// Tracing support + +func (p *printer) printTrace(a ...interface{}) { + if !p.enableTrace { + return + } + + const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . " + const n = len(dots) + i := 2 * p.indentTrace + for i > n { + fmt.Print(dots) + i -= n + } + // i <= n + fmt.Print(dots[0:i]) + fmt.Println(a...) +} + +func trace(p *printer, msg string) *printer { + p.printTrace(msg, "(") + p.indentTrace++ + return p +} + +// Usage pattern: defer un(trace(p, "...")) +func un(p *printer) { + p.indentTrace-- + p.printTrace(")") +} diff --git a/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go new file mode 100644 index 000000000..6617ab8e7 --- /dev/null +++ b/vendor/github.com/hashicorp/hcl/hcl/printer/printer.go @@ -0,0 +1,66 @@ +// Package printer implements printing of AST nodes to HCL format. +package printer + +import ( + "bytes" + "io" + "text/tabwriter" + + "github.com/hashicorp/hcl/hcl/ast" + "github.com/hashicorp/hcl/hcl/parser" +) + +var DefaultConfig = Config{ + SpacesWidth: 2, +} + +// A Config node controls the output of Fprint. +type Config struct { + SpacesWidth int // if set, it will use spaces instead of tabs for alignment +} + +func (c *Config) Fprint(output io.Writer, node ast.Node) error { + p := &printer{ + cfg: *c, + comments: make([]*ast.CommentGroup, 0), + standaloneComments: make([]*ast.CommentGroup, 0), + // enableTrace: true, + } + + p.collectComments(node) + + if _, err := output.Write(p.unindent(p.output(node))); err != nil { + return err + } + + // flush tabwriter, if any + var err error + if tw, _ := output.(*tabwriter.Writer); tw != nil { + err = tw.Flush() + } + + return err +} + +// Fprint "pretty-prints" an HCL node to output +// It calls Config.Fprint with default settings. +func Fprint(output io.Writer, node ast.Node) error { + return DefaultConfig.Fprint(output, node) +} + +// Format formats src HCL and returns the result. +func Format(src []byte) ([]byte, error) { + node, err := parser.Parse(src) + if err != nil { + return nil, err + } + + var buf bytes.Buffer + if err := DefaultConfig.Fprint(&buf, node); err != nil { + return nil, err + } + + // Add trailing newline to result + buf.WriteString("\n") + return buf.Bytes(), nil +} diff --git a/vendor/github.com/k-sone/critbitgo/.travis.yml b/vendor/github.com/k-sone/critbitgo/.travis.yml new file mode 100644 index 000000000..81def16a8 --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.5 + - 1.6 + - 1.7 diff --git a/vendor/github.com/k-sone/critbitgo/CHANGES.md b/vendor/github.com/k-sone/critbitgo/CHANGES.md new file mode 100644 index 000000000..ec4265a69 --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/CHANGES.md @@ -0,0 +1,22 @@ +## 1.4.0 (2019/11/02) + +- Add Net.WalkPrefix [#10](https://github.com/k-sone/critbitgo/pull/10) +- Add Net.WalkMatch [#11](https://github.com/k-sone/critbitgo/pull/11) +- Fix Allprefixed [#12](https://github.com/k-sone/critbitgo/pull/12) +- Make Walk API handle empty trie [#13](https://github.com/k-sone/critbitgo/pull/13) + +## 1.3.0 (2019/09/30) + +- Add Net.Walk [#9](https://github.com/k-sone/critbitgo/pull/9) + +## 1.2.0 (2018/04/25) + +- Add ContainedIP() as fast way to check an IP [#7](https://github.com/k-sone/critbitgo/pull/7) + +## 1.1.0 (2016/12/29) + +- Add `LongestPrefix ` and `Walk` functions + +## 1.0.0 (2016/04/02) + +- Initial release diff --git a/vendor/github.com/k-sone/critbitgo/LICENSE b/vendor/github.com/k-sone/critbitgo/LICENSE new file mode 100644 index 000000000..f36eed92a --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Keita Sone + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/k-sone/critbitgo/README.md b/vendor/github.com/k-sone/critbitgo/README.md new file mode 100644 index 000000000..ab3c50fa2 --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/README.md @@ -0,0 +1,44 @@ +[![Build Status](https://travis-ci.org/k-sone/critbitgo.svg?branch=master)](https://travis-ci.org/k-sone/critbitgo) + +critbitgo +========= + +[Crit-bit trees](http://cr.yp.to/critbit.html) in golang and its applications. + +This implementation extended to handle the key that contains a null character from [C implementation](https://github.com/agl/critbit). + +Usage +-------- + +```go +// Create Trie +trie := critbitgo.NewTrie() + +// Insert +trie.Insert([]byte("aa"), "value1") +trie.Insert([]byte("bb"), "value2") +trie.Insert([]byte("ab"), "value3") + +// Get +v, ok := trie.Get([]byte("aa")) +fmt.Println(v, ok) // -> value1 true + +// Iterate containing keys +trie.Allprefixed([]byte{}, func(key []byte, value interface{}) bool { + fmt.Println(key, value) // -> [97 97] value1 + // [97 98] value3 + // [98 98] value2 + return true +}) + +// Delete +v, ok = trie.Delete([]byte("aa")) +fmt.Println(v, ok) // -> value1 true +v, ok = trie.Delete([]byte("aa")) +fmt.Println(v, ok) // -> false +``` + +License +------- + +MIT diff --git a/vendor/github.com/k-sone/critbitgo/critbit.go b/vendor/github.com/k-sone/critbitgo/critbit.go new file mode 100644 index 000000000..f8b2bec1a --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/critbit.go @@ -0,0 +1,393 @@ +package critbitgo + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "strconv" +) + +// The matrix of most significant bit +var msbMatrix [256]byte + +func buildMsbMatrix() { + for i := 0; i < len(msbMatrix); i++ { + b := byte(i) + b |= b >> 1 + b |= b >> 2 + b |= b >> 4 + msbMatrix[i] = b &^ (b >> 1) + } +} + +type node struct { + internal *internal + external *external +} + +type internal struct { + child [2]node + offset int + bit byte + cont bool // if true, key of child[1] contains key of child[0] +} + +type external struct { + key []byte + value interface{} +} + +// finding the critical bit. +func (n *external) criticalBit(key []byte) (offset int, bit byte, cont bool) { + nlen := len(n.key) + klen := len(key) + mlen := nlen + if nlen > klen { + mlen = klen + } + + // find first differing byte and bit + for offset = 0; offset < mlen; offset++ { + if a, b := key[offset], n.key[offset]; a != b { + bit = msbMatrix[a^b] + return + } + } + + if nlen < klen { + bit = msbMatrix[key[offset]] + } else if nlen > klen { + bit = msbMatrix[n.key[offset]] + } else { + // two keys are equal + offset = -1 + } + return offset, bit, true +} + +// calculate direction. +func (n *internal) direction(key []byte) int { + if n.offset < len(key) && (key[n.offset]&n.bit != 0 || n.cont) { + return 1 + } + return 0 +} + +// Crit-bit Tree +type Trie struct { + root node + size int +} + +// searching the tree. +func (t *Trie) search(key []byte) *node { + n := &t.root + for n.internal != nil { + n = &n.internal.child[n.internal.direction(key)] + } + return n +} + +// membership testing. +func (t *Trie) Contains(key []byte) bool { + if n := t.search(key); n.external != nil && bytes.Equal(n.external.key, key) { + return true + } + return false +} + +// get member. +// if `key` is in Trie, `ok` is true. +func (t *Trie) Get(key []byte) (value interface{}, ok bool) { + if n := t.search(key); n.external != nil && bytes.Equal(n.external.key, key) { + return n.external.value, true + } + return +} + +// insert into the tree (replaceable). +func (t *Trie) insert(key []byte, value interface{}, replace bool) bool { + // an empty tree + if t.size == 0 { + t.root.external = &external{ + key: key, + value: value, + } + t.size = 1 + return true + } + + n := t.search(key) + newOffset, newBit, newCont := n.external.criticalBit(key) + + // already exists in the tree + if newOffset == -1 { + if replace { + n.external.value = value + return true + } + return false + } + + // allocate new node + newNode := &internal{ + offset: newOffset, + bit: newBit, + cont: newCont, + } + direction := newNode.direction(key) + newNode.child[direction].external = &external{ + key: key, + value: value, + } + + // insert new node + wherep := &t.root + for in := wherep.internal; in != nil; in = wherep.internal { + if in.offset > newOffset || (in.offset == newOffset && in.bit < newBit) { + break + } + wherep = &in.child[in.direction(key)] + } + + if wherep.internal != nil { + newNode.child[1-direction].internal = wherep.internal + } else { + newNode.child[1-direction].external = wherep.external + wherep.external = nil + } + wherep.internal = newNode + t.size += 1 + return true +} + +// insert into the tree. +// if `key` is alredy in Trie, return false. +func (t *Trie) Insert(key []byte, value interface{}) bool { + return t.insert(key, value, false) +} + +// set into the tree. +func (t *Trie) Set(key []byte, value interface{}) { + t.insert(key, value, true) +} + +// deleting elements. +// if `key` is in Trie, `ok` is true. +func (t *Trie) Delete(key []byte) (value interface{}, ok bool) { + // an empty tree + if t.size == 0 { + return + } + + var direction int + var whereq *node // pointer to the grandparent + var wherep *node = &t.root + + // finding the best candidate to delete + for in := wherep.internal; in != nil; in = wherep.internal { + direction = in.direction(key) + whereq = wherep + wherep = &in.child[direction] + } + + // checking that we have the right element + if !bytes.Equal(wherep.external.key, key) { + return + } + value = wherep.external.value + ok = true + + // removing the node + if whereq == nil { + wherep.external = nil + } else { + othern := whereq.internal.child[1-direction] + whereq.internal = othern.internal + whereq.external = othern.external + } + t.size -= 1 + return +} + +// clearing a tree. +func (t *Trie) Clear() { + t.root.internal = nil + t.root.external = nil + t.size = 0 +} + +// return the number of key in a tree. +func (t *Trie) Size() int { + return t.size +} + +// fetching elements with a given prefix. +// handle is called with arguments key and value (if handle returns `false`, the iteration is aborted) +func (t *Trie) Allprefixed(prefix []byte, handle func(key []byte, value interface{}) bool) bool { + // an empty tree + if t.size == 0 { + return true + } + + // walk tree, maintaining top pointer + p := &t.root + top := p + if len(prefix) > 0 { + for q := p.internal; q != nil; q = p.internal { + p = &q.child[q.direction(prefix)] + if q.offset < len(prefix) { + top = p + } + } + + // check prefix + if !bytes.HasPrefix(p.external.key, prefix) { + return true + } + } + + return allprefixed(top, handle) +} + +func allprefixed(n *node, handle func([]byte, interface{}) bool) bool { + if n.internal != nil { + // dealing with an internal node while recursing + for i := 0; i < 2; i++ { + if !allprefixed(&n.internal.child[i], handle) { + return false + } + } + } else { + // dealing with an external node while recursing + return handle(n.external.key, n.external.value) + } + return true +} + +// Search for the longest matching key from the beginning of the given key. +// if `key` is in Trie, `ok` is true. +func (t *Trie) LongestPrefix(given []byte) (key []byte, value interface{}, ok bool) { + // an empty tree + if t.size == 0 { + return + } + return longestPrefix(&t.root, given) +} + +func longestPrefix(n *node, key []byte) ([]byte, interface{}, bool) { + if n.internal != nil { + direction := n.internal.direction(key) + if k, v, ok := longestPrefix(&n.internal.child[direction], key); ok { + return k, v, ok + } + if direction == 1 { + return longestPrefix(&n.internal.child[0], key) + } + } else { + if bytes.HasPrefix(key, n.external.key) { + return n.external.key, n.external.value, true + } + } + return nil, nil, false +} + +// Iterating elements from a given start key. +// handle is called with arguments key and value (if handle returns `false`, the iteration is aborted) +func (t *Trie) Walk(start []byte, handle func(key []byte, value interface{}) bool) bool { + if t.size == 0 { + return true + } + var seek bool + if start != nil { + seek = true + } + return walk(&t.root, start, &seek, handle) +} + +func walk(n *node, key []byte, seek *bool, handle func([]byte, interface{}) bool) bool { + if n.internal != nil { + var direction int + if *seek { + direction = n.internal.direction(key) + } + if !walk(&n.internal.child[direction], key, seek, handle) { + return false + } + if !(*seek) && direction == 0 { + // iteration another side + return walk(&n.internal.child[1], key, seek, handle) + } + return true + } else { + if *seek { + if bytes.Equal(n.external.key, key) { + // seek completed + *seek = false + } else { + // key is not in Trie + return false + } + } + return handle(n.external.key, n.external.value) + } +} + +// dump tree. (for debugging) +func (t *Trie) Dump(w io.Writer) { + if t.root.internal == nil && t.root.external == nil { + return + } + if w == nil { + w = os.Stdout + } + dump(w, &t.root, true, "") +} + +func dump(w io.Writer, n *node, right bool, prefix string) { + var ownprefix string + if right { + ownprefix = prefix + } else { + ownprefix = prefix[:len(prefix)-1] + "`" + } + + if in := n.internal; in != nil { + fmt.Fprintf(w, "%s-- off=%d, bit=%08b(%02x), cont=%v\n", ownprefix, in.offset, in.bit, in.bit, in.cont) + for i := 0; i < 2; i++ { + var nextprefix string + switch i { + case 0: + nextprefix = prefix + " |" + right = true + case 1: + nextprefix = prefix + " " + right = false + } + dump(w, &in.child[i], right, nextprefix) + } + } else { + fmt.Fprintf(w, "%s-- key=%d (%s)\n", ownprefix, n.external.key, key2str(n.external.key)) + } + return +} + +func key2str(key []byte) string { + for _, c := range key { + if !strconv.IsPrint(rune(c)) { + return hex.EncodeToString(key) + } + } + return string(key) +} + +// create a tree. +func NewTrie() *Trie { + return &Trie{} +} + +func init() { + buildMsbMatrix() +} diff --git a/vendor/github.com/k-sone/critbitgo/map.go b/vendor/github.com/k-sone/critbitgo/map.go new file mode 100644 index 000000000..17bcb0b88 --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/map.go @@ -0,0 +1,57 @@ +package critbitgo + +import ( + "unsafe" +) + +// The map is sorted according to the natural ordering of its keys +type SortedMap struct { + trie *Trie +} + +func (m *SortedMap) Contains(key string) bool { + return m.trie.Contains(*(*[]byte)(unsafe.Pointer(&key))) +} + +func (m *SortedMap) Get(key string) (value interface{}, ok bool) { + return m.trie.Get(*(*[]byte)(unsafe.Pointer(&key))) +} + +func (m *SortedMap) Set(key string, value interface{}) { + m.trie.Set([]byte(key), value) +} + +func (m *SortedMap) Delete(key string) (value interface{}, ok bool) { + return m.trie.Delete(*(*[]byte)(unsafe.Pointer(&key))) +} + +func (m *SortedMap) Clear() { + m.trie.Clear() +} + +func (m *SortedMap) Size() int { + return m.trie.Size() +} + +// Returns a slice of sorted keys +func (m *SortedMap) Keys() []string { + keys := make([]string, 0, m.Size()) + m.trie.Allprefixed([]byte{}, func(k []byte, v interface{}) bool { + keys = append(keys, string(k)) + return true + }) + return keys +} + +// Executes a provided function for each element that has a given prefix. +// if handle returns `false`, the iteration is aborted. +func (m *SortedMap) Each(prefix string, handle func(key string, value interface{}) bool) bool { + return m.trie.Allprefixed([]byte(prefix), func(k []byte, v interface{}) bool { + return handle(string(k), v) + }) +} + +// Create a SortedMap +func NewSortedMap() *SortedMap { + return &SortedMap{NewTrie()} +} diff --git a/vendor/github.com/k-sone/critbitgo/net.go b/vendor/github.com/k-sone/critbitgo/net.go new file mode 100644 index 000000000..047313c86 --- /dev/null +++ b/vendor/github.com/k-sone/critbitgo/net.go @@ -0,0 +1,323 @@ +package critbitgo + +import ( + "net" +) + +var ( + mask32 = net.IPMask{0xff, 0xff, 0xff, 0xff} + mask128 = net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} +) + +// IP routing table. +type Net struct { + trie *Trie +} + +// Add a route. +// If `r` is not IPv4/IPv6 network, returns an error. +func (n *Net) Add(r *net.IPNet, value interface{}) (err error) { + var ip net.IP + if ip, _, err = netValidateIPNet(r); err == nil { + n.trie.Set(netIPNetToKey(ip, r.Mask), value) + } + return +} + +// Add a route. +// If `s` is not CIDR notation, returns an error. +func (n *Net) AddCIDR(s string, value interface{}) (err error) { + var r *net.IPNet + if _, r, err = net.ParseCIDR(s); err == nil { + n.Add(r, value) + } + return +} + +// Delete a specific route. +// If `r` is not IP4/IPv6 network or a route is not found, `ok` is false. +func (n *Net) Delete(r *net.IPNet) (value interface{}, ok bool, err error) { + var ip net.IP + if ip, _, err = netValidateIPNet(r); err == nil { + value, ok = n.trie.Delete(netIPNetToKey(ip, r.Mask)) + } + return +} + +// Delete a specific route. +// If `s` is not CIDR notation or a route is not found, `ok` is false. +func (n *Net) DeleteCIDR(s string) (value interface{}, ok bool, err error) { + var r *net.IPNet + if _, r, err = net.ParseCIDR(s); err == nil { + value, ok, err = n.Delete(r) + } + return +} + +// Get a specific route. +// If `r` is not IPv4/IPv6 network or a route is not found, `ok` is false. +func (n *Net) Get(r *net.IPNet) (value interface{}, ok bool, err error) { + var ip net.IP + if ip, _, err = netValidateIPNet(r); err == nil { + value, ok = n.trie.Get(netIPNetToKey(ip, r.Mask)) + } + return +} + +// Get a specific route. +// If `s` is not CIDR notation or a route is not found, `ok` is false. +func (n *Net) GetCIDR(s string) (value interface{}, ok bool, err error) { + var r *net.IPNet + if _, r, err = net.ParseCIDR(s); err == nil { + value, ok, err = n.Get(r) + } + return +} + +// Return a specific route by using the longest prefix matching. +// If `r` is not IPv4/IPv6 network or a route is not found, `route` is nil. +func (n *Net) Match(r *net.IPNet) (route *net.IPNet, value interface{}, err error) { + var ip net.IP + if ip, _, err = netValidateIP(r.IP); err == nil { + if k, v := n.match(netIPNetToKey(ip, r.Mask)); k != nil { + route = netKeyToIPNet(k) + value = v + } + } + return +} + +// Return a specific route by using the longest prefix matching. +// If `s` is not CIDR notation, or a route is not found, `route` is nil. +func (n *Net) MatchCIDR(s string) (route *net.IPNet, value interface{}, err error) { + var r *net.IPNet + if _, r, err = net.ParseCIDR(s); err == nil { + route, value, err = n.Match(r) + } + return +} + +// Return a bool indicating whether a route would be found +func (n *Net) ContainedIP(ip net.IP) (contained bool, err error) { + k, _, err := n.matchIP(ip) + contained = k != nil + return +} + +// Return a specific route by using the longest prefix matching. +// If `ip` is invalid IP, or a route is not found, `route` is nil. +func (n *Net) MatchIP(ip net.IP) (route *net.IPNet, value interface{}, err error) { + k, v, err := n.matchIP(ip) + if k != nil { + route = netKeyToIPNet(k) + value = v + } + return +} + +func (n *Net) matchIP(ip net.IP) (k []byte, v interface{}, err error) { + var isV4 bool + ip, isV4, err = netValidateIP(ip) + if err != nil { + return + } + var mask net.IPMask + if isV4 { + mask = mask32 + } else { + mask = mask128 + } + k, v = n.match(netIPNetToKey(ip, mask)) + return +} + +func (n *Net) match(key []byte) ([]byte, interface{}) { + if n.trie.size > 0 { + if node := lookup(&n.trie.root, key, false); node != nil { + return node.external.key, node.external.value + } + } + return nil, nil +} + +func lookup(p *node, key []byte, backtracking bool) *node { + if p.internal != nil { + var direction int + if p.internal.offset == len(key)-1 { + // selecting the larger side when comparing the mask + direction = 1 + } else if backtracking { + direction = 0 + } else { + direction = p.internal.direction(key) + } + + if c := lookup(&p.internal.child[direction], key, backtracking); c != nil { + return c + } + if direction == 1 { + // search other node + return lookup(&p.internal.child[0], key, true) + } + return nil + } else { + nlen := len(p.external.key) + if nlen != len(key) { + return nil + } + + // check mask + mask := p.external.key[nlen-1] + if mask > key[nlen-1] { + return nil + } + + // compare both keys with mask + div := int(mask >> 3) + for i := 0; i < div; i++ { + if p.external.key[i] != key[i] { + return nil + } + } + if mod := uint(mask & 0x07); mod > 0 { + bit := 8 - mod + if p.external.key[div] != key[div]&(0xff>>bit<> 3) + if mod := uint(mask & 0x07); mod != 0 { + bit = 8 - mod + } + } + } + wrapper := func(key []byte, value interface{}) bool { + if bit != 0 { + if prefix[div]>>bit != key[div]>>bit { + return false + } + } + return handle(netKeyToIPNet(key), value) + } + n.trie.Allprefixed(prefix[0:div], wrapper) +} + +func walkMatch(p *node, key []byte, handle func(*net.IPNet, interface{}) bool) bool { + if p.internal != nil { + if !walkMatch(&p.internal.child[0], key, handle) { + return false + } + + if p.internal.offset >= len(key)-1 || key[p.internal.offset]&p.internal.bit > 0 { + return walkMatch(&p.internal.child[1], key, handle) + } + return true + } + + mask := p.external.key[len(p.external.key)-1] + if key[len(key)-1] < mask { + return true + } + + div := int(mask >> 3) + for i := 0; i < div; i++ { + if p.external.key[i] != key[i] { + return true + } + } + + if mod := uint(mask & 0x07); mod > 0 { + bit := 8 - mod + if p.external.key[div] != key[div]&(0xff>>bit< 0 { + walkMatch(&n.trie.root, netIPNetToKey(r.IP, r.Mask), handle) + } +} + +// Deletes all routes. +func (n *Net) Clear() { + n.trie.Clear() +} + +// Returns number of routes. +func (n *Net) Size() int { + return n.trie.Size() +} + +// Create IP routing table +func NewNet() *Net { + return &Net{NewTrie()} +} + +func netValidateIP(ip net.IP) (nIP net.IP, isV4 bool, err error) { + if v4 := ip.To4(); v4 != nil { + nIP = v4 + isV4 = true + } else if ip.To16() != nil { + nIP = ip + } else { + err = &net.AddrError{Err: "Invalid IP address", Addr: ip.String()} + } + return +} + +func netValidateIPNet(r *net.IPNet) (nIP net.IP, isV4 bool, err error) { + if r == nil { + err = &net.AddrError{Err: "IP network is nil"} + return + } + return netValidateIP(r.IP) +} + +func netIPNetToKey(ip net.IP, mask net.IPMask) []byte { + // +--------------+------+ + // | ip address.. | mask | + // +--------------+------+ + ones, _ := mask.Size() + return append(ip, byte(ones)) +} + +func netKeyToIPNet(k []byte) *net.IPNet { + iplen := len(k) - 1 + return &net.IPNet{ + IP: net.IP(k[:iplen]), + Mask: net.CIDRMask(int(k[iplen]), iplen*8), + } +} diff --git a/vendor/github.com/magiconair/properties/.travis.yml b/vendor/github.com/magiconair/properties/.travis.yml index 1a30a6cbd..baf9031df 100644 --- a/vendor/github.com/magiconair/properties/.travis.yml +++ b/vendor/github.com/magiconair/properties/.travis.yml @@ -13,4 +13,5 @@ go: - "1.13.x" - "1.14.x" - "1.15.x" + - "1.16.x" - tip diff --git a/vendor/github.com/magiconair/properties/properties.go b/vendor/github.com/magiconair/properties/properties.go index 0d0fc2820..1529e7223 100644 --- a/vendor/github.com/magiconair/properties/properties.go +++ b/vendor/github.com/magiconair/properties/properties.go @@ -637,7 +637,7 @@ func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n i } for _, c := range comments { - x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc)) + x, err = fmt.Fprintf(w, "%s%s\n", prefix, c) if err != nil { return } diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml deleted file mode 100644 index 7942c565c..000000000 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) - diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index e055952b6..ca0483711 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,6 +1,6 @@ # go-colorable -[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) +[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest) [![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) [![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go index 1f7806fe1..416d1bbbf 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index 08cbd1e0f..766d94603 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -1,5 +1,5 @@ -// +build !windows -// +build !appengine +//go:build !windows && !appengine +// +build !windows,!appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 41215d7fc..1846ad5ab 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package colorable @@ -452,18 +452,22 @@ func (w *Writer) Write(data []byte) (n int, err error) { } else { er = bytes.NewReader(data) } - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop diff --git a/vendor/github.com/mattn/go-colorable/go.mod b/vendor/github.com/mattn/go-colorable/go.mod index 1e590b819..27351c027 100644 --- a/vendor/github.com/mattn/go-colorable/go.mod +++ b/vendor/github.com/mattn/go-colorable/go.mod @@ -1,8 +1,8 @@ module github.com/mattn/go-colorable require ( - github.com/mattn/go-isatty v0.0.12 - golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect + github.com/mattn/go-isatty v0.0.14 + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect ) go 1.13 diff --git a/vendor/github.com/mattn/go-colorable/go.sum b/vendor/github.com/mattn/go-colorable/go.sum index cf5b95d97..40c33b333 100644 --- a/vendor/github.com/mattn/go-colorable/go.sum +++ b/vendor/github.com/mattn/go-colorable/go.sum @@ -1,5 +1,5 @@ -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go index 95f2c6be2..05d6f74bf 100644 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -18,18 +18,22 @@ func NewNonColorable(w io.Writer) io.Writer { // Write writes data on console func (w *NonColorable) Write(data []byte) (n int, err error) { er := bytes.NewReader(data) - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop @@ -38,7 +42,6 @@ loop: continue } - var buf bytes.Buffer for { c, err := er.ReadByte() if err != nil { @@ -47,7 +50,6 @@ loop: if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { break } - buf.Write([]byte(string(c))) } } diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml deleted file mode 100644 index 604314dd4..000000000 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod index 605c4c221..c9a20b7f3 100644 --- a/vendor/github.com/mattn/go-isatty/go.mod +++ b/vendor/github.com/mattn/go-isatty/go.mod @@ -2,4 +2,4 @@ module github.com/mattn/go-isatty go 1.12 -require golang.org/x/sys v0.0.0-20200116001909-b77594299b42 +require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 711f28808..39bbcf00f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -1,3 +1,4 @@ +//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine // +build darwin freebsd openbsd netbsd dragonfly // +build !appengine diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go index ff714a376..31503226f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_others.go +++ b/vendor/github.com/mattn/go-isatty/isatty_others.go @@ -1,4 +1,5 @@ -// +build appengine js nacl +//go:build appengine || js || nacl || wasm +// +build appengine js nacl wasm package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go index c5b6e0c08..bae7f9bb3 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go +++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go @@ -1,3 +1,4 @@ +//go:build plan9 // +build plan9 package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go index bdd5c79a0..0c3acf2dc 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_solaris.go +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -1,5 +1,5 @@ -// +build solaris -// +build !appengine +//go:build solaris && !appengine +// +build solaris,!appengine package isatty @@ -8,10 +8,9 @@ import ( ) // IsTerminal returns true if the given file descriptor is a terminal. -// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c func IsTerminal(fd uintptr) bool { - var termio unix.Termio - err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + _, err := unix.IoctlGetTermio(int(fd), unix.TCGETA) return err == nil } diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go index 31a1ca973..67787657f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -1,4 +1,5 @@ -// +build linux aix +//go:build (linux || aix || zos) && !appengine +// +build linux aix zos // +build !appengine package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go index 1fa869154..8e3c99171 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package isatty @@ -76,7 +76,7 @@ func isCygwinPipeName(name string) bool { } // getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler -// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion +// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion // guys are using Windows XP, this is a workaround for those guys, it will also work on system from // Windows vista to 10 // see https://stackoverflow.com/a/18792477 for details diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json deleted file mode 100644 index 5ae9d96b7..000000000 --- a/vendor/github.com/mattn/go-isatty/renovate.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "config:base" - ], - "postUpdateOptions": [ - "gomodTidy" - ] -} diff --git a/vendor/github.com/mitchellh/mapstructure/.travis.yml b/vendor/github.com/mitchellh/mapstructure/.travis.yml deleted file mode 100644 index 5e31a95a8..000000000 --- a/vendor/github.com/mitchellh/mapstructure/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go - -go: - - "1.14.x" - - tip - -script: - - go test - - go test -bench . -benchmem diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md index 20eea2b7a..38a099162 100644 --- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -1,3 +1,25 @@ +## 1.4.3 + +* Fix cases where `json.Number` didn't decode properly [GH-261] + +## 1.4.2 + +* Custom name matchers to support any sort of casing, formatting, etc. for + field names. [GH-250] +* Fix possible panic in ComposeDecodeHookFunc [GH-251] + +## 1.4.1 + +* Fix regression where `*time.Time` value would be set to empty and not be sent + to decode hooks properly [GH-232] + +## 1.4.0 + +* A new decode hook type `DecodeHookFuncValue` has been added that has + access to the full values. [GH-183] +* Squash is now supported with embedded fields that are struct pointers [GH-205] +* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206] + ## 1.3.3 * Decoding maps from maps creates a settable value for decode hooks [GH-203] diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go index 1f0abc65a..4d4bbc733 100644 --- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -1,6 +1,7 @@ package mapstructure import ( + "encoding" "errors" "fmt" "net" @@ -16,10 +17,11 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // Create variables here so we can reference them with the reflect pkg var f1 DecodeHookFuncType var f2 DecodeHookFuncKind + var f3 DecodeHookFuncValue // Fill in the variables into this interface and the rest is done // automatically using the reflect package. - potential := []interface{}{f1, f2} + potential := []interface{}{f1, f2, f3} v := reflect.ValueOf(h) vt := v.Type() @@ -38,13 +40,15 @@ func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { // that took reflect.Kind instead of reflect.Type. func DecodeHookExec( raw DecodeHookFunc, - from reflect.Type, to reflect.Type, - data interface{}) (interface{}, error) { + from reflect.Value, to reflect.Value) (interface{}, error) { + switch f := typedDecodeHook(raw).(type) { case DecodeHookFuncType: - return f(from, to, data) + return f(from.Type(), to.Type(), from.Interface()) case DecodeHookFuncKind: - return f(from.Kind(), to.Kind(), data) + return f(from.Kind(), to.Kind(), from.Interface()) + case DecodeHookFuncValue: + return f(from, to) default: return nil, errors.New("invalid decode hook signature") } @@ -56,22 +60,17 @@ func DecodeHookExec( // The composed funcs are called in order, with the result of the // previous transformation. func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { - return func( - f reflect.Type, - t reflect.Type, - data interface{}) (interface{}, error) { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { var err error + data := f.Interface() + + newFrom := f for _, f1 := range fs { - data, err = DecodeHookExec(f1, f, t, data) + data, err = DecodeHookExec(f1, newFrom, t) if err != nil { return nil, err } - - // Modify the from kind to be correct with the new data - f = nil - if val := reflect.ValueOf(data); val.IsValid() { - f = val.Type() - } + newFrom = reflect.ValueOf(data) } return data, nil @@ -215,3 +214,44 @@ func WeaklyTypedHook( return data, nil } + +func RecursiveStructToMapHookFunc() DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + if f.Kind() != reflect.Struct { + return f.Interface(), nil + } + + var i interface{} = struct{}{} + if t.Type() != reflect.TypeOf(&i).Elem() { + return f.Interface(), nil + } + + m := make(map[string]interface{}) + t.Set(reflect.ValueOf(m)) + + return f.Interface(), nil + } +} + +// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies +// strings to the UnmarshalText function, when the target type +// implements the encoding.TextUnmarshaler interface +func TextUnmarshallerHookFunc() DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + result := reflect.New(t).Interface() + unmarshaller, ok := result.(encoding.TextUnmarshaler) + if !ok { + return data, nil + } + if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { + return nil, err + } + return result, nil + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go index f41bcc58f..6b81b0067 100644 --- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -72,6 +72,17 @@ // "name": "alice", // } // +// When decoding from a struct to a map, the squash tag squashes the struct +// fields into a single map. Using the example structs from above: +// +// Friend{Person: Person{Name: "alice"}} +// +// Will be decoded into a map: +// +// map[string]interface{}{ +// "name": "alice", +// } +// // DecoderConfig has a field that changes the behavior of mapstructure // to always squash embedded structs. // @@ -161,10 +172,11 @@ import ( // data transformations. See "DecodeHook" in the DecoderConfig // struct. // -// The type should be DecodeHookFuncType or DecodeHookFuncKind. -// Either is accepted. Types are a superset of Kinds (Types can return -// Kinds) and are generally a richer thing to use, but Kinds are simpler -// if you only need those. +// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or +// DecodeHookFuncValue. +// Values are a superset of Types (Values can return types), and Types are a +// superset of Kinds (Types can return Kinds) and are generally a richer thing +// to use, but Kinds are simpler if you only need those. // // The reason DecodeHookFunc is multi-typed is for backwards compatibility: // we started with Kinds and then realized Types were the better solution, @@ -180,15 +192,22 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface // source and target types. type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) +// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target +// values. +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) + // DecoderConfig is the configuration that is used to create a new decoder // and allows customization of various aspects of decoding. type DecoderConfig struct { // DecodeHook, if set, will be called before any decoding and any // type conversion (if WeaklyTypedInput is on). This lets you modify - // the values before they're set down onto the resulting struct. + // the values before they're set down onto the resulting struct. The + // DecodeHook is called for every map and value in the input. This means + // that if a struct has embedded fields with squash tags the decode hook + // is called only once with all of the input data, not once for each + // embedded struct. // - // If an error is returned, the entire decode will fail with that - // error. + // If an error is returned, the entire decode will fail with that error. DecodeHook DecodeHookFunc // If ErrorUnused is true, then it is an error for there to exist @@ -239,6 +258,11 @@ type DecoderConfig struct { // The tag name that mapstructure reads for field names. This // defaults to "mapstructure" TagName string + + // MatchName is the function used to match the map key to the struct + // field name or tag. Defaults to `strings.EqualFold`. This can be used + // to implement case-sensitive tag values, support snake casing, etc. + MatchName func(mapKey, fieldName string) bool } // A Decoder takes a raw interface value and turns it into structured @@ -357,6 +381,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { config.TagName = "mapstructure" } + if config.MatchName == nil { + config.MatchName = strings.EqualFold + } + result := &Decoder{ config: config, } @@ -409,9 +437,7 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e if d.config.DecodeHook != nil { // We have a DecodeHook, so let's pre-process the input. var err error - input, err = DecodeHookExec( - d.config.DecodeHook, - inputVal.Type(), outVal.Type(), input) + input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) if err != nil { return fmt.Errorf("error decoding '%s': %s", name, err) } @@ -562,8 +588,8 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) if !converted { return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } return nil @@ -588,7 +614,12 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er val.SetInt(0) } case dataKind == reflect.String && d.config.WeaklyTypedInput: - i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseInt(str, 0, val.Type().Bits()) if err == nil { val.SetInt(i) } else { @@ -604,8 +635,8 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er val.SetInt(i) default: return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } return nil @@ -640,7 +671,12 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e val.SetUint(0) } case dataKind == reflect.String && d.config.WeaklyTypedInput: - i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseUint(str, 0, val.Type().Bits()) if err == nil { val.SetUint(i) } else { @@ -648,20 +684,16 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) - i, err := jn.Int64() + i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { return fmt.Errorf( "error decoding json.Number into %s: %s", name, err) } - if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) - } - val.SetUint(uint64(i)) + val.SetUint(i) default: return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } return nil @@ -691,8 +723,8 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } default: return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } return nil @@ -717,7 +749,12 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) val.SetFloat(0) } case dataKind == reflect.String && d.config.WeaklyTypedInput: - f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) + str := dataVal.String() + if str == "" { + str = "0" + } + + f, err := strconv.ParseFloat(str, val.Type().Bits()) if err == nil { val.SetFloat(f) } else { @@ -733,8 +770,8 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) val.SetFloat(i) default: return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } return nil @@ -785,7 +822,7 @@ func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val ref for i := 0; i < dataVal.Len(); i++ { err := d.decode( - fmt.Sprintf("%s[%d]", name, i), + name+"["+strconv.Itoa(i)+"]", dataVal.Index(i).Interface(), val) if err != nil { return err @@ -818,7 +855,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle } for _, k := range dataVal.MapKeys() { - fieldName := fmt.Sprintf("%s[%s]", name, k) + fieldName := name + "[" + k.String() + "]" // First decode the key into the proper type currentKey := reflect.Indirect(reflect.New(valKeyType)) @@ -871,6 +908,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // If Squash is set in the config, we squash the field down. squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous + // Determine the name of the key in the map if index := strings.Index(tagValue, ","); index != -1 { if tagValue[:index] == "-" { @@ -883,8 +921,16 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re // If "squash" is specified in the tag, we squash the field down. squash = !squash && strings.Index(tagValue[index+1:], "squash") != -1 - if squash && v.Kind() != reflect.Struct { - return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + if squash { + // When squashing, the embedded type can be a pointer to a struct. + if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { + v = v.Elem() + } + + // The final type must be a struct + if v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } } keyName = tagValue[:index] } else if len(tagValue) > 0 { @@ -995,8 +1041,8 @@ func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) e dataVal := reflect.Indirect(reflect.ValueOf(data)) if val.Type() != dataVal.Type() { return fmt.Errorf( - "'%s' expected type '%s', got unconvertible type '%s'", - name, val.Type(), dataVal.Type()) + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) } val.Set(dataVal) return nil @@ -1062,7 +1108,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) } currentField := valSlice.Index(i) - fieldName := fmt.Sprintf("%s[%d]", name, i) + fieldName := name + "[" + strconv.Itoa(i) + "]" if err := d.decode(fieldName, currentData, currentField); err != nil { errors = appendErrors(errors, err) } @@ -1129,7 +1175,7 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) currentData := dataVal.Index(i).Interface() currentField := valArray.Index(i) - fieldName := fmt.Sprintf("%s[%d]", name, i) + fieldName := name + "[" + strconv.Itoa(i) + "]" if err := d.decode(fieldName, currentData, currentField); err != nil { errors = appendErrors(errors, err) } @@ -1232,10 +1278,14 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e for i := 0; i < structType.NumField(); i++ { fieldType := structType.Field(i) - fieldKind := fieldType.Type.Kind() + fieldVal := structVal.Field(i) + if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { + // Handle embedded struct pointers as embedded structs. + fieldVal = fieldVal.Elem() + } // If "squash" is specified in the tag, we squash the field down. - squash := d.config.Squash && fieldKind == reflect.Struct && fieldType.Anonymous + squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous remain := false // We always parse the tags cause we're looking for other tags too @@ -1253,21 +1303,21 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } if squash { - if fieldKind != reflect.Struct { + if fieldVal.Kind() != reflect.Struct { errors = appendErrors(errors, - fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) + fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) } else { - structs = append(structs, structVal.FieldByName(fieldType.Name)) + structs = append(structs, fieldVal) } continue } // Build our field if remain { - remainField = &field{fieldType, structVal.Field(i)} + remainField = &field{fieldType, fieldVal} } else { // Normal struct field, store it away - fields = append(fields, field{fieldType, structVal.Field(i)}) + fields = append(fields, field{fieldType, fieldVal}) } } } @@ -1295,7 +1345,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e continue } - if strings.EqualFold(mK, fieldName) { + if d.config.MatchName(mK, fieldName) { rawMapKey = dataValKey rawMapVal = dataVal.MapIndex(dataValKey) break @@ -1326,7 +1376,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e // If the name is empty string, then we're at the root, and we // don't dot-join the fields. if name != "" { - fieldName = fmt.Sprintf("%s.%s", name, fieldName) + fieldName = name + "." + fieldName } if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { @@ -1373,7 +1423,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e for rawKey := range dataValKeysUnused { key := rawKey.(string) if name != "" { - key = fmt.Sprintf("%s.%s", name, key) + key = name + "." + key } d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) diff --git a/vendor/github.com/osrg/gobgp/v3/LICENSE b/vendor/github.com/osrg/gobgp/v3/LICENSE new file mode 100644 index 000000000..5c304d1a4 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/vendor/github.com/osrg/gobgp/v3/api/attribute.pb.go b/vendor/github.com/osrg/gobgp/v3/api/attribute.pb.go new file mode 100644 index 000000000..e733a6461 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/attribute.pb.go @@ -0,0 +1,10273 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.19.1 +// source: attribute.proto + +package apipb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + 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 LsOspfRouteType int32 + +const ( + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_UNKNOWN LsOspfRouteType = 0 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_INTRA_AREA LsOspfRouteType = 1 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_INTER_AREA LsOspfRouteType = 2 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_EXTERNAL1 LsOspfRouteType = 3 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_EXTERNAL2 LsOspfRouteType = 4 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_NSSA1 LsOspfRouteType = 5 + LsOspfRouteType_LS_OSPF_ROUTE_TYPE_NSSA2 LsOspfRouteType = 6 +) + +// Enum value maps for LsOspfRouteType. +var ( + LsOspfRouteType_name = map[int32]string{ + 0: "LS_OSPF_ROUTE_TYPE_UNKNOWN", + 1: "LS_OSPF_ROUTE_TYPE_INTRA_AREA", + 2: "LS_OSPF_ROUTE_TYPE_INTER_AREA", + 3: "LS_OSPF_ROUTE_TYPE_EXTERNAL1", + 4: "LS_OSPF_ROUTE_TYPE_EXTERNAL2", + 5: "LS_OSPF_ROUTE_TYPE_NSSA1", + 6: "LS_OSPF_ROUTE_TYPE_NSSA2", + } + LsOspfRouteType_value = map[string]int32{ + "LS_OSPF_ROUTE_TYPE_UNKNOWN": 0, + "LS_OSPF_ROUTE_TYPE_INTRA_AREA": 1, + "LS_OSPF_ROUTE_TYPE_INTER_AREA": 2, + "LS_OSPF_ROUTE_TYPE_EXTERNAL1": 3, + "LS_OSPF_ROUTE_TYPE_EXTERNAL2": 4, + "LS_OSPF_ROUTE_TYPE_NSSA1": 5, + "LS_OSPF_ROUTE_TYPE_NSSA2": 6, + } +) + +func (x LsOspfRouteType) Enum() *LsOspfRouteType { + p := new(LsOspfRouteType) + *p = x + return p +} + +func (x LsOspfRouteType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (LsOspfRouteType) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[0].Descriptor() +} + +func (LsOspfRouteType) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[0] +} + +func (x LsOspfRouteType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use LsOspfRouteType.Descriptor instead. +func (LsOspfRouteType) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{0} +} + +// Based om RFC 7752, Table 1. +type LsNLRIType int32 + +const ( + LsNLRIType_LS_NLRI_UNKNOWN LsNLRIType = 0 + LsNLRIType_LS_NLRI_NODE LsNLRIType = 1 + LsNLRIType_LS_NLRI_LINK LsNLRIType = 2 + LsNLRIType_LS_NLRI_PREFIX_V4 LsNLRIType = 3 + LsNLRIType_LS_NLRI_PREFIX_V6 LsNLRIType = 4 +) + +// Enum value maps for LsNLRIType. +var ( + LsNLRIType_name = map[int32]string{ + 0: "LS_NLRI_UNKNOWN", + 1: "LS_NLRI_NODE", + 2: "LS_NLRI_LINK", + 3: "LS_NLRI_PREFIX_V4", + 4: "LS_NLRI_PREFIX_V6", + } + LsNLRIType_value = map[string]int32{ + "LS_NLRI_UNKNOWN": 0, + "LS_NLRI_NODE": 1, + "LS_NLRI_LINK": 2, + "LS_NLRI_PREFIX_V4": 3, + "LS_NLRI_PREFIX_V6": 4, + } +) + +func (x LsNLRIType) Enum() *LsNLRIType { + p := new(LsNLRIType) + *p = x + return p +} + +func (x LsNLRIType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (LsNLRIType) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[1].Descriptor() +} + +func (LsNLRIType) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[1] +} + +func (x LsNLRIType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use LsNLRIType.Descriptor instead. +func (LsNLRIType) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{1} +} + +type LsProtocolID int32 + +const ( + LsProtocolID_LS_PROTOCOL_UNKNOWN LsProtocolID = 0 + LsProtocolID_LS_PROTOCOL_ISIS_L1 LsProtocolID = 1 + LsProtocolID_LS_PROTOCOL_ISIS_L2 LsProtocolID = 2 + LsProtocolID_LS_PROTOCOL_OSPF_V2 LsProtocolID = 3 + LsProtocolID_LS_PROTOCOL_DIRECT LsProtocolID = 4 + LsProtocolID_LS_PROTOCOL_STATIC LsProtocolID = 5 + LsProtocolID_LS_PROTOCOL_OSPF_V3 LsProtocolID = 6 +) + +// Enum value maps for LsProtocolID. +var ( + LsProtocolID_name = map[int32]string{ + 0: "LS_PROTOCOL_UNKNOWN", + 1: "LS_PROTOCOL_ISIS_L1", + 2: "LS_PROTOCOL_ISIS_L2", + 3: "LS_PROTOCOL_OSPF_V2", + 4: "LS_PROTOCOL_DIRECT", + 5: "LS_PROTOCOL_STATIC", + 6: "LS_PROTOCOL_OSPF_V3", + } + LsProtocolID_value = map[string]int32{ + "LS_PROTOCOL_UNKNOWN": 0, + "LS_PROTOCOL_ISIS_L1": 1, + "LS_PROTOCOL_ISIS_L2": 2, + "LS_PROTOCOL_OSPF_V2": 3, + "LS_PROTOCOL_DIRECT": 4, + "LS_PROTOCOL_STATIC": 5, + "LS_PROTOCOL_OSPF_V3": 6, + } +) + +func (x LsProtocolID) Enum() *LsProtocolID { + p := new(LsProtocolID) + *p = x + return p +} + +func (x LsProtocolID) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (LsProtocolID) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[2].Descriptor() +} + +func (LsProtocolID) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[2] +} + +func (x LsProtocolID) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use LsProtocolID.Descriptor instead. +func (LsProtocolID) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{2} +} + +type SRv6Behavior int32 + +const ( + SRv6Behavior_RESERVED SRv6Behavior = 0 + SRv6Behavior_END SRv6Behavior = 1 + SRv6Behavior_END_WITH_PSP SRv6Behavior = 2 + SRv6Behavior_END_WITH_USP SRv6Behavior = 3 + SRv6Behavior_END_WITH_PSP_USP SRv6Behavior = 4 + SRv6Behavior_ENDX SRv6Behavior = 5 + SRv6Behavior_ENDX_WITH_PSP SRv6Behavior = 6 + SRv6Behavior_ENDX_WITH_USP SRv6Behavior = 7 + SRv6Behavior_ENDX_WITH_PSP_USP SRv6Behavior = 8 + SRv6Behavior_ENDT SRv6Behavior = 9 + SRv6Behavior_ENDT_WITH_PSP SRv6Behavior = 10 + SRv6Behavior_ENDT_WITH_USP SRv6Behavior = 11 + SRv6Behavior_ENDT_WITH_PSP_USP SRv6Behavior = 12 + SRv6Behavior_END_B6_ENCAPS SRv6Behavior = 14 + SRv6Behavior_END_BM SRv6Behavior = 15 + SRv6Behavior_END_DX6 SRv6Behavior = 16 + SRv6Behavior_END_DX4 SRv6Behavior = 17 + SRv6Behavior_END_DT6 SRv6Behavior = 18 + SRv6Behavior_END_DT4 SRv6Behavior = 19 + SRv6Behavior_END_DT46 SRv6Behavior = 20 + SRv6Behavior_END_DX2 SRv6Behavior = 21 + SRv6Behavior_END_DX2V SRv6Behavior = 22 + SRv6Behavior_END_DT2U SRv6Behavior = 23 + SRv6Behavior_END_DT2M SRv6Behavior = 24 + SRv6Behavior_END_B6_ENCAPS_Red SRv6Behavior = 27 + SRv6Behavior_END_WITH_USD SRv6Behavior = 28 + SRv6Behavior_END_WITH_PSP_USD SRv6Behavior = 29 + SRv6Behavior_END_WITH_USP_USD SRv6Behavior = 30 + SRv6Behavior_END_WITH_PSP_USP_USD SRv6Behavior = 31 + SRv6Behavior_ENDX_WITH_USD SRv6Behavior = 32 + SRv6Behavior_ENDX_WITH_PSP_USD SRv6Behavior = 33 + SRv6Behavior_ENDX_WITH_USP_USD SRv6Behavior = 34 + SRv6Behavior_ENDX_WITH_PSP_USP_USD SRv6Behavior = 35 + SRv6Behavior_ENDT_WITH_USD SRv6Behavior = 36 + SRv6Behavior_ENDT_WITH_PSP_USD SRv6Behavior = 37 + SRv6Behavior_ENDT_WITH_USP_USD SRv6Behavior = 38 + SRv6Behavior_ENDT_WITH_PSP_USP_USD SRv6Behavior = 39 + SRv6Behavior_ENDM_GTP6D SRv6Behavior = 69 // 0x0045 + SRv6Behavior_ENDM_GTP6DI SRv6Behavior = 70 // 0x0046 + SRv6Behavior_ENDM_GTP6E SRv6Behavior = 71 // 0x0047 + SRv6Behavior_ENDM_GTP4E SRv6Behavior = 72 // 0x0048 +) + +// Enum value maps for SRv6Behavior. +var ( + SRv6Behavior_name = map[int32]string{ + 0: "RESERVED", + 1: "END", + 2: "END_WITH_PSP", + 3: "END_WITH_USP", + 4: "END_WITH_PSP_USP", + 5: "ENDX", + 6: "ENDX_WITH_PSP", + 7: "ENDX_WITH_USP", + 8: "ENDX_WITH_PSP_USP", + 9: "ENDT", + 10: "ENDT_WITH_PSP", + 11: "ENDT_WITH_USP", + 12: "ENDT_WITH_PSP_USP", + 14: "END_B6_ENCAPS", + 15: "END_BM", + 16: "END_DX6", + 17: "END_DX4", + 18: "END_DT6", + 19: "END_DT4", + 20: "END_DT46", + 21: "END_DX2", + 22: "END_DX2V", + 23: "END_DT2U", + 24: "END_DT2M", + 27: "END_B6_ENCAPS_Red", + 28: "END_WITH_USD", + 29: "END_WITH_PSP_USD", + 30: "END_WITH_USP_USD", + 31: "END_WITH_PSP_USP_USD", + 32: "ENDX_WITH_USD", + 33: "ENDX_WITH_PSP_USD", + 34: "ENDX_WITH_USP_USD", + 35: "ENDX_WITH_PSP_USP_USD", + 36: "ENDT_WITH_USD", + 37: "ENDT_WITH_PSP_USD", + 38: "ENDT_WITH_USP_USD", + 39: "ENDT_WITH_PSP_USP_USD", + 69: "ENDM_GTP6D", + 70: "ENDM_GTP6DI", + 71: "ENDM_GTP6E", + 72: "ENDM_GTP4E", + } + SRv6Behavior_value = map[string]int32{ + "RESERVED": 0, + "END": 1, + "END_WITH_PSP": 2, + "END_WITH_USP": 3, + "END_WITH_PSP_USP": 4, + "ENDX": 5, + "ENDX_WITH_PSP": 6, + "ENDX_WITH_USP": 7, + "ENDX_WITH_PSP_USP": 8, + "ENDT": 9, + "ENDT_WITH_PSP": 10, + "ENDT_WITH_USP": 11, + "ENDT_WITH_PSP_USP": 12, + "END_B6_ENCAPS": 14, + "END_BM": 15, + "END_DX6": 16, + "END_DX4": 17, + "END_DT6": 18, + "END_DT4": 19, + "END_DT46": 20, + "END_DX2": 21, + "END_DX2V": 22, + "END_DT2U": 23, + "END_DT2M": 24, + "END_B6_ENCAPS_Red": 27, + "END_WITH_USD": 28, + "END_WITH_PSP_USD": 29, + "END_WITH_USP_USD": 30, + "END_WITH_PSP_USP_USD": 31, + "ENDX_WITH_USD": 32, + "ENDX_WITH_PSP_USD": 33, + "ENDX_WITH_USP_USD": 34, + "ENDX_WITH_PSP_USP_USD": 35, + "ENDT_WITH_USD": 36, + "ENDT_WITH_PSP_USD": 37, + "ENDT_WITH_USP_USD": 38, + "ENDT_WITH_PSP_USP_USD": 39, + "ENDM_GTP6D": 69, + "ENDM_GTP6DI": 70, + "ENDM_GTP6E": 71, + "ENDM_GTP4E": 72, + } +) + +func (x SRv6Behavior) Enum() *SRv6Behavior { + p := new(SRv6Behavior) + *p = x + return p +} + +func (x SRv6Behavior) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SRv6Behavior) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[3].Descriptor() +} + +func (SRv6Behavior) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[3] +} + +func (x SRv6Behavior) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SRv6Behavior.Descriptor instead. +func (SRv6Behavior) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{3} +} + +type ENLPType int32 + +const ( + ENLPType_Reserved ENLPType = 0 + ENLPType_Type1 ENLPType = 1 + ENLPType_Type2 ENLPType = 2 + ENLPType_Type3 ENLPType = 3 + ENLPType_Type4 ENLPType = 4 +) + +// Enum value maps for ENLPType. +var ( + ENLPType_name = map[int32]string{ + 0: "Reserved", + 1: "Type1", + 2: "Type2", + 3: "Type3", + 4: "Type4", + } + ENLPType_value = map[string]int32{ + "Reserved": 0, + "Type1": 1, + "Type2": 2, + "Type3": 3, + "Type4": 4, + } +) + +func (x ENLPType) Enum() *ENLPType { + p := new(ENLPType) + *p = x + return p +} + +func (x ENLPType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ENLPType) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[4].Descriptor() +} + +func (ENLPType) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[4] +} + +func (x ENLPType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ENLPType.Descriptor instead. +func (ENLPType) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{4} +} + +type AsSegment_Type int32 + +const ( + AsSegment_UNKNOWN AsSegment_Type = 0 + AsSegment_AS_SET AsSegment_Type = 1 + AsSegment_AS_SEQUENCE AsSegment_Type = 2 + AsSegment_AS_CONFED_SEQUENCE AsSegment_Type = 3 + AsSegment_AS_CONFED_SET AsSegment_Type = 4 +) + +// Enum value maps for AsSegment_Type. +var ( + AsSegment_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "AS_SET", + 2: "AS_SEQUENCE", + 3: "AS_CONFED_SEQUENCE", + 4: "AS_CONFED_SET", + } + AsSegment_Type_value = map[string]int32{ + "UNKNOWN": 0, + "AS_SET": 1, + "AS_SEQUENCE": 2, + "AS_CONFED_SEQUENCE": 3, + "AS_CONFED_SET": 4, + } +) + +func (x AsSegment_Type) Enum() *AsSegment_Type { + p := new(AsSegment_Type) + *p = x + return p +} + +func (x AsSegment_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AsSegment_Type) Descriptor() protoreflect.EnumDescriptor { + return file_attribute_proto_enumTypes[5].Descriptor() +} + +func (AsSegment_Type) Type() protoreflect.EnumType { + return &file_attribute_proto_enumTypes[5] +} + +func (x AsSegment_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AsSegment_Type.Descriptor instead. +func (AsSegment_Type) EnumDescriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{1, 0} +} + +type OriginAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Origin uint32 `protobuf:"varint,1,opt,name=origin,proto3" json:"origin,omitempty"` +} + +func (x *OriginAttribute) Reset() { + *x = OriginAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OriginAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginAttribute) ProtoMessage() {} + +func (x *OriginAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 OriginAttribute.ProtoReflect.Descriptor instead. +func (*OriginAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{0} +} + +func (x *OriginAttribute) GetOrigin() uint32 { + if x != nil { + return x.Origin + } + return 0 +} + +type AsSegment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type AsSegment_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.AsSegment_Type" json:"type,omitempty"` + Numbers []uint32 `protobuf:"varint,2,rep,packed,name=numbers,proto3" json:"numbers,omitempty"` +} + +func (x *AsSegment) Reset() { + *x = AsSegment{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AsSegment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AsSegment) ProtoMessage() {} + +func (x *AsSegment) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 AsSegment.ProtoReflect.Descriptor instead. +func (*AsSegment) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{1} +} + +func (x *AsSegment) GetType() AsSegment_Type { + if x != nil { + return x.Type + } + return AsSegment_UNKNOWN +} + +func (x *AsSegment) GetNumbers() []uint32 { + if x != nil { + return x.Numbers + } + return nil +} + +type AsPathAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Segments []*AsSegment `protobuf:"bytes,1,rep,name=segments,proto3" json:"segments,omitempty"` +} + +func (x *AsPathAttribute) Reset() { + *x = AsPathAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AsPathAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AsPathAttribute) ProtoMessage() {} + +func (x *AsPathAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 AsPathAttribute.ProtoReflect.Descriptor instead. +func (*AsPathAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{2} +} + +func (x *AsPathAttribute) GetSegments() []*AsSegment { + if x != nil { + return x.Segments + } + return nil +} + +type NextHopAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NextHop string `protobuf:"bytes,1,opt,name=next_hop,json=nextHop,proto3" json:"next_hop,omitempty"` +} + +func (x *NextHopAttribute) Reset() { + *x = NextHopAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NextHopAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NextHopAttribute) ProtoMessage() {} + +func (x *NextHopAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 NextHopAttribute.ProtoReflect.Descriptor instead. +func (*NextHopAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{3} +} + +func (x *NextHopAttribute) GetNextHop() string { + if x != nil { + return x.NextHop + } + return "" +} + +type MultiExitDiscAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Med uint32 `protobuf:"varint,1,opt,name=med,proto3" json:"med,omitempty"` +} + +func (x *MultiExitDiscAttribute) Reset() { + *x = MultiExitDiscAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MultiExitDiscAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MultiExitDiscAttribute) ProtoMessage() {} + +func (x *MultiExitDiscAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 MultiExitDiscAttribute.ProtoReflect.Descriptor instead. +func (*MultiExitDiscAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{4} +} + +func (x *MultiExitDiscAttribute) GetMed() uint32 { + if x != nil { + return x.Med + } + return 0 +} + +type LocalPrefAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalPref uint32 `protobuf:"varint,1,opt,name=local_pref,json=localPref,proto3" json:"local_pref,omitempty"` +} + +func (x *LocalPrefAttribute) Reset() { + *x = LocalPrefAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalPrefAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalPrefAttribute) ProtoMessage() {} + +func (x *LocalPrefAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 LocalPrefAttribute.ProtoReflect.Descriptor instead. +func (*LocalPrefAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{5} +} + +func (x *LocalPrefAttribute) GetLocalPref() uint32 { + if x != nil { + return x.LocalPref + } + return 0 +} + +type AtomicAggregateAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AtomicAggregateAttribute) Reset() { + *x = AtomicAggregateAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AtomicAggregateAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AtomicAggregateAttribute) ProtoMessage() {} + +func (x *AtomicAggregateAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 AtomicAggregateAttribute.ProtoReflect.Descriptor instead. +func (*AtomicAggregateAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{6} +} + +type AggregatorAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *AggregatorAttribute) Reset() { + *x = AggregatorAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AggregatorAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AggregatorAttribute) ProtoMessage() {} + +func (x *AggregatorAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 AggregatorAttribute.ProtoReflect.Descriptor instead. +func (*AggregatorAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{7} +} + +func (x *AggregatorAttribute) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *AggregatorAttribute) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type CommunitiesAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Communities []uint32 `protobuf:"varint,1,rep,packed,name=communities,proto3" json:"communities,omitempty"` +} + +func (x *CommunitiesAttribute) Reset() { + *x = CommunitiesAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommunitiesAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommunitiesAttribute) ProtoMessage() {} + +func (x *CommunitiesAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 CommunitiesAttribute.ProtoReflect.Descriptor instead. +func (*CommunitiesAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{8} +} + +func (x *CommunitiesAttribute) GetCommunities() []uint32 { + if x != nil { + return x.Communities + } + return nil +} + +type OriginatorIdAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *OriginatorIdAttribute) Reset() { + *x = OriginatorIdAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OriginatorIdAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginatorIdAttribute) ProtoMessage() {} + +func (x *OriginatorIdAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 OriginatorIdAttribute.ProtoReflect.Descriptor instead. +func (*OriginatorIdAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{9} +} + +func (x *OriginatorIdAttribute) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ClusterListAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` +} + +func (x *ClusterListAttribute) Reset() { + *x = ClusterListAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterListAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterListAttribute) ProtoMessage() {} + +func (x *ClusterListAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 ClusterListAttribute.ProtoReflect.Descriptor instead. +func (*ClusterListAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{10} +} + +func (x *ClusterListAttribute) GetIds() []string { + if x != nil { + return x.Ids + } + return nil +} + +// IPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=1 +// - AFI=2, SAFI=1 +type IPAddressPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PrefixLen uint32 `protobuf:"varint,1,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *IPAddressPrefix) Reset() { + *x = IPAddressPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IPAddressPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IPAddressPrefix) ProtoMessage() {} + +func (x *IPAddressPrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 IPAddressPrefix.ProtoReflect.Descriptor instead. +func (*IPAddressPrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{11} +} + +func (x *IPAddressPrefix) GetPrefixLen() uint32 { + if x != nil { + return x.PrefixLen + } + return 0 +} + +func (x *IPAddressPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +// LabeledIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=4 +// - AFI=2, SAFI=4 +type LabeledIPAddressPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Labels []uint32 `protobuf:"varint,1,rep,packed,name=labels,proto3" json:"labels,omitempty"` + PrefixLen uint32 `protobuf:"varint,2,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *LabeledIPAddressPrefix) Reset() { + *x = LabeledIPAddressPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LabeledIPAddressPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LabeledIPAddressPrefix) ProtoMessage() {} + +func (x *LabeledIPAddressPrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 LabeledIPAddressPrefix.ProtoReflect.Descriptor instead. +func (*LabeledIPAddressPrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{12} +} + +func (x *LabeledIPAddressPrefix) GetLabels() []uint32 { + if x != nil { + return x.Labels + } + return nil +} + +func (x *LabeledIPAddressPrefix) GetPrefixLen() uint32 { + if x != nil { + return x.PrefixLen + } + return 0 +} + +func (x *LabeledIPAddressPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +// EncapsulationNLRI represents the NLRI for: +// - AFI=1, SAFI=7 +// - AFI=2, SAFI=7 +type EncapsulationNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *EncapsulationNLRI) Reset() { + *x = EncapsulationNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EncapsulationNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EncapsulationNLRI) ProtoMessage() {} + +func (x *EncapsulationNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 EncapsulationNLRI.ProtoReflect.Descriptor instead. +func (*EncapsulationNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{13} +} + +func (x *EncapsulationNLRI) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type RouteDistinguisherTwoOctetASN struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Admin uint32 `protobuf:"varint,1,opt,name=admin,proto3" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned,proto3" json:"assigned,omitempty"` +} + +func (x *RouteDistinguisherTwoOctetASN) Reset() { + *x = RouteDistinguisherTwoOctetASN{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteDistinguisherTwoOctetASN) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteDistinguisherTwoOctetASN) ProtoMessage() {} + +func (x *RouteDistinguisherTwoOctetASN) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 RouteDistinguisherTwoOctetASN.ProtoReflect.Descriptor instead. +func (*RouteDistinguisherTwoOctetASN) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{14} +} + +func (x *RouteDistinguisherTwoOctetASN) GetAdmin() uint32 { + if x != nil { + return x.Admin + } + return 0 +} + +func (x *RouteDistinguisherTwoOctetASN) GetAssigned() uint32 { + if x != nil { + return x.Assigned + } + return 0 +} + +type RouteDistinguisherIPAddress struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned,proto3" json:"assigned,omitempty"` +} + +func (x *RouteDistinguisherIPAddress) Reset() { + *x = RouteDistinguisherIPAddress{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteDistinguisherIPAddress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteDistinguisherIPAddress) ProtoMessage() {} + +func (x *RouteDistinguisherIPAddress) ProtoReflect() protoreflect.Message { + mi := &file_attribute_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 RouteDistinguisherIPAddress.ProtoReflect.Descriptor instead. +func (*RouteDistinguisherIPAddress) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{15} +} + +func (x *RouteDistinguisherIPAddress) GetAdmin() string { + if x != nil { + return x.Admin + } + return "" +} + +func (x *RouteDistinguisherIPAddress) GetAssigned() uint32 { + if x != nil { + return x.Assigned + } + return 0 +} + +type RouteDistinguisherFourOctetASN struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Admin uint32 `protobuf:"varint,1,opt,name=admin,proto3" json:"admin,omitempty"` + Assigned uint32 `protobuf:"varint,2,opt,name=assigned,proto3" json:"assigned,omitempty"` +} + +func (x *RouteDistinguisherFourOctetASN) Reset() { + *x = RouteDistinguisherFourOctetASN{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteDistinguisherFourOctetASN) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteDistinguisherFourOctetASN) ProtoMessage() {} + +func (x *RouteDistinguisherFourOctetASN) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[16] + 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 RouteDistinguisherFourOctetASN.ProtoReflect.Descriptor instead. +func (*RouteDistinguisherFourOctetASN) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{16} +} + +func (x *RouteDistinguisherFourOctetASN) GetAdmin() uint32 { + if x != nil { + return x.Admin + } + return 0 +} + +func (x *RouteDistinguisherFourOctetASN) GetAssigned() uint32 { + if x != nil { + return x.Assigned + } + return 0 +} + +type EthernetSegmentIdentifier struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *EthernetSegmentIdentifier) Reset() { + *x = EthernetSegmentIdentifier{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EthernetSegmentIdentifier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EthernetSegmentIdentifier) ProtoMessage() {} + +func (x *EthernetSegmentIdentifier) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[17] + 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 EthernetSegmentIdentifier.ProtoReflect.Descriptor instead. +func (*EthernetSegmentIdentifier) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{17} +} + +func (x *EthernetSegmentIdentifier) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *EthernetSegmentIdentifier) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// EVPNEthernetAutoDiscoveryRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=1 +type EVPNEthernetAutoDiscoveryRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi,proto3" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag,proto3" json:"ethernet_tag,omitempty"` + Label uint32 `protobuf:"varint,4,opt,name=label,proto3" json:"label,omitempty"` +} + +func (x *EVPNEthernetAutoDiscoveryRoute) Reset() { + *x = EVPNEthernetAutoDiscoveryRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNEthernetAutoDiscoveryRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNEthernetAutoDiscoveryRoute) ProtoMessage() {} + +func (x *EVPNEthernetAutoDiscoveryRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[18] + 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 EVPNEthernetAutoDiscoveryRoute.ProtoReflect.Descriptor instead. +func (*EVPNEthernetAutoDiscoveryRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{18} +} + +func (x *EVPNEthernetAutoDiscoveryRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNEthernetAutoDiscoveryRoute) GetEsi() *EthernetSegmentIdentifier { + if x != nil { + return x.Esi + } + return nil +} + +func (x *EVPNEthernetAutoDiscoveryRoute) GetEthernetTag() uint32 { + if x != nil { + return x.EthernetTag + } + return 0 +} + +func (x *EVPNEthernetAutoDiscoveryRoute) GetLabel() uint32 { + if x != nil { + return x.Label + } + return 0 +} + +// EVPNMACIPAdvertisementRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=2 +type EVPNMACIPAdvertisementRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi,proto3" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag,proto3" json:"ethernet_tag,omitempty"` + MacAddress string `protobuf:"bytes,4,opt,name=mac_address,json=macAddress,proto3" json:"mac_address,omitempty"` + IpAddress string `protobuf:"bytes,5,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"` + Labels []uint32 `protobuf:"varint,6,rep,packed,name=labels,proto3" json:"labels,omitempty"` +} + +func (x *EVPNMACIPAdvertisementRoute) Reset() { + *x = EVPNMACIPAdvertisementRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNMACIPAdvertisementRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNMACIPAdvertisementRoute) ProtoMessage() {} + +func (x *EVPNMACIPAdvertisementRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[19] + 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 EVPNMACIPAdvertisementRoute.ProtoReflect.Descriptor instead. +func (*EVPNMACIPAdvertisementRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{19} +} + +func (x *EVPNMACIPAdvertisementRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNMACIPAdvertisementRoute) GetEsi() *EthernetSegmentIdentifier { + if x != nil { + return x.Esi + } + return nil +} + +func (x *EVPNMACIPAdvertisementRoute) GetEthernetTag() uint32 { + if x != nil { + return x.EthernetTag + } + return 0 +} + +func (x *EVPNMACIPAdvertisementRoute) GetMacAddress() string { + if x != nil { + return x.MacAddress + } + return "" +} + +func (x *EVPNMACIPAdvertisementRoute) GetIpAddress() string { + if x != nil { + return x.IpAddress + } + return "" +} + +func (x *EVPNMACIPAdvertisementRoute) GetLabels() []uint32 { + if x != nil { + return x.Labels + } + return nil +} + +// EVPNInclusiveMulticastEthernetTagRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=3 +type EVPNInclusiveMulticastEthernetTagRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + EthernetTag uint32 `protobuf:"varint,2,opt,name=ethernet_tag,json=ethernetTag,proto3" json:"ethernet_tag,omitempty"` + IpAddress string `protobuf:"bytes,3,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"` +} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) Reset() { + *x = EVPNInclusiveMulticastEthernetTagRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNInclusiveMulticastEthernetTagRoute) ProtoMessage() {} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[20] + 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 EVPNInclusiveMulticastEthernetTagRoute.ProtoReflect.Descriptor instead. +func (*EVPNInclusiveMulticastEthernetTagRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{20} +} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) GetEthernetTag() uint32 { + if x != nil { + return x.EthernetTag + } + return 0 +} + +func (x *EVPNInclusiveMulticastEthernetTagRoute) GetIpAddress() string { + if x != nil { + return x.IpAddress + } + return "" +} + +// EVPNEthernetSegmentRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=4 +type EVPNEthernetSegmentRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi,proto3" json:"esi,omitempty"` + IpAddress string `protobuf:"bytes,3,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"` +} + +func (x *EVPNEthernetSegmentRoute) Reset() { + *x = EVPNEthernetSegmentRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNEthernetSegmentRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNEthernetSegmentRoute) ProtoMessage() {} + +func (x *EVPNEthernetSegmentRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[21] + 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 EVPNEthernetSegmentRoute.ProtoReflect.Descriptor instead. +func (*EVPNEthernetSegmentRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{21} +} + +func (x *EVPNEthernetSegmentRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNEthernetSegmentRoute) GetEsi() *EthernetSegmentIdentifier { + if x != nil { + return x.Esi + } + return nil +} + +func (x *EVPNEthernetSegmentRoute) GetIpAddress() string { + if x != nil { + return x.IpAddress + } + return "" +} + +// EVPNIPPrefixRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=5 +type EVPNIPPrefixRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Esi *EthernetSegmentIdentifier `protobuf:"bytes,2,opt,name=esi,proto3" json:"esi,omitempty"` + EthernetTag uint32 `protobuf:"varint,3,opt,name=ethernet_tag,json=ethernetTag,proto3" json:"ethernet_tag,omitempty"` + IpPrefix string `protobuf:"bytes,4,opt,name=ip_prefix,json=ipPrefix,proto3" json:"ip_prefix,omitempty"` + IpPrefixLen uint32 `protobuf:"varint,5,opt,name=ip_prefix_len,json=ipPrefixLen,proto3" json:"ip_prefix_len,omitempty"` + GwAddress string `protobuf:"bytes,6,opt,name=gw_address,json=gwAddress,proto3" json:"gw_address,omitempty"` + Label uint32 `protobuf:"varint,7,opt,name=label,proto3" json:"label,omitempty"` +} + +func (x *EVPNIPPrefixRoute) Reset() { + *x = EVPNIPPrefixRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNIPPrefixRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNIPPrefixRoute) ProtoMessage() {} + +func (x *EVPNIPPrefixRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[22] + 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 EVPNIPPrefixRoute.ProtoReflect.Descriptor instead. +func (*EVPNIPPrefixRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{22} +} + +func (x *EVPNIPPrefixRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNIPPrefixRoute) GetEsi() *EthernetSegmentIdentifier { + if x != nil { + return x.Esi + } + return nil +} + +func (x *EVPNIPPrefixRoute) GetEthernetTag() uint32 { + if x != nil { + return x.EthernetTag + } + return 0 +} + +func (x *EVPNIPPrefixRoute) GetIpPrefix() string { + if x != nil { + return x.IpPrefix + } + return "" +} + +func (x *EVPNIPPrefixRoute) GetIpPrefixLen() uint32 { + if x != nil { + return x.IpPrefixLen + } + return 0 +} + +func (x *EVPNIPPrefixRoute) GetGwAddress() string { + if x != nil { + return x.GwAddress + } + return "" +} + +func (x *EVPNIPPrefixRoute) GetLabel() uint32 { + if x != nil { + return x.Label + } + return 0 +} + +// EVPNIPMSIRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=9 +type EVPNIPMSIRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + EthernetTag uint32 `protobuf:"varint,2,opt,name=ethernet_tag,json=ethernetTag,proto3" json:"ethernet_tag,omitempty"` + Rt *anypb.Any `protobuf:"bytes,3,opt,name=rt,proto3" json:"rt,omitempty"` +} + +func (x *EVPNIPMSIRoute) Reset() { + *x = EVPNIPMSIRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EVPNIPMSIRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EVPNIPMSIRoute) ProtoMessage() {} + +func (x *EVPNIPMSIRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[23] + 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 EVPNIPMSIRoute.ProtoReflect.Descriptor instead. +func (*EVPNIPMSIRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{23} +} + +func (x *EVPNIPMSIRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *EVPNIPMSIRoute) GetEthernetTag() uint32 { + if x != nil { + return x.EthernetTag + } + return 0 +} + +func (x *EVPNIPMSIRoute) GetRt() *anypb.Any { + if x != nil { + return x.Rt + } + return nil +} + +// SRPolicyNLRI represents the NLRI for: +// - AFI=1, SAFI=73 +// - AFI=2, SAFI=73 +type SRPolicyNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // length field carries the length of NLRI portion expressed in bits + Length uint32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"` + // distinguisher field carries 4-octet value uniquely identifying the policy + // in the context of tuple. + Distinguisher uint32 `protobuf:"varint,2,opt,name=distinguisher,proto3" json:"distinguisher,omitempty"` + // color field carries 4-octet value identifying (with the endpoint) the + // policy. The color is used to match the color of the destination + // prefixes to steer traffic into the SR Policy + Color uint32 `protobuf:"varint,3,opt,name=color,proto3" json:"color,omitempty"` + // endpoint field identifies the endpoint of a policy. The Endpoint may + // represent a single node or a set of nodes (e.g., an anycast + // address). The Endpoint is an IPv4 (4-octet) address or an IPv6 + // (16-octet) address according to the AFI of the NLRI. + Endpoint []byte `protobuf:"bytes,4,opt,name=endpoint,proto3" json:"endpoint,omitempty"` +} + +func (x *SRPolicyNLRI) Reset() { + *x = SRPolicyNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRPolicyNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRPolicyNLRI) ProtoMessage() {} + +func (x *SRPolicyNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[24] + 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 SRPolicyNLRI.ProtoReflect.Descriptor instead. +func (*SRPolicyNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{24} +} + +func (x *SRPolicyNLRI) GetLength() uint32 { + if x != nil { + return x.Length + } + return 0 +} + +func (x *SRPolicyNLRI) GetDistinguisher() uint32 { + if x != nil { + return x.Distinguisher + } + return 0 +} + +func (x *SRPolicyNLRI) GetColor() uint32 { + if x != nil { + return x.Color + } + return 0 +} + +func (x *SRPolicyNLRI) GetEndpoint() []byte { + if x != nil { + return x.Endpoint + } + return nil +} + +// LabeledVPNIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=128 +// - AFI=2, SAFI=128 +type LabeledVPNIPAddressPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Labels []uint32 `protobuf:"varint,1,rep,packed,name=labels,proto3" json:"labels,omitempty"` + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + Rd *anypb.Any `protobuf:"bytes,2,opt,name=rd,proto3" json:"rd,omitempty"` + PrefixLen uint32 `protobuf:"varint,3,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *LabeledVPNIPAddressPrefix) Reset() { + *x = LabeledVPNIPAddressPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LabeledVPNIPAddressPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LabeledVPNIPAddressPrefix) ProtoMessage() {} + +func (x *LabeledVPNIPAddressPrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[25] + 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 LabeledVPNIPAddressPrefix.ProtoReflect.Descriptor instead. +func (*LabeledVPNIPAddressPrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{25} +} + +func (x *LabeledVPNIPAddressPrefix) GetLabels() []uint32 { + if x != nil { + return x.Labels + } + return nil +} + +func (x *LabeledVPNIPAddressPrefix) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *LabeledVPNIPAddressPrefix) GetPrefixLen() uint32 { + if x != nil { + return x.PrefixLen + } + return 0 +} + +func (x *LabeledVPNIPAddressPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +// RouteTargetMembershipNLRI represents the NLRI for: +// - AFI=1, SAFI=132 +type RouteTargetMembershipNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + Rt *anypb.Any `protobuf:"bytes,2,opt,name=rt,proto3" json:"rt,omitempty"` +} + +func (x *RouteTargetMembershipNLRI) Reset() { + *x = RouteTargetMembershipNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteTargetMembershipNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteTargetMembershipNLRI) ProtoMessage() {} + +func (x *RouteTargetMembershipNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[26] + 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 RouteTargetMembershipNLRI.ProtoReflect.Descriptor instead. +func (*RouteTargetMembershipNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{26} +} + +func (x *RouteTargetMembershipNLRI) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *RouteTargetMembershipNLRI) GetRt() *anypb.Any { + if x != nil { + return x.Rt + } + return nil +} + +type FlowSpecIPPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + PrefixLen uint32 `protobuf:"varint,2,opt,name=prefix_len,json=prefixLen,proto3" json:"prefix_len,omitempty"` + Prefix string `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix,omitempty"` + // IPv6 only + Offset uint32 `protobuf:"varint,4,opt,name=offset,proto3" json:"offset,omitempty"` +} + +func (x *FlowSpecIPPrefix) Reset() { + *x = FlowSpecIPPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlowSpecIPPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlowSpecIPPrefix) ProtoMessage() {} + +func (x *FlowSpecIPPrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[27] + 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 FlowSpecIPPrefix.ProtoReflect.Descriptor instead. +func (*FlowSpecIPPrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{27} +} + +func (x *FlowSpecIPPrefix) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *FlowSpecIPPrefix) GetPrefixLen() uint32 { + if x != nil { + return x.PrefixLen + } + return 0 +} + +func (x *FlowSpecIPPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *FlowSpecIPPrefix) GetOffset() uint32 { + if x != nil { + return x.Offset + } + return 0 +} + +type FlowSpecMAC struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *FlowSpecMAC) Reset() { + *x = FlowSpecMAC{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlowSpecMAC) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlowSpecMAC) ProtoMessage() {} + +func (x *FlowSpecMAC) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[28] + 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 FlowSpecMAC.ProtoReflect.Descriptor instead. +func (*FlowSpecMAC) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{28} +} + +func (x *FlowSpecMAC) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *FlowSpecMAC) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type FlowSpecComponentItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Operator for Numeric type, Operand for Bitmask type + Op uint32 `protobuf:"varint,1,opt,name=op,proto3" json:"op,omitempty"` + Value uint64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *FlowSpecComponentItem) Reset() { + *x = FlowSpecComponentItem{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlowSpecComponentItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlowSpecComponentItem) ProtoMessage() {} + +func (x *FlowSpecComponentItem) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[29] + 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 FlowSpecComponentItem.ProtoReflect.Descriptor instead. +func (*FlowSpecComponentItem) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{29} +} + +func (x *FlowSpecComponentItem) GetOp() uint32 { + if x != nil { + return x.Op + } + return 0 +} + +func (x *FlowSpecComponentItem) GetValue() uint64 { + if x != nil { + return x.Value + } + return 0 +} + +type FlowSpecComponent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Items []*FlowSpecComponentItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *FlowSpecComponent) Reset() { + *x = FlowSpecComponent{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlowSpecComponent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlowSpecComponent) ProtoMessage() {} + +func (x *FlowSpecComponent) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[30] + 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 FlowSpecComponent.ProtoReflect.Descriptor instead. +func (*FlowSpecComponent) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{30} +} + +func (x *FlowSpecComponent) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *FlowSpecComponent) GetItems() []*FlowSpecComponentItem { + if x != nil { + return x.Items + } + return nil +} + +// FlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=133 +// - AFI=2, SAFI=133 +type FlowSpecNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + Rules []*anypb.Any `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` +} + +func (x *FlowSpecNLRI) Reset() { + *x = FlowSpecNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FlowSpecNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FlowSpecNLRI) ProtoMessage() {} + +func (x *FlowSpecNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[31] + 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 FlowSpecNLRI.ProtoReflect.Descriptor instead. +func (*FlowSpecNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{31} +} + +func (x *FlowSpecNLRI) GetRules() []*anypb.Any { + if x != nil { + return x.Rules + } + return nil +} + +// VPNFlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=134 +// - AFI=2, SAFI=134 +// - AFI=25, SAFI=134 +type VPNFlowSpecNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + Rules []*anypb.Any `protobuf:"bytes,2,rep,name=rules,proto3" json:"rules,omitempty"` +} + +func (x *VPNFlowSpecNLRI) Reset() { + *x = VPNFlowSpecNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VPNFlowSpecNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VPNFlowSpecNLRI) ProtoMessage() {} + +func (x *VPNFlowSpecNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[32] + 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 VPNFlowSpecNLRI.ProtoReflect.Descriptor instead. +func (*VPNFlowSpecNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{32} +} + +func (x *VPNFlowSpecNLRI) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *VPNFlowSpecNLRI) GetRules() []*anypb.Any { + if x != nil { + return x.Rules + } + return nil +} + +// OpaqueNLRI represents the NLRI for: +// - AFI=16397, SAFI=241 +type OpaqueNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *OpaqueNLRI) Reset() { + *x = OpaqueNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OpaqueNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OpaqueNLRI) ProtoMessage() {} + +func (x *OpaqueNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[33] + 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 OpaqueNLRI.ProtoReflect.Descriptor instead. +func (*OpaqueNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{33} +} + +func (x *OpaqueNLRI) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +func (x *OpaqueNLRI) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type LsNodeDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + BgpLsId uint32 `protobuf:"varint,2,opt,name=bgp_ls_id,json=bgpLsId,proto3" json:"bgp_ls_id,omitempty"` + OspfAreaId uint32 `protobuf:"varint,3,opt,name=ospf_area_id,json=ospfAreaId,proto3" json:"ospf_area_id,omitempty"` + Pseudonode bool `protobuf:"varint,4,opt,name=pseudonode,proto3" json:"pseudonode,omitempty"` + IgpRouterId string `protobuf:"bytes,5,opt,name=igp_router_id,json=igpRouterId,proto3" json:"igp_router_id,omitempty"` +} + +func (x *LsNodeDescriptor) Reset() { + *x = LsNodeDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsNodeDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsNodeDescriptor) ProtoMessage() {} + +func (x *LsNodeDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[34] + 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 LsNodeDescriptor.ProtoReflect.Descriptor instead. +func (*LsNodeDescriptor) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{34} +} + +func (x *LsNodeDescriptor) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *LsNodeDescriptor) GetBgpLsId() uint32 { + if x != nil { + return x.BgpLsId + } + return 0 +} + +func (x *LsNodeDescriptor) GetOspfAreaId() uint32 { + if x != nil { + return x.OspfAreaId + } + return 0 +} + +func (x *LsNodeDescriptor) GetPseudonode() bool { + if x != nil { + return x.Pseudonode + } + return false +} + +func (x *LsNodeDescriptor) GetIgpRouterId() string { + if x != nil { + return x.IgpRouterId + } + return "" +} + +type LsLinkDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LinkLocalId uint32 `protobuf:"varint,1,opt,name=link_local_id,json=linkLocalId,proto3" json:"link_local_id,omitempty"` + LinkRemoteId uint32 `protobuf:"varint,2,opt,name=link_remote_id,json=linkRemoteId,proto3" json:"link_remote_id,omitempty"` + InterfaceAddrIpv4 string `protobuf:"bytes,3,opt,name=interface_addr_ipv4,json=interfaceAddrIpv4,proto3" json:"interface_addr_ipv4,omitempty"` + NeighborAddrIpv4 string `protobuf:"bytes,4,opt,name=neighbor_addr_ipv4,json=neighborAddrIpv4,proto3" json:"neighbor_addr_ipv4,omitempty"` + InterfaceAddrIpv6 string `protobuf:"bytes,5,opt,name=interface_addr_ipv6,json=interfaceAddrIpv6,proto3" json:"interface_addr_ipv6,omitempty"` + NeighborAddrIpv6 string `protobuf:"bytes,6,opt,name=neighbor_addr_ipv6,json=neighborAddrIpv6,proto3" json:"neighbor_addr_ipv6,omitempty"` +} + +func (x *LsLinkDescriptor) Reset() { + *x = LsLinkDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsLinkDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsLinkDescriptor) ProtoMessage() {} + +func (x *LsLinkDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[35] + 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 LsLinkDescriptor.ProtoReflect.Descriptor instead. +func (*LsLinkDescriptor) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{35} +} + +func (x *LsLinkDescriptor) GetLinkLocalId() uint32 { + if x != nil { + return x.LinkLocalId + } + return 0 +} + +func (x *LsLinkDescriptor) GetLinkRemoteId() uint32 { + if x != nil { + return x.LinkRemoteId + } + return 0 +} + +func (x *LsLinkDescriptor) GetInterfaceAddrIpv4() string { + if x != nil { + return x.InterfaceAddrIpv4 + } + return "" +} + +func (x *LsLinkDescriptor) GetNeighborAddrIpv4() string { + if x != nil { + return x.NeighborAddrIpv4 + } + return "" +} + +func (x *LsLinkDescriptor) GetInterfaceAddrIpv6() string { + if x != nil { + return x.InterfaceAddrIpv6 + } + return "" +} + +func (x *LsLinkDescriptor) GetNeighborAddrIpv6() string { + if x != nil { + return x.NeighborAddrIpv6 + } + return "" +} + +type LsPrefixDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IpReachability []string `protobuf:"bytes,1,rep,name=ip_reachability,json=ipReachability,proto3" json:"ip_reachability,omitempty"` + OspfRouteType LsOspfRouteType `protobuf:"varint,2,opt,name=ospf_route_type,json=ospfRouteType,proto3,enum=apipb.LsOspfRouteType" json:"ospf_route_type,omitempty"` +} + +func (x *LsPrefixDescriptor) Reset() { + *x = LsPrefixDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsPrefixDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsPrefixDescriptor) ProtoMessage() {} + +func (x *LsPrefixDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[36] + 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 LsPrefixDescriptor.ProtoReflect.Descriptor instead. +func (*LsPrefixDescriptor) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{36} +} + +func (x *LsPrefixDescriptor) GetIpReachability() []string { + if x != nil { + return x.IpReachability + } + return nil +} + +func (x *LsPrefixDescriptor) GetOspfRouteType() LsOspfRouteType { + if x != nil { + return x.OspfRouteType + } + return LsOspfRouteType_LS_OSPF_ROUTE_TYPE_UNKNOWN +} + +type LsNodeNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode,proto3" json:"local_node,omitempty"` +} + +func (x *LsNodeNLRI) Reset() { + *x = LsNodeNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsNodeNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsNodeNLRI) ProtoMessage() {} + +func (x *LsNodeNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[37] + 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 LsNodeNLRI.ProtoReflect.Descriptor instead. +func (*LsNodeNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{37} +} + +func (x *LsNodeNLRI) GetLocalNode() *LsNodeDescriptor { + if x != nil { + return x.LocalNode + } + return nil +} + +type LsLinkNLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode,proto3" json:"local_node,omitempty"` + RemoteNode *LsNodeDescriptor `protobuf:"bytes,2,opt,name=remote_node,json=remoteNode,proto3" json:"remote_node,omitempty"` + LinkDescriptor *LsLinkDescriptor `protobuf:"bytes,3,opt,name=link_descriptor,json=linkDescriptor,proto3" json:"link_descriptor,omitempty"` +} + +func (x *LsLinkNLRI) Reset() { + *x = LsLinkNLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsLinkNLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsLinkNLRI) ProtoMessage() {} + +func (x *LsLinkNLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[38] + 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 LsLinkNLRI.ProtoReflect.Descriptor instead. +func (*LsLinkNLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{38} +} + +func (x *LsLinkNLRI) GetLocalNode() *LsNodeDescriptor { + if x != nil { + return x.LocalNode + } + return nil +} + +func (x *LsLinkNLRI) GetRemoteNode() *LsNodeDescriptor { + if x != nil { + return x.RemoteNode + } + return nil +} + +func (x *LsLinkNLRI) GetLinkDescriptor() *LsLinkDescriptor { + if x != nil { + return x.LinkDescriptor + } + return nil +} + +type LsPrefixV4NLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode,proto3" json:"local_node,omitempty"` + PrefixDescriptor *LsPrefixDescriptor `protobuf:"bytes,2,opt,name=prefix_descriptor,json=prefixDescriptor,proto3" json:"prefix_descriptor,omitempty"` +} + +func (x *LsPrefixV4NLRI) Reset() { + *x = LsPrefixV4NLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsPrefixV4NLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsPrefixV4NLRI) ProtoMessage() {} + +func (x *LsPrefixV4NLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[39] + 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 LsPrefixV4NLRI.ProtoReflect.Descriptor instead. +func (*LsPrefixV4NLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{39} +} + +func (x *LsPrefixV4NLRI) GetLocalNode() *LsNodeDescriptor { + if x != nil { + return x.LocalNode + } + return nil +} + +func (x *LsPrefixV4NLRI) GetPrefixDescriptor() *LsPrefixDescriptor { + if x != nil { + return x.PrefixDescriptor + } + return nil +} + +type LsPrefixV6NLRI struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalNode *LsNodeDescriptor `protobuf:"bytes,1,opt,name=local_node,json=localNode,proto3" json:"local_node,omitempty"` + PrefixDescriptor *LsPrefixDescriptor `protobuf:"bytes,2,opt,name=prefix_descriptor,json=prefixDescriptor,proto3" json:"prefix_descriptor,omitempty"` +} + +func (x *LsPrefixV6NLRI) Reset() { + *x = LsPrefixV6NLRI{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsPrefixV6NLRI) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsPrefixV6NLRI) ProtoMessage() {} + +func (x *LsPrefixV6NLRI) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[40] + 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 LsPrefixV6NLRI.ProtoReflect.Descriptor instead. +func (*LsPrefixV6NLRI) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{40} +} + +func (x *LsPrefixV6NLRI) GetLocalNode() *LsNodeDescriptor { + if x != nil { + return x.LocalNode + } + return nil +} + +func (x *LsPrefixV6NLRI) GetPrefixDescriptor() *LsPrefixDescriptor { + if x != nil { + return x.PrefixDescriptor + } + return nil +} + +// LsAddrPrefix represents the NLRI for: +// - AFI=16388, SAFI=71 +type LsAddrPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type LsNLRIType `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.LsNLRIType" json:"type,omitempty"` + // One of: + // - LsNodeNLRI + // - LsLinkNLRI + // - LsPrefixV4NLRI + // - LsPrefixV6NLRI + Nlri *anypb.Any `protobuf:"bytes,2,opt,name=nlri,proto3" json:"nlri,omitempty"` + Length uint32 `protobuf:"varint,3,opt,name=length,proto3" json:"length,omitempty"` + ProtocolId LsProtocolID `protobuf:"varint,4,opt,name=protocol_id,json=protocolId,proto3,enum=apipb.LsProtocolID" json:"protocol_id,omitempty"` + Identifier uint64 `protobuf:"varint,5,opt,name=identifier,proto3" json:"identifier,omitempty"` +} + +func (x *LsAddrPrefix) Reset() { + *x = LsAddrPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsAddrPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsAddrPrefix) ProtoMessage() {} + +func (x *LsAddrPrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[41] + 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 LsAddrPrefix.ProtoReflect.Descriptor instead. +func (*LsAddrPrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{41} +} + +func (x *LsAddrPrefix) GetType() LsNLRIType { + if x != nil { + return x.Type + } + return LsNLRIType_LS_NLRI_UNKNOWN +} + +func (x *LsAddrPrefix) GetNlri() *anypb.Any { + if x != nil { + return x.Nlri + } + return nil +} + +func (x *LsAddrPrefix) GetLength() uint32 { + if x != nil { + return x.Length + } + return 0 +} + +func (x *LsAddrPrefix) GetProtocolId() LsProtocolID { + if x != nil { + return x.ProtocolId + } + return LsProtocolID_LS_PROTOCOL_UNKNOWN +} + +func (x *LsAddrPrefix) GetIdentifier() uint64 { + if x != nil { + return x.Identifier + } + return 0 +} + +type MUPInterworkSegmentDiscoveryRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Prefix string `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *MUPInterworkSegmentDiscoveryRoute) Reset() { + *x = MUPInterworkSegmentDiscoveryRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MUPInterworkSegmentDiscoveryRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MUPInterworkSegmentDiscoveryRoute) ProtoMessage() {} + +func (x *MUPInterworkSegmentDiscoveryRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[42] + 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 MUPInterworkSegmentDiscoveryRoute.ProtoReflect.Descriptor instead. +func (*MUPInterworkSegmentDiscoveryRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{42} +} + +func (x *MUPInterworkSegmentDiscoveryRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *MUPInterworkSegmentDiscoveryRoute) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +type MUPDirectSegmentDiscoveryRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *MUPDirectSegmentDiscoveryRoute) Reset() { + *x = MUPDirectSegmentDiscoveryRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MUPDirectSegmentDiscoveryRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MUPDirectSegmentDiscoveryRoute) ProtoMessage() {} + +func (x *MUPDirectSegmentDiscoveryRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[43] + 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 MUPDirectSegmentDiscoveryRoute.ProtoReflect.Descriptor instead. +func (*MUPDirectSegmentDiscoveryRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{43} +} + +func (x *MUPDirectSegmentDiscoveryRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *MUPDirectSegmentDiscoveryRoute) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type MUPType1SessionTransformedRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + // Deprecated: Do not use. + PrefixLength uint32 `protobuf:"varint,2,opt,name=prefix_length,json=prefixLength,proto3" json:"prefix_length,omitempty"` + Prefix string `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix,omitempty"` + Teid uint32 `protobuf:"varint,4,opt,name=teid,proto3" json:"teid,omitempty"` + Qfi uint32 `protobuf:"varint,5,opt,name=qfi,proto3" json:"qfi,omitempty"` + EndpointAddressLength uint32 `protobuf:"varint,6,opt,name=endpoint_address_length,json=endpointAddressLength,proto3" json:"endpoint_address_length,omitempty"` + EndpointAddress string `protobuf:"bytes,7,opt,name=endpoint_address,json=endpointAddress,proto3" json:"endpoint_address,omitempty"` +} + +func (x *MUPType1SessionTransformedRoute) Reset() { + *x = MUPType1SessionTransformedRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MUPType1SessionTransformedRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MUPType1SessionTransformedRoute) ProtoMessage() {} + +func (x *MUPType1SessionTransformedRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[44] + 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 MUPType1SessionTransformedRoute.ProtoReflect.Descriptor instead. +func (*MUPType1SessionTransformedRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{44} +} + +func (x *MUPType1SessionTransformedRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +// Deprecated: Do not use. +func (x *MUPType1SessionTransformedRoute) GetPrefixLength() uint32 { + if x != nil { + return x.PrefixLength + } + return 0 +} + +func (x *MUPType1SessionTransformedRoute) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *MUPType1SessionTransformedRoute) GetTeid() uint32 { + if x != nil { + return x.Teid + } + return 0 +} + +func (x *MUPType1SessionTransformedRoute) GetQfi() uint32 { + if x != nil { + return x.Qfi + } + return 0 +} + +func (x *MUPType1SessionTransformedRoute) GetEndpointAddressLength() uint32 { + if x != nil { + return x.EndpointAddressLength + } + return 0 +} + +func (x *MUPType1SessionTransformedRoute) GetEndpointAddress() string { + if x != nil { + return x.EndpointAddress + } + return "" +} + +type MUPType2SessionTransformedRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + Rd *anypb.Any `protobuf:"bytes,1,opt,name=rd,proto3" json:"rd,omitempty"` + EndpointAddressLength uint32 `protobuf:"varint,2,opt,name=endpoint_address_length,json=endpointAddressLength,proto3" json:"endpoint_address_length,omitempty"` + EndpointAddress string `protobuf:"bytes,3,opt,name=endpoint_address,json=endpointAddress,proto3" json:"endpoint_address,omitempty"` + Teid uint32 `protobuf:"varint,4,opt,name=teid,proto3" json:"teid,omitempty"` +} + +func (x *MUPType2SessionTransformedRoute) Reset() { + *x = MUPType2SessionTransformedRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MUPType2SessionTransformedRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MUPType2SessionTransformedRoute) ProtoMessage() {} + +func (x *MUPType2SessionTransformedRoute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[45] + 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 MUPType2SessionTransformedRoute.ProtoReflect.Descriptor instead. +func (*MUPType2SessionTransformedRoute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{45} +} + +func (x *MUPType2SessionTransformedRoute) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *MUPType2SessionTransformedRoute) GetEndpointAddressLength() uint32 { + if x != nil { + return x.EndpointAddressLength + } + return 0 +} + +func (x *MUPType2SessionTransformedRoute) GetEndpointAddress() string { + if x != nil { + return x.EndpointAddress + } + return "" +} + +func (x *MUPType2SessionTransformedRoute) GetTeid() uint32 { + if x != nil { + return x.Teid + } + return 0 +} + +type MpReachNLRIAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + NextHops []string `protobuf:"bytes,2,rep,name=next_hops,json=nextHops,proto3" json:"next_hops,omitempty"` + // Each NLRI must be one of: + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - EVPNIPMSIRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + // - LsAddrPrefix + // - SR Policy NLRI + // - MUPInterworkSegmentDiscoveryRoute + // - MUPDirectSegmentDiscoveryRoute + // - MUPType1SessionTransformedRoute + // - MUPType2SessionTransformedRoute + Nlris []*anypb.Any `protobuf:"bytes,3,rep,name=nlris,proto3" json:"nlris,omitempty"` +} + +func (x *MpReachNLRIAttribute) Reset() { + *x = MpReachNLRIAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MpReachNLRIAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MpReachNLRIAttribute) ProtoMessage() {} + +func (x *MpReachNLRIAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[46] + 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 MpReachNLRIAttribute.ProtoReflect.Descriptor instead. +func (*MpReachNLRIAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{46} +} + +func (x *MpReachNLRIAttribute) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *MpReachNLRIAttribute) GetNextHops() []string { + if x != nil { + return x.NextHops + } + return nil +} + +func (x *MpReachNLRIAttribute) GetNlris() []*anypb.Any { + if x != nil { + return x.Nlris + } + return nil +} + +type MpUnreachNLRIAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + // The same as NLRI field of MpReachNLRIAttribute + Nlris []*anypb.Any `protobuf:"bytes,3,rep,name=nlris,proto3" json:"nlris,omitempty"` +} + +func (x *MpUnreachNLRIAttribute) Reset() { + *x = MpUnreachNLRIAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MpUnreachNLRIAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MpUnreachNLRIAttribute) ProtoMessage() {} + +func (x *MpUnreachNLRIAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[47] + 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 MpUnreachNLRIAttribute.ProtoReflect.Descriptor instead. +func (*MpUnreachNLRIAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{47} +} + +func (x *MpUnreachNLRIAttribute) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *MpUnreachNLRIAttribute) GetNlris() []*anypb.Any { + if x != nil { + return x.Nlris + } + return nil +} + +type TwoOctetAsSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive,proto3" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType,proto3" json:"sub_type,omitempty"` + Asn uint32 `protobuf:"varint,3,opt,name=asn,proto3" json:"asn,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *TwoOctetAsSpecificExtended) Reset() { + *x = TwoOctetAsSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TwoOctetAsSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TwoOctetAsSpecificExtended) ProtoMessage() {} + +func (x *TwoOctetAsSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[48] + 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 TwoOctetAsSpecificExtended.ProtoReflect.Descriptor instead. +func (*TwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{48} +} + +func (x *TwoOctetAsSpecificExtended) GetIsTransitive() bool { + if x != nil { + return x.IsTransitive + } + return false +} + +func (x *TwoOctetAsSpecificExtended) GetSubType() uint32 { + if x != nil { + return x.SubType + } + return 0 +} + +func (x *TwoOctetAsSpecificExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *TwoOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type IPv4AddressSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive,proto3" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType,proto3" json:"sub_type,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *IPv4AddressSpecificExtended) Reset() { + *x = IPv4AddressSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IPv4AddressSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IPv4AddressSpecificExtended) ProtoMessage() {} + +func (x *IPv4AddressSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[49] + 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 IPv4AddressSpecificExtended.ProtoReflect.Descriptor instead. +func (*IPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{49} +} + +func (x *IPv4AddressSpecificExtended) GetIsTransitive() bool { + if x != nil { + return x.IsTransitive + } + return false +} + +func (x *IPv4AddressSpecificExtended) GetSubType() uint32 { + if x != nil { + return x.SubType + } + return 0 +} + +func (x *IPv4AddressSpecificExtended) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *IPv4AddressSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type FourOctetAsSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive,proto3" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType,proto3" json:"sub_type,omitempty"` + Asn uint32 `protobuf:"varint,3,opt,name=asn,proto3" json:"asn,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *FourOctetAsSpecificExtended) Reset() { + *x = FourOctetAsSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FourOctetAsSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FourOctetAsSpecificExtended) ProtoMessage() {} + +func (x *FourOctetAsSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[50] + 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 FourOctetAsSpecificExtended.ProtoReflect.Descriptor instead. +func (*FourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{50} +} + +func (x *FourOctetAsSpecificExtended) GetIsTransitive() bool { + if x != nil { + return x.IsTransitive + } + return false +} + +func (x *FourOctetAsSpecificExtended) GetSubType() uint32 { + if x != nil { + return x.SubType + } + return 0 +} + +func (x *FourOctetAsSpecificExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *FourOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type LinkBandwidthExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + Bandwidth float32 `protobuf:"fixed32,2,opt,name=bandwidth,proto3" json:"bandwidth,omitempty"` +} + +func (x *LinkBandwidthExtended) Reset() { + *x = LinkBandwidthExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LinkBandwidthExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LinkBandwidthExtended) ProtoMessage() {} + +func (x *LinkBandwidthExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[51] + 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 LinkBandwidthExtended.ProtoReflect.Descriptor instead. +func (*LinkBandwidthExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{51} +} + +func (x *LinkBandwidthExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *LinkBandwidthExtended) GetBandwidth() float32 { + if x != nil { + return x.Bandwidth + } + return 0 +} + +type ValidationExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + State uint32 `protobuf:"varint,1,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *ValidationExtended) Reset() { + *x = ValidationExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ValidationExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidationExtended) ProtoMessage() {} + +func (x *ValidationExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[52] + 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 ValidationExtended.ProtoReflect.Descriptor instead. +func (*ValidationExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{52} +} + +func (x *ValidationExtended) GetState() uint32 { + if x != nil { + return x.State + } + return 0 +} + +type ColorExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Color uint32 `protobuf:"varint,1,opt,name=color,proto3" json:"color,omitempty"` +} + +func (x *ColorExtended) Reset() { + *x = ColorExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ColorExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ColorExtended) ProtoMessage() {} + +func (x *ColorExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[53] + 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 ColorExtended.ProtoReflect.Descriptor instead. +func (*ColorExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{53} +} + +func (x *ColorExtended) GetColor() uint32 { + if x != nil { + return x.Color + } + return 0 +} + +type EncapExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TunnelType uint32 `protobuf:"varint,1,opt,name=tunnel_type,json=tunnelType,proto3" json:"tunnel_type,omitempty"` +} + +func (x *EncapExtended) Reset() { + *x = EncapExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EncapExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EncapExtended) ProtoMessage() {} + +func (x *EncapExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[54] + 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 EncapExtended.ProtoReflect.Descriptor instead. +func (*EncapExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{54} +} + +func (x *EncapExtended) GetTunnelType() uint32 { + if x != nil { + return x.TunnelType + } + return 0 +} + +type DefaultGatewayExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DefaultGatewayExtended) Reset() { + *x = DefaultGatewayExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DefaultGatewayExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DefaultGatewayExtended) ProtoMessage() {} + +func (x *DefaultGatewayExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[55] + 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 DefaultGatewayExtended.ProtoReflect.Descriptor instead. +func (*DefaultGatewayExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{55} +} + +type OpaqueExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive,proto3" json:"is_transitive,omitempty"` + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *OpaqueExtended) Reset() { + *x = OpaqueExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OpaqueExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OpaqueExtended) ProtoMessage() {} + +func (x *OpaqueExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[56] + 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 OpaqueExtended.ProtoReflect.Descriptor instead. +func (*OpaqueExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{56} +} + +func (x *OpaqueExtended) GetIsTransitive() bool { + if x != nil { + return x.IsTransitive + } + return false +} + +func (x *OpaqueExtended) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type ESILabelExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsSingleActive bool `protobuf:"varint,1,opt,name=is_single_active,json=isSingleActive,proto3" json:"is_single_active,omitempty"` + Label uint32 `protobuf:"varint,2,opt,name=label,proto3" json:"label,omitempty"` +} + +func (x *ESILabelExtended) Reset() { + *x = ESILabelExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ESILabelExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ESILabelExtended) ProtoMessage() {} + +func (x *ESILabelExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[57] + 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 ESILabelExtended.ProtoReflect.Descriptor instead. +func (*ESILabelExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{57} +} + +func (x *ESILabelExtended) GetIsSingleActive() bool { + if x != nil { + return x.IsSingleActive + } + return false +} + +func (x *ESILabelExtended) GetLabel() uint32 { + if x != nil { + return x.Label + } + return 0 +} + +type ESImportRouteTarget struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EsImport string `protobuf:"bytes,1,opt,name=es_import,json=esImport,proto3" json:"es_import,omitempty"` +} + +func (x *ESImportRouteTarget) Reset() { + *x = ESImportRouteTarget{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ESImportRouteTarget) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ESImportRouteTarget) ProtoMessage() {} + +func (x *ESImportRouteTarget) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[58] + 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 ESImportRouteTarget.ProtoReflect.Descriptor instead. +func (*ESImportRouteTarget) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{58} +} + +func (x *ESImportRouteTarget) GetEsImport() string { + if x != nil { + return x.EsImport + } + return "" +} + +type MacMobilityExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsSticky bool `protobuf:"varint,1,opt,name=is_sticky,json=isSticky,proto3" json:"is_sticky,omitempty"` + SequenceNum uint32 `protobuf:"varint,2,opt,name=sequence_num,json=sequenceNum,proto3" json:"sequence_num,omitempty"` +} + +func (x *MacMobilityExtended) Reset() { + *x = MacMobilityExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MacMobilityExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MacMobilityExtended) ProtoMessage() {} + +func (x *MacMobilityExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[59] + 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 MacMobilityExtended.ProtoReflect.Descriptor instead. +func (*MacMobilityExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{59} +} + +func (x *MacMobilityExtended) GetIsSticky() bool { + if x != nil { + return x.IsSticky + } + return false +} + +func (x *MacMobilityExtended) GetSequenceNum() uint32 { + if x != nil { + return x.SequenceNum + } + return 0 +} + +type RouterMacExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Mac string `protobuf:"bytes,1,opt,name=mac,proto3" json:"mac,omitempty"` +} + +func (x *RouterMacExtended) Reset() { + *x = RouterMacExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouterMacExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouterMacExtended) ProtoMessage() {} + +func (x *RouterMacExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[60] + 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 RouterMacExtended.ProtoReflect.Descriptor instead. +func (*RouterMacExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{60} +} + +func (x *RouterMacExtended) GetMac() string { + if x != nil { + return x.Mac + } + return "" +} + +type TrafficRateExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + Rate float32 `protobuf:"fixed32,2,opt,name=rate,proto3" json:"rate,omitempty"` +} + +func (x *TrafficRateExtended) Reset() { + *x = TrafficRateExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TrafficRateExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrafficRateExtended) ProtoMessage() {} + +func (x *TrafficRateExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[61] + 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 TrafficRateExtended.ProtoReflect.Descriptor instead. +func (*TrafficRateExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{61} +} + +func (x *TrafficRateExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *TrafficRateExtended) GetRate() float32 { + if x != nil { + return x.Rate + } + return 0 +} + +type TrafficActionExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Terminal bool `protobuf:"varint,1,opt,name=terminal,proto3" json:"terminal,omitempty"` + Sample bool `protobuf:"varint,2,opt,name=sample,proto3" json:"sample,omitempty"` +} + +func (x *TrafficActionExtended) Reset() { + *x = TrafficActionExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TrafficActionExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrafficActionExtended) ProtoMessage() {} + +func (x *TrafficActionExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[62] + 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 TrafficActionExtended.ProtoReflect.Descriptor instead. +func (*TrafficActionExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{62} +} + +func (x *TrafficActionExtended) GetTerminal() bool { + if x != nil { + return x.Terminal + } + return false +} + +func (x *TrafficActionExtended) GetSample() bool { + if x != nil { + return x.Sample + } + return false +} + +type RedirectTwoOctetAsSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *RedirectTwoOctetAsSpecificExtended) Reset() { + *x = RedirectTwoOctetAsSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedirectTwoOctetAsSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedirectTwoOctetAsSpecificExtended) ProtoMessage() {} + +func (x *RedirectTwoOctetAsSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[63] + 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 RedirectTwoOctetAsSpecificExtended.ProtoReflect.Descriptor instead. +func (*RedirectTwoOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{63} +} + +func (x *RedirectTwoOctetAsSpecificExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *RedirectTwoOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type RedirectIPv4AddressSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *RedirectIPv4AddressSpecificExtended) Reset() { + *x = RedirectIPv4AddressSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedirectIPv4AddressSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedirectIPv4AddressSpecificExtended) ProtoMessage() {} + +func (x *RedirectIPv4AddressSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[64] + 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 RedirectIPv4AddressSpecificExtended.ProtoReflect.Descriptor instead. +func (*RedirectIPv4AddressSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{64} +} + +func (x *RedirectIPv4AddressSpecificExtended) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *RedirectIPv4AddressSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type RedirectFourOctetAsSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *RedirectFourOctetAsSpecificExtended) Reset() { + *x = RedirectFourOctetAsSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedirectFourOctetAsSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedirectFourOctetAsSpecificExtended) ProtoMessage() {} + +func (x *RedirectFourOctetAsSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[65] + 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 RedirectFourOctetAsSpecificExtended.ProtoReflect.Descriptor instead. +func (*RedirectFourOctetAsSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{65} +} + +func (x *RedirectFourOctetAsSpecificExtended) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *RedirectFourOctetAsSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type TrafficRemarkExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Dscp uint32 `protobuf:"varint,1,opt,name=dscp,proto3" json:"dscp,omitempty"` +} + +func (x *TrafficRemarkExtended) Reset() { + *x = TrafficRemarkExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TrafficRemarkExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrafficRemarkExtended) ProtoMessage() {} + +func (x *TrafficRemarkExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[66] + 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 TrafficRemarkExtended.ProtoReflect.Descriptor instead. +func (*TrafficRemarkExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{66} +} + +func (x *TrafficRemarkExtended) GetDscp() uint32 { + if x != nil { + return x.Dscp + } + return 0 +} + +type MUPExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SubType uint32 `protobuf:"varint,1,opt,name=sub_type,json=subType,proto3" json:"sub_type,omitempty"` + SegmentId2 uint32 `protobuf:"varint,2,opt,name=segment_id2,json=segmentId2,proto3" json:"segment_id2,omitempty"` + SegmentId4 uint32 `protobuf:"varint,3,opt,name=segment_id4,json=segmentId4,proto3" json:"segment_id4,omitempty"` +} + +func (x *MUPExtended) Reset() { + *x = MUPExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MUPExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MUPExtended) ProtoMessage() {} + +func (x *MUPExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[67] + 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 MUPExtended.ProtoReflect.Descriptor instead. +func (*MUPExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{67} +} + +func (x *MUPExtended) GetSubType() uint32 { + if x != nil { + return x.SubType + } + return 0 +} + +func (x *MUPExtended) GetSegmentId2() uint32 { + if x != nil { + return x.SegmentId2 + } + return 0 +} + +func (x *MUPExtended) GetSegmentId4() uint32 { + if x != nil { + return x.SegmentId4 + } + return 0 +} + +type UnknownExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *UnknownExtended) Reset() { + *x = UnknownExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnknownExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnknownExtended) ProtoMessage() {} + +func (x *UnknownExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[68] + 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 UnknownExtended.ProtoReflect.Descriptor instead. +func (*UnknownExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{68} +} + +func (x *UnknownExtended) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *UnknownExtended) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type ExtendedCommunitiesAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Each Community must be one of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + // - OpaqueExtended + // - ESILabelExtended + // - MacMobilityExtended + // - RouterMacExtended + // - TrafficRateExtended + // - TrafficActionExtended + // - RedirectTwoOctetAsSpecificExtended + // - RedirectIPv4AddressSpecificExtended + // - RedirectFourOctetAsSpecificExtended + // - TrafficRemarkExtended + // - MUPExtended + // - UnknownExtended + Communities []*anypb.Any `protobuf:"bytes,1,rep,name=communities,proto3" json:"communities,omitempty"` +} + +func (x *ExtendedCommunitiesAttribute) Reset() { + *x = ExtendedCommunitiesAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtendedCommunitiesAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtendedCommunitiesAttribute) ProtoMessage() {} + +func (x *ExtendedCommunitiesAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[69] + 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 ExtendedCommunitiesAttribute.ProtoReflect.Descriptor instead. +func (*ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{69} +} + +func (x *ExtendedCommunitiesAttribute) GetCommunities() []*anypb.Any { + if x != nil { + return x.Communities + } + return nil +} + +type As4PathAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Segments []*AsSegment `protobuf:"bytes,1,rep,name=segments,proto3" json:"segments,omitempty"` +} + +func (x *As4PathAttribute) Reset() { + *x = As4PathAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *As4PathAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*As4PathAttribute) ProtoMessage() {} + +func (x *As4PathAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[70] + 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 As4PathAttribute.ProtoReflect.Descriptor instead. +func (*As4PathAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{70} +} + +func (x *As4PathAttribute) GetSegments() []*AsSegment { + if x != nil { + return x.Segments + } + return nil +} + +type As4AggregatorAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,2,opt,name=asn,proto3" json:"asn,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *As4AggregatorAttribute) Reset() { + *x = As4AggregatorAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *As4AggregatorAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*As4AggregatorAttribute) ProtoMessage() {} + +func (x *As4AggregatorAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[71] + 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 As4AggregatorAttribute.ProtoReflect.Descriptor instead. +func (*As4AggregatorAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{71} +} + +func (x *As4AggregatorAttribute) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *As4AggregatorAttribute) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type PmsiTunnelAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Type uint32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` + Label uint32 `protobuf:"varint,3,opt,name=label,proto3" json:"label,omitempty"` + Id []byte `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *PmsiTunnelAttribute) Reset() { + *x = PmsiTunnelAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PmsiTunnelAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PmsiTunnelAttribute) ProtoMessage() {} + +func (x *PmsiTunnelAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[72] + 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 PmsiTunnelAttribute.ProtoReflect.Descriptor instead. +func (*PmsiTunnelAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{72} +} + +func (x *PmsiTunnelAttribute) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *PmsiTunnelAttribute) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *PmsiTunnelAttribute) GetLabel() uint32 { + if x != nil { + return x.Label + } + return 0 +} + +func (x *PmsiTunnelAttribute) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +type TunnelEncapSubTLVEncapsulation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key uint32 `protobuf:"varint,1,opt,name=key,proto3" json:"key,omitempty"` + Cookie []byte `protobuf:"bytes,2,opt,name=cookie,proto3" json:"cookie,omitempty"` +} + +func (x *TunnelEncapSubTLVEncapsulation) Reset() { + *x = TunnelEncapSubTLVEncapsulation{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVEncapsulation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVEncapsulation) ProtoMessage() {} + +func (x *TunnelEncapSubTLVEncapsulation) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[73] + 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 TunnelEncapSubTLVEncapsulation.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVEncapsulation) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{73} +} + +func (x *TunnelEncapSubTLVEncapsulation) GetKey() uint32 { + if x != nil { + return x.Key + } + return 0 +} + +func (x *TunnelEncapSubTLVEncapsulation) GetCookie() []byte { + if x != nil { + return x.Cookie + } + return nil +} + +type TunnelEncapSubTLVProtocol struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Protocol uint32 `protobuf:"varint,1,opt,name=protocol,proto3" json:"protocol,omitempty"` +} + +func (x *TunnelEncapSubTLVProtocol) Reset() { + *x = TunnelEncapSubTLVProtocol{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVProtocol) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVProtocol) ProtoMessage() {} + +func (x *TunnelEncapSubTLVProtocol) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[74] + 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 TunnelEncapSubTLVProtocol.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVProtocol) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{74} +} + +func (x *TunnelEncapSubTLVProtocol) GetProtocol() uint32 { + if x != nil { + return x.Protocol + } + return 0 +} + +type TunnelEncapSubTLVColor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Color uint32 `protobuf:"varint,1,opt,name=color,proto3" json:"color,omitempty"` +} + +func (x *TunnelEncapSubTLVColor) Reset() { + *x = TunnelEncapSubTLVColor{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVColor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVColor) ProtoMessage() {} + +func (x *TunnelEncapSubTLVColor) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[75] + 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 TunnelEncapSubTLVColor.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVColor) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{75} +} + +func (x *TunnelEncapSubTLVColor) GetColor() uint32 { + if x != nil { + return x.Color + } + return 0 +} + +type TunnelEncapSubTLVSRPreference struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Preference uint32 `protobuf:"varint,2,opt,name=preference,proto3" json:"preference,omitempty"` +} + +func (x *TunnelEncapSubTLVSRPreference) Reset() { + *x = TunnelEncapSubTLVSRPreference{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[76] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRPreference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRPreference) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRPreference) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[76] + 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 TunnelEncapSubTLVSRPreference.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRPreference) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{76} +} + +func (x *TunnelEncapSubTLVSRPreference) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *TunnelEncapSubTLVSRPreference) GetPreference() uint32 { + if x != nil { + return x.Preference + } + return 0 +} + +type TunnelEncapSubTLVSRCandidatePathName struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CandidatePathName string `protobuf:"bytes,1,opt,name=candidate_path_name,json=candidatePathName,proto3" json:"candidate_path_name,omitempty"` +} + +func (x *TunnelEncapSubTLVSRCandidatePathName) Reset() { + *x = TunnelEncapSubTLVSRCandidatePathName{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRCandidatePathName) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRCandidatePathName) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRCandidatePathName) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[77] + 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 TunnelEncapSubTLVSRCandidatePathName.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRCandidatePathName) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{77} +} + +func (x *TunnelEncapSubTLVSRCandidatePathName) GetCandidatePathName() string { + if x != nil { + return x.CandidatePathName + } + return "" +} + +type TunnelEncapSubTLVSRPriority struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Priority uint32 `protobuf:"varint,1,opt,name=priority,proto3" json:"priority,omitempty"` +} + +func (x *TunnelEncapSubTLVSRPriority) Reset() { + *x = TunnelEncapSubTLVSRPriority{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[78] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRPriority) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRPriority) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRPriority) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[78] + 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 TunnelEncapSubTLVSRPriority.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRPriority) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{78} +} + +func (x *TunnelEncapSubTLVSRPriority) GetPriority() uint32 { + if x != nil { + return x.Priority + } + return 0 +} + +type TunnelEncapSubTLVSRBindingSID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // bsid must be one of: + // - SRBindingSID + // - SRv6BindingSID + Bsid *anypb.Any `protobuf:"bytes,1,opt,name=bsid,proto3" json:"bsid,omitempty"` +} + +func (x *TunnelEncapSubTLVSRBindingSID) Reset() { + *x = TunnelEncapSubTLVSRBindingSID{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[79] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRBindingSID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRBindingSID) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRBindingSID) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[79] + 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 TunnelEncapSubTLVSRBindingSID.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRBindingSID) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{79} +} + +func (x *TunnelEncapSubTLVSRBindingSID) GetBsid() *anypb.Any { + if x != nil { + return x.Bsid + } + return nil +} + +type SRBindingSID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SFlag bool `protobuf:"varint,1,opt,name=s_flag,json=sFlag,proto3" json:"s_flag,omitempty"` + IFlag bool `protobuf:"varint,2,opt,name=i_flag,json=iFlag,proto3" json:"i_flag,omitempty"` + Sid []byte `protobuf:"bytes,3,opt,name=sid,proto3" json:"sid,omitempty"` +} + +func (x *SRBindingSID) Reset() { + *x = SRBindingSID{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[80] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRBindingSID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRBindingSID) ProtoMessage() {} + +func (x *SRBindingSID) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[80] + 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 SRBindingSID.ProtoReflect.Descriptor instead. +func (*SRBindingSID) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{80} +} + +func (x *SRBindingSID) GetSFlag() bool { + if x != nil { + return x.SFlag + } + return false +} + +func (x *SRBindingSID) GetIFlag() bool { + if x != nil { + return x.IFlag + } + return false +} + +func (x *SRBindingSID) GetSid() []byte { + if x != nil { + return x.Sid + } + return nil +} + +type SRv6EndPointBehavior struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Behavior SRv6Behavior `protobuf:"varint,1,opt,name=behavior,proto3,enum=apipb.SRv6Behavior" json:"behavior,omitempty"` + BlockLen uint32 `protobuf:"varint,2,opt,name=block_len,json=blockLen,proto3" json:"block_len,omitempty"` + NodeLen uint32 `protobuf:"varint,3,opt,name=node_len,json=nodeLen,proto3" json:"node_len,omitempty"` + FuncLen uint32 `protobuf:"varint,4,opt,name=func_len,json=funcLen,proto3" json:"func_len,omitempty"` + ArgLen uint32 `protobuf:"varint,5,opt,name=arg_len,json=argLen,proto3" json:"arg_len,omitempty"` +} + +func (x *SRv6EndPointBehavior) Reset() { + *x = SRv6EndPointBehavior{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[81] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6EndPointBehavior) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6EndPointBehavior) ProtoMessage() {} + +func (x *SRv6EndPointBehavior) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[81] + 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 SRv6EndPointBehavior.ProtoReflect.Descriptor instead. +func (*SRv6EndPointBehavior) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{81} +} + +func (x *SRv6EndPointBehavior) GetBehavior() SRv6Behavior { + if x != nil { + return x.Behavior + } + return SRv6Behavior_RESERVED +} + +func (x *SRv6EndPointBehavior) GetBlockLen() uint32 { + if x != nil { + return x.BlockLen + } + return 0 +} + +func (x *SRv6EndPointBehavior) GetNodeLen() uint32 { + if x != nil { + return x.NodeLen + } + return 0 +} + +func (x *SRv6EndPointBehavior) GetFuncLen() uint32 { + if x != nil { + return x.FuncLen + } + return 0 +} + +func (x *SRv6EndPointBehavior) GetArgLen() uint32 { + if x != nil { + return x.ArgLen + } + return 0 +} + +type SRv6BindingSID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SFlag bool `protobuf:"varint,1,opt,name=s_flag,json=sFlag,proto3" json:"s_flag,omitempty"` + IFlag bool `protobuf:"varint,2,opt,name=i_flag,json=iFlag,proto3" json:"i_flag,omitempty"` + BFlag bool `protobuf:"varint,3,opt,name=b_flag,json=bFlag,proto3" json:"b_flag,omitempty"` + Sid []byte `protobuf:"bytes,4,opt,name=sid,proto3" json:"sid,omitempty"` + EndpointBehaviorStructure *SRv6EndPointBehavior `protobuf:"bytes,5,opt,name=endpoint_behavior_structure,json=endpointBehaviorStructure,proto3" json:"endpoint_behavior_structure,omitempty"` +} + +func (x *SRv6BindingSID) Reset() { + *x = SRv6BindingSID{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[82] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6BindingSID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6BindingSID) ProtoMessage() {} + +func (x *SRv6BindingSID) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[82] + 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 SRv6BindingSID.ProtoReflect.Descriptor instead. +func (*SRv6BindingSID) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{82} +} + +func (x *SRv6BindingSID) GetSFlag() bool { + if x != nil { + return x.SFlag + } + return false +} + +func (x *SRv6BindingSID) GetIFlag() bool { + if x != nil { + return x.IFlag + } + return false +} + +func (x *SRv6BindingSID) GetBFlag() bool { + if x != nil { + return x.BFlag + } + return false +} + +func (x *SRv6BindingSID) GetSid() []byte { + if x != nil { + return x.Sid + } + return nil +} + +func (x *SRv6BindingSID) GetEndpointBehaviorStructure() *SRv6EndPointBehavior { + if x != nil { + return x.EndpointBehaviorStructure + } + return nil +} + +type TunnelEncapSubTLVSRENLP struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Enlp ENLPType `protobuf:"varint,2,opt,name=enlp,proto3,enum=apipb.ENLPType" json:"enlp,omitempty"` +} + +func (x *TunnelEncapSubTLVSRENLP) Reset() { + *x = TunnelEncapSubTLVSRENLP{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[83] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRENLP) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRENLP) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRENLP) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[83] + 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 TunnelEncapSubTLVSRENLP.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRENLP) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{83} +} + +func (x *TunnelEncapSubTLVSRENLP) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *TunnelEncapSubTLVSRENLP) GetEnlp() ENLPType { + if x != nil { + return x.Enlp + } + return ENLPType_Reserved +} + +type SRWeight struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Weight uint32 `protobuf:"varint,2,opt,name=weight,proto3" json:"weight,omitempty"` +} + +func (x *SRWeight) Reset() { + *x = SRWeight{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[84] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRWeight) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRWeight) ProtoMessage() {} + +func (x *SRWeight) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[84] + 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 SRWeight.ProtoReflect.Descriptor instead. +func (*SRWeight) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{84} +} + +func (x *SRWeight) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *SRWeight) GetWeight() uint32 { + if x != nil { + return x.Weight + } + return 0 +} + +type SegmentFlags struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + VFlag bool `protobuf:"varint,1,opt,name=v_flag,json=vFlag,proto3" json:"v_flag,omitempty"` + AFlag bool `protobuf:"varint,2,opt,name=a_flag,json=aFlag,proto3" json:"a_flag,omitempty"` + SFlag bool `protobuf:"varint,3,opt,name=s_flag,json=sFlag,proto3" json:"s_flag,omitempty"` + BFlag bool `protobuf:"varint,4,opt,name=b_flag,json=bFlag,proto3" json:"b_flag,omitempty"` +} + +func (x *SegmentFlags) Reset() { + *x = SegmentFlags{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[85] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SegmentFlags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SegmentFlags) ProtoMessage() {} + +func (x *SegmentFlags) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[85] + 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 SegmentFlags.ProtoReflect.Descriptor instead. +func (*SegmentFlags) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{85} +} + +func (x *SegmentFlags) GetVFlag() bool { + if x != nil { + return x.VFlag + } + return false +} + +func (x *SegmentFlags) GetAFlag() bool { + if x != nil { + return x.AFlag + } + return false +} + +func (x *SegmentFlags) GetSFlag() bool { + if x != nil { + return x.SFlag + } + return false +} + +func (x *SegmentFlags) GetBFlag() bool { + if x != nil { + return x.BFlag + } + return false +} + +type SegmentTypeA struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags *SegmentFlags `protobuf:"bytes,1,opt,name=flags,proto3" json:"flags,omitempty"` + Label uint32 `protobuf:"varint,2,opt,name=label,proto3" json:"label,omitempty"` +} + +func (x *SegmentTypeA) Reset() { + *x = SegmentTypeA{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[86] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SegmentTypeA) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SegmentTypeA) ProtoMessage() {} + +func (x *SegmentTypeA) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[86] + 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 SegmentTypeA.ProtoReflect.Descriptor instead. +func (*SegmentTypeA) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{86} +} + +func (x *SegmentTypeA) GetFlags() *SegmentFlags { + if x != nil { + return x.Flags + } + return nil +} + +func (x *SegmentTypeA) GetLabel() uint32 { + if x != nil { + return x.Label + } + return 0 +} + +type SegmentTypeB struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags *SegmentFlags `protobuf:"bytes,1,opt,name=flags,proto3" json:"flags,omitempty"` + Sid []byte `protobuf:"bytes,2,opt,name=sid,proto3" json:"sid,omitempty"` + EndpointBehaviorStructure *SRv6EndPointBehavior `protobuf:"bytes,3,opt,name=endpoint_behavior_structure,json=endpointBehaviorStructure,proto3" json:"endpoint_behavior_structure,omitempty"` +} + +func (x *SegmentTypeB) Reset() { + *x = SegmentTypeB{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[87] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SegmentTypeB) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SegmentTypeB) ProtoMessage() {} + +func (x *SegmentTypeB) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[87] + 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 SegmentTypeB.ProtoReflect.Descriptor instead. +func (*SegmentTypeB) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{87} +} + +func (x *SegmentTypeB) GetFlags() *SegmentFlags { + if x != nil { + return x.Flags + } + return nil +} + +func (x *SegmentTypeB) GetSid() []byte { + if x != nil { + return x.Sid + } + return nil +} + +func (x *SegmentTypeB) GetEndpointBehaviorStructure() *SRv6EndPointBehavior { + if x != nil { + return x.EndpointBehaviorStructure + } + return nil +} + +type TunnelEncapSubTLVSRSegmentList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Weight *SRWeight `protobuf:"bytes,1,opt,name=weight,proto3" json:"weight,omitempty"` + // segments must be one of: + // - SegmentTypeA + // - SegmentTypeB + Segments []*anypb.Any `protobuf:"bytes,2,rep,name=segments,proto3" json:"segments,omitempty"` +} + +func (x *TunnelEncapSubTLVSRSegmentList) Reset() { + *x = TunnelEncapSubTLVSRSegmentList{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[88] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVSRSegmentList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVSRSegmentList) ProtoMessage() {} + +func (x *TunnelEncapSubTLVSRSegmentList) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[88] + 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 TunnelEncapSubTLVSRSegmentList.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVSRSegmentList) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{88} +} + +func (x *TunnelEncapSubTLVSRSegmentList) GetWeight() *SRWeight { + if x != nil { + return x.Weight + } + return nil +} + +func (x *TunnelEncapSubTLVSRSegmentList) GetSegments() []*anypb.Any { + if x != nil { + return x.Segments + } + return nil +} + +type TunnelEncapSubTLVEgressEndpoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *TunnelEncapSubTLVEgressEndpoint) Reset() { + *x = TunnelEncapSubTLVEgressEndpoint{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[89] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVEgressEndpoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVEgressEndpoint) ProtoMessage() {} + +func (x *TunnelEncapSubTLVEgressEndpoint) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[89] + 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 TunnelEncapSubTLVEgressEndpoint.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVEgressEndpoint) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{89} +} + +func (x *TunnelEncapSubTLVEgressEndpoint) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type TunnelEncapSubTLVUDPDestPort struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Port uint32 `protobuf:"varint,1,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *TunnelEncapSubTLVUDPDestPort) Reset() { + *x = TunnelEncapSubTLVUDPDestPort{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[90] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVUDPDestPort) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVUDPDestPort) ProtoMessage() {} + +func (x *TunnelEncapSubTLVUDPDestPort) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[90] + 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 TunnelEncapSubTLVUDPDestPort.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVUDPDestPort) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{90} +} + +func (x *TunnelEncapSubTLVUDPDestPort) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type TunnelEncapSubTLVUnknown struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *TunnelEncapSubTLVUnknown) Reset() { + *x = TunnelEncapSubTLVUnknown{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[91] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapSubTLVUnknown) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapSubTLVUnknown) ProtoMessage() {} + +func (x *TunnelEncapSubTLVUnknown) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[91] + 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 TunnelEncapSubTLVUnknown.ProtoReflect.Descriptor instead. +func (*TunnelEncapSubTLVUnknown) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{91} +} + +func (x *TunnelEncapSubTLVUnknown) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *TunnelEncapSubTLVUnknown) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type TunnelEncapTLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + // Each TLV must be one of: + // - TunnelEncapSubTLVEncapsulation + // - TunnelEncapSubTLVProtocol + // - TunnelEncapSubTLVColor + // - TunnelEncapSubTLVSRPolicy + // - TunnelEncapSubTLVUnknown + Tlvs []*anypb.Any `protobuf:"bytes,2,rep,name=tlvs,proto3" json:"tlvs,omitempty"` +} + +func (x *TunnelEncapTLV) Reset() { + *x = TunnelEncapTLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[92] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapTLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapTLV) ProtoMessage() {} + +func (x *TunnelEncapTLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[92] + 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 TunnelEncapTLV.ProtoReflect.Descriptor instead. +func (*TunnelEncapTLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{92} +} + +func (x *TunnelEncapTLV) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *TunnelEncapTLV) GetTlvs() []*anypb.Any { + if x != nil { + return x.Tlvs + } + return nil +} + +type TunnelEncapAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tlvs []*TunnelEncapTLV `protobuf:"bytes,1,rep,name=tlvs,proto3" json:"tlvs,omitempty"` +} + +func (x *TunnelEncapAttribute) Reset() { + *x = TunnelEncapAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[93] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TunnelEncapAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TunnelEncapAttribute) ProtoMessage() {} + +func (x *TunnelEncapAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[93] + 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 TunnelEncapAttribute.ProtoReflect.Descriptor instead. +func (*TunnelEncapAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{93} +} + +func (x *TunnelEncapAttribute) GetTlvs() []*TunnelEncapTLV { + if x != nil { + return x.Tlvs + } + return nil +} + +type IPv6AddressSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IsTransitive bool `protobuf:"varint,1,opt,name=is_transitive,json=isTransitive,proto3" json:"is_transitive,omitempty"` + SubType uint32 `protobuf:"varint,2,opt,name=sub_type,json=subType,proto3" json:"sub_type,omitempty"` + Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,4,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *IPv6AddressSpecificExtended) Reset() { + *x = IPv6AddressSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[94] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IPv6AddressSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IPv6AddressSpecificExtended) ProtoMessage() {} + +func (x *IPv6AddressSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[94] + 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 IPv6AddressSpecificExtended.ProtoReflect.Descriptor instead. +func (*IPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{94} +} + +func (x *IPv6AddressSpecificExtended) GetIsTransitive() bool { + if x != nil { + return x.IsTransitive + } + return false +} + +func (x *IPv6AddressSpecificExtended) GetSubType() uint32 { + if x != nil { + return x.SubType + } + return 0 +} + +func (x *IPv6AddressSpecificExtended) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *IPv6AddressSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type RedirectIPv6AddressSpecificExtended struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + LocalAdmin uint32 `protobuf:"varint,2,opt,name=local_admin,json=localAdmin,proto3" json:"local_admin,omitempty"` +} + +func (x *RedirectIPv6AddressSpecificExtended) Reset() { + *x = RedirectIPv6AddressSpecificExtended{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[95] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RedirectIPv6AddressSpecificExtended) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RedirectIPv6AddressSpecificExtended) ProtoMessage() {} + +func (x *RedirectIPv6AddressSpecificExtended) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[95] + 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 RedirectIPv6AddressSpecificExtended.ProtoReflect.Descriptor instead. +func (*RedirectIPv6AddressSpecificExtended) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{95} +} + +func (x *RedirectIPv6AddressSpecificExtended) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *RedirectIPv6AddressSpecificExtended) GetLocalAdmin() uint32 { + if x != nil { + return x.LocalAdmin + } + return 0 +} + +type IP6ExtendedCommunitiesAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Each Community must be one of: + // - IPv6AddressSpecificExtended + // - RedirectIPv6AddressSpecificExtended + Communities []*anypb.Any `protobuf:"bytes,1,rep,name=communities,proto3" json:"communities,omitempty"` +} + +func (x *IP6ExtendedCommunitiesAttribute) Reset() { + *x = IP6ExtendedCommunitiesAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[96] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IP6ExtendedCommunitiesAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IP6ExtendedCommunitiesAttribute) ProtoMessage() {} + +func (x *IP6ExtendedCommunitiesAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[96] + 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 IP6ExtendedCommunitiesAttribute.ProtoReflect.Descriptor instead. +func (*IP6ExtendedCommunitiesAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{96} +} + +func (x *IP6ExtendedCommunitiesAttribute) GetCommunities() []*anypb.Any { + if x != nil { + return x.Communities + } + return nil +} + +type AigpTLVIGPMetric struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Metric uint64 `protobuf:"varint,1,opt,name=metric,proto3" json:"metric,omitempty"` +} + +func (x *AigpTLVIGPMetric) Reset() { + *x = AigpTLVIGPMetric{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[97] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AigpTLVIGPMetric) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AigpTLVIGPMetric) ProtoMessage() {} + +func (x *AigpTLVIGPMetric) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[97] + 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 AigpTLVIGPMetric.ProtoReflect.Descriptor instead. +func (*AigpTLVIGPMetric) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{97} +} + +func (x *AigpTLVIGPMetric) GetMetric() uint64 { + if x != nil { + return x.Metric + } + return 0 +} + +type AigpTLVUnknown struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *AigpTLVUnknown) Reset() { + *x = AigpTLVUnknown{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[98] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AigpTLVUnknown) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AigpTLVUnknown) ProtoMessage() {} + +func (x *AigpTLVUnknown) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[98] + 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 AigpTLVUnknown.ProtoReflect.Descriptor instead. +func (*AigpTLVUnknown) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{98} +} + +func (x *AigpTLVUnknown) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *AigpTLVUnknown) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +type AigpAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Each TLV must be one of: + // - AigpTLVIGPMetric + // - AigpTLVUnknown + Tlvs []*anypb.Any `protobuf:"bytes,1,rep,name=tlvs,proto3" json:"tlvs,omitempty"` +} + +func (x *AigpAttribute) Reset() { + *x = AigpAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[99] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AigpAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AigpAttribute) ProtoMessage() {} + +func (x *AigpAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[99] + 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 AigpAttribute.ProtoReflect.Descriptor instead. +func (*AigpAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{99} +} + +func (x *AigpAttribute) GetTlvs() []*anypb.Any { + if x != nil { + return x.Tlvs + } + return nil +} + +type LargeCommunity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GlobalAdmin uint32 `protobuf:"varint,1,opt,name=global_admin,json=globalAdmin,proto3" json:"global_admin,omitempty"` + LocalData1 uint32 `protobuf:"varint,2,opt,name=local_data1,json=localData1,proto3" json:"local_data1,omitempty"` + LocalData2 uint32 `protobuf:"varint,3,opt,name=local_data2,json=localData2,proto3" json:"local_data2,omitempty"` +} + +func (x *LargeCommunity) Reset() { + *x = LargeCommunity{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[100] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LargeCommunity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LargeCommunity) ProtoMessage() {} + +func (x *LargeCommunity) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[100] + 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 LargeCommunity.ProtoReflect.Descriptor instead. +func (*LargeCommunity) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{100} +} + +func (x *LargeCommunity) GetGlobalAdmin() uint32 { + if x != nil { + return x.GlobalAdmin + } + return 0 +} + +func (x *LargeCommunity) GetLocalData1() uint32 { + if x != nil { + return x.LocalData1 + } + return 0 +} + +func (x *LargeCommunity) GetLocalData2() uint32 { + if x != nil { + return x.LocalData2 + } + return 0 +} + +type LargeCommunitiesAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Communities []*LargeCommunity `protobuf:"bytes,1,rep,name=communities,proto3" json:"communities,omitempty"` +} + +func (x *LargeCommunitiesAttribute) Reset() { + *x = LargeCommunitiesAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[101] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LargeCommunitiesAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LargeCommunitiesAttribute) ProtoMessage() {} + +func (x *LargeCommunitiesAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[101] + 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 LargeCommunitiesAttribute.ProtoReflect.Descriptor instead. +func (*LargeCommunitiesAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{101} +} + +func (x *LargeCommunitiesAttribute) GetCommunities() []*LargeCommunity { + if x != nil { + return x.Communities + } + return nil +} + +type LsNodeFlags struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Overload bool `protobuf:"varint,1,opt,name=overload,proto3" json:"overload,omitempty"` + Attached bool `protobuf:"varint,2,opt,name=attached,proto3" json:"attached,omitempty"` + External bool `protobuf:"varint,3,opt,name=external,proto3" json:"external,omitempty"` + Abr bool `protobuf:"varint,4,opt,name=abr,proto3" json:"abr,omitempty"` + Router bool `protobuf:"varint,5,opt,name=router,proto3" json:"router,omitempty"` + V6 bool `protobuf:"varint,6,opt,name=v6,proto3" json:"v6,omitempty"` +} + +func (x *LsNodeFlags) Reset() { + *x = LsNodeFlags{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[102] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsNodeFlags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsNodeFlags) ProtoMessage() {} + +func (x *LsNodeFlags) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[102] + 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 LsNodeFlags.ProtoReflect.Descriptor instead. +func (*LsNodeFlags) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{102} +} + +func (x *LsNodeFlags) GetOverload() bool { + if x != nil { + return x.Overload + } + return false +} + +func (x *LsNodeFlags) GetAttached() bool { + if x != nil { + return x.Attached + } + return false +} + +func (x *LsNodeFlags) GetExternal() bool { + if x != nil { + return x.External + } + return false +} + +func (x *LsNodeFlags) GetAbr() bool { + if x != nil { + return x.Abr + } + return false +} + +func (x *LsNodeFlags) GetRouter() bool { + if x != nil { + return x.Router + } + return false +} + +func (x *LsNodeFlags) GetV6() bool { + if x != nil { + return x.V6 + } + return false +} + +type LsIGPFlags struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Down bool `protobuf:"varint,1,opt,name=down,proto3" json:"down,omitempty"` + NoUnicast bool `protobuf:"varint,2,opt,name=no_unicast,json=noUnicast,proto3" json:"no_unicast,omitempty"` + LocalAddress bool `protobuf:"varint,3,opt,name=local_address,json=localAddress,proto3" json:"local_address,omitempty"` + PropagateNssa bool `protobuf:"varint,4,opt,name=propagate_nssa,json=propagateNssa,proto3" json:"propagate_nssa,omitempty"` +} + +func (x *LsIGPFlags) Reset() { + *x = LsIGPFlags{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[103] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsIGPFlags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsIGPFlags) ProtoMessage() {} + +func (x *LsIGPFlags) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[103] + 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 LsIGPFlags.ProtoReflect.Descriptor instead. +func (*LsIGPFlags) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{103} +} + +func (x *LsIGPFlags) GetDown() bool { + if x != nil { + return x.Down + } + return false +} + +func (x *LsIGPFlags) GetNoUnicast() bool { + if x != nil { + return x.NoUnicast + } + return false +} + +func (x *LsIGPFlags) GetLocalAddress() bool { + if x != nil { + return x.LocalAddress + } + return false +} + +func (x *LsIGPFlags) GetPropagateNssa() bool { + if x != nil { + return x.PropagateNssa + } + return false +} + +type LsSrRange struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Begin uint32 `protobuf:"varint,1,opt,name=begin,proto3" json:"begin,omitempty"` + End uint32 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *LsSrRange) Reset() { + *x = LsSrRange{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[104] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsSrRange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsSrRange) ProtoMessage() {} + +func (x *LsSrRange) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[104] + 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 LsSrRange.ProtoReflect.Descriptor instead. +func (*LsSrRange) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{104} +} + +func (x *LsSrRange) GetBegin() uint32 { + if x != nil { + return x.Begin + } + return 0 +} + +func (x *LsSrRange) GetEnd() uint32 { + if x != nil { + return x.End + } + return 0 +} + +type LsSrCapabilities struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ipv4Supported bool `protobuf:"varint,1,opt,name=ipv4_supported,json=ipv4Supported,proto3" json:"ipv4_supported,omitempty"` + Ipv6Supported bool `protobuf:"varint,2,opt,name=ipv6_supported,json=ipv6Supported,proto3" json:"ipv6_supported,omitempty"` + Ranges []*LsSrRange `protobuf:"bytes,3,rep,name=ranges,proto3" json:"ranges,omitempty"` +} + +func (x *LsSrCapabilities) Reset() { + *x = LsSrCapabilities{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[105] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsSrCapabilities) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsSrCapabilities) ProtoMessage() {} + +func (x *LsSrCapabilities) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[105] + 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 LsSrCapabilities.ProtoReflect.Descriptor instead. +func (*LsSrCapabilities) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{105} +} + +func (x *LsSrCapabilities) GetIpv4Supported() bool { + if x != nil { + return x.Ipv4Supported + } + return false +} + +func (x *LsSrCapabilities) GetIpv6Supported() bool { + if x != nil { + return x.Ipv6Supported + } + return false +} + +func (x *LsSrCapabilities) GetRanges() []*LsSrRange { + if x != nil { + return x.Ranges + } + return nil +} + +type LsSrLocalBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ranges []*LsSrRange `protobuf:"bytes,1,rep,name=ranges,proto3" json:"ranges,omitempty"` +} + +func (x *LsSrLocalBlock) Reset() { + *x = LsSrLocalBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[106] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsSrLocalBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsSrLocalBlock) ProtoMessage() {} + +func (x *LsSrLocalBlock) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[106] + 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 LsSrLocalBlock.ProtoReflect.Descriptor instead. +func (*LsSrLocalBlock) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{106} +} + +func (x *LsSrLocalBlock) GetRanges() []*LsSrRange { + if x != nil { + return x.Ranges + } + return nil +} + +type LsAttributeNode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Flags *LsNodeFlags `protobuf:"bytes,2,opt,name=flags,proto3" json:"flags,omitempty"` + LocalRouterId string `protobuf:"bytes,3,opt,name=local_router_id,json=localRouterId,proto3" json:"local_router_id,omitempty"` + LocalRouterIdV6 string `protobuf:"bytes,4,opt,name=local_router_id_v6,json=localRouterIdV6,proto3" json:"local_router_id_v6,omitempty"` + IsisArea []byte `protobuf:"bytes,5,opt,name=isis_area,json=isisArea,proto3" json:"isis_area,omitempty"` + Opaque []byte `protobuf:"bytes,6,opt,name=opaque,proto3" json:"opaque,omitempty"` + SrCapabilities *LsSrCapabilities `protobuf:"bytes,7,opt,name=sr_capabilities,json=srCapabilities,proto3" json:"sr_capabilities,omitempty"` + SrAlgorithms []byte `protobuf:"bytes,8,opt,name=sr_algorithms,json=srAlgorithms,proto3" json:"sr_algorithms,omitempty"` + SrLocalBlock *LsSrLocalBlock `protobuf:"bytes,9,opt,name=sr_local_block,json=srLocalBlock,proto3" json:"sr_local_block,omitempty"` +} + +func (x *LsAttributeNode) Reset() { + *x = LsAttributeNode{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[107] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsAttributeNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsAttributeNode) ProtoMessage() {} + +func (x *LsAttributeNode) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[107] + 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 LsAttributeNode.ProtoReflect.Descriptor instead. +func (*LsAttributeNode) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{107} +} + +func (x *LsAttributeNode) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *LsAttributeNode) GetFlags() *LsNodeFlags { + if x != nil { + return x.Flags + } + return nil +} + +func (x *LsAttributeNode) GetLocalRouterId() string { + if x != nil { + return x.LocalRouterId + } + return "" +} + +func (x *LsAttributeNode) GetLocalRouterIdV6() string { + if x != nil { + return x.LocalRouterIdV6 + } + return "" +} + +func (x *LsAttributeNode) GetIsisArea() []byte { + if x != nil { + return x.IsisArea + } + return nil +} + +func (x *LsAttributeNode) GetOpaque() []byte { + if x != nil { + return x.Opaque + } + return nil +} + +func (x *LsAttributeNode) GetSrCapabilities() *LsSrCapabilities { + if x != nil { + return x.SrCapabilities + } + return nil +} + +func (x *LsAttributeNode) GetSrAlgorithms() []byte { + if x != nil { + return x.SrAlgorithms + } + return nil +} + +func (x *LsAttributeNode) GetSrLocalBlock() *LsSrLocalBlock { + if x != nil { + return x.SrLocalBlock + } + return nil +} + +type LsAttributeLink struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + LocalRouterId string `protobuf:"bytes,2,opt,name=local_router_id,json=localRouterId,proto3" json:"local_router_id,omitempty"` + LocalRouterIdV6 string `protobuf:"bytes,3,opt,name=local_router_id_v6,json=localRouterIdV6,proto3" json:"local_router_id_v6,omitempty"` + RemoteRouterId string `protobuf:"bytes,4,opt,name=remote_router_id,json=remoteRouterId,proto3" json:"remote_router_id,omitempty"` + RemoteRouterIdV6 string `protobuf:"bytes,5,opt,name=remote_router_id_v6,json=remoteRouterIdV6,proto3" json:"remote_router_id_v6,omitempty"` + AdminGroup uint32 `protobuf:"varint,6,opt,name=admin_group,json=adminGroup,proto3" json:"admin_group,omitempty"` + DefaultTeMetric uint32 `protobuf:"varint,7,opt,name=default_te_metric,json=defaultTeMetric,proto3" json:"default_te_metric,omitempty"` + IgpMetric uint32 `protobuf:"varint,8,opt,name=igp_metric,json=igpMetric,proto3" json:"igp_metric,omitempty"` + Opaque []byte `protobuf:"bytes,9,opt,name=opaque,proto3" json:"opaque,omitempty"` + Bandwidth float32 `protobuf:"fixed32,10,opt,name=bandwidth,proto3" json:"bandwidth,omitempty"` + ReservableBandwidth float32 `protobuf:"fixed32,11,opt,name=reservable_bandwidth,json=reservableBandwidth,proto3" json:"reservable_bandwidth,omitempty"` + UnreservedBandwidth []float32 `protobuf:"fixed32,12,rep,packed,name=unreserved_bandwidth,json=unreservedBandwidth,proto3" json:"unreserved_bandwidth,omitempty"` + SrAdjacencySid uint32 `protobuf:"varint,13,opt,name=sr_adjacency_sid,json=srAdjacencySid,proto3" json:"sr_adjacency_sid,omitempty"` + Srlgs []uint32 `protobuf:"varint,14,rep,packed,name=srlgs,proto3" json:"srlgs,omitempty"` +} + +func (x *LsAttributeLink) Reset() { + *x = LsAttributeLink{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[108] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsAttributeLink) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsAttributeLink) ProtoMessage() {} + +func (x *LsAttributeLink) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[108] + 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 LsAttributeLink.ProtoReflect.Descriptor instead. +func (*LsAttributeLink) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{108} +} + +func (x *LsAttributeLink) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *LsAttributeLink) GetLocalRouterId() string { + if x != nil { + return x.LocalRouterId + } + return "" +} + +func (x *LsAttributeLink) GetLocalRouterIdV6() string { + if x != nil { + return x.LocalRouterIdV6 + } + return "" +} + +func (x *LsAttributeLink) GetRemoteRouterId() string { + if x != nil { + return x.RemoteRouterId + } + return "" +} + +func (x *LsAttributeLink) GetRemoteRouterIdV6() string { + if x != nil { + return x.RemoteRouterIdV6 + } + return "" +} + +func (x *LsAttributeLink) GetAdminGroup() uint32 { + if x != nil { + return x.AdminGroup + } + return 0 +} + +func (x *LsAttributeLink) GetDefaultTeMetric() uint32 { + if x != nil { + return x.DefaultTeMetric + } + return 0 +} + +func (x *LsAttributeLink) GetIgpMetric() uint32 { + if x != nil { + return x.IgpMetric + } + return 0 +} + +func (x *LsAttributeLink) GetOpaque() []byte { + if x != nil { + return x.Opaque + } + return nil +} + +func (x *LsAttributeLink) GetBandwidth() float32 { + if x != nil { + return x.Bandwidth + } + return 0 +} + +func (x *LsAttributeLink) GetReservableBandwidth() float32 { + if x != nil { + return x.ReservableBandwidth + } + return 0 +} + +func (x *LsAttributeLink) GetUnreservedBandwidth() []float32 { + if x != nil { + return x.UnreservedBandwidth + } + return nil +} + +func (x *LsAttributeLink) GetSrAdjacencySid() uint32 { + if x != nil { + return x.SrAdjacencySid + } + return 0 +} + +func (x *LsAttributeLink) GetSrlgs() []uint32 { + if x != nil { + return x.Srlgs + } + return nil +} + +type LsAttributePrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IgpFlags *LsIGPFlags `protobuf:"bytes,1,opt,name=igp_flags,json=igpFlags,proto3" json:"igp_flags,omitempty"` + Opaque []byte `protobuf:"bytes,2,opt,name=opaque,proto3" json:"opaque,omitempty"` + SrPrefixSid uint32 `protobuf:"varint,3,opt,name=sr_prefix_sid,json=srPrefixSid,proto3" json:"sr_prefix_sid,omitempty"` +} + +func (x *LsAttributePrefix) Reset() { + *x = LsAttributePrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[109] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsAttributePrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsAttributePrefix) ProtoMessage() {} + +func (x *LsAttributePrefix) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[109] + 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 LsAttributePrefix.ProtoReflect.Descriptor instead. +func (*LsAttributePrefix) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{109} +} + +func (x *LsAttributePrefix) GetIgpFlags() *LsIGPFlags { + if x != nil { + return x.IgpFlags + } + return nil +} + +func (x *LsAttributePrefix) GetOpaque() []byte { + if x != nil { + return x.Opaque + } + return nil +} + +func (x *LsAttributePrefix) GetSrPrefixSid() uint32 { + if x != nil { + return x.SrPrefixSid + } + return 0 +} + +type LsAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Node *LsAttributeNode `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + Link *LsAttributeLink `protobuf:"bytes,2,opt,name=link,proto3" json:"link,omitempty"` + Prefix *LsAttributePrefix `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *LsAttribute) Reset() { + *x = LsAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[110] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LsAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LsAttribute) ProtoMessage() {} + +func (x *LsAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[110] + 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 LsAttribute.ProtoReflect.Descriptor instead. +func (*LsAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{110} +} + +func (x *LsAttribute) GetNode() *LsAttributeNode { + if x != nil { + return x.Node + } + return nil +} + +func (x *LsAttribute) GetLink() *LsAttributeLink { + if x != nil { + return x.Link + } + return nil +} + +func (x *LsAttribute) GetPrefix() *LsAttributePrefix { + if x != nil { + return x.Prefix + } + return nil +} + +type UnknownAttribute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Type uint32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"` + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *UnknownAttribute) Reset() { + *x = UnknownAttribute{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[111] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnknownAttribute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnknownAttribute) ProtoMessage() {} + +func (x *UnknownAttribute) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[111] + 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 UnknownAttribute.ProtoReflect.Descriptor instead. +func (*UnknownAttribute) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{111} +} + +func (x *UnknownAttribute) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *UnknownAttribute) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +func (x *UnknownAttribute) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-3.2.1 +type SRv6StructureSubSubTLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocatorBlockLength uint32 `protobuf:"varint,1,opt,name=locator_block_length,json=locatorBlockLength,proto3" json:"locator_block_length,omitempty"` + LocatorNodeLength uint32 `protobuf:"varint,2,opt,name=locator_node_length,json=locatorNodeLength,proto3" json:"locator_node_length,omitempty"` + FunctionLength uint32 `protobuf:"varint,3,opt,name=function_length,json=functionLength,proto3" json:"function_length,omitempty"` + ArgumentLength uint32 `protobuf:"varint,4,opt,name=argument_length,json=argumentLength,proto3" json:"argument_length,omitempty"` + TranspositionLength uint32 `protobuf:"varint,5,opt,name=transposition_length,json=transpositionLength,proto3" json:"transposition_length,omitempty"` + TranspositionOffset uint32 `protobuf:"varint,6,opt,name=transposition_offset,json=transpositionOffset,proto3" json:"transposition_offset,omitempty"` +} + +func (x *SRv6StructureSubSubTLV) Reset() { + *x = SRv6StructureSubSubTLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[112] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6StructureSubSubTLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6StructureSubSubTLV) ProtoMessage() {} + +func (x *SRv6StructureSubSubTLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[112] + 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 SRv6StructureSubSubTLV.ProtoReflect.Descriptor instead. +func (*SRv6StructureSubSubTLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{112} +} + +func (x *SRv6StructureSubSubTLV) GetLocatorBlockLength() uint32 { + if x != nil { + return x.LocatorBlockLength + } + return 0 +} + +func (x *SRv6StructureSubSubTLV) GetLocatorNodeLength() uint32 { + if x != nil { + return x.LocatorNodeLength + } + return 0 +} + +func (x *SRv6StructureSubSubTLV) GetFunctionLength() uint32 { + if x != nil { + return x.FunctionLength + } + return 0 +} + +func (x *SRv6StructureSubSubTLV) GetArgumentLength() uint32 { + if x != nil { + return x.ArgumentLength + } + return 0 +} + +func (x *SRv6StructureSubSubTLV) GetTranspositionLength() uint32 { + if x != nil { + return x.TranspositionLength + } + return 0 +} + +func (x *SRv6StructureSubSubTLV) GetTranspositionOffset() uint32 { + if x != nil { + return x.TranspositionOffset + } + return 0 +} + +type SRv6SIDFlags struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Placeholder for future sid flags + Flag_1 bool `protobuf:"varint,1,opt,name=flag_1,json=flag1,proto3" json:"flag_1,omitempty"` +} + +func (x *SRv6SIDFlags) Reset() { + *x = SRv6SIDFlags{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[113] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6SIDFlags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6SIDFlags) ProtoMessage() {} + +func (x *SRv6SIDFlags) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[113] + 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 SRv6SIDFlags.ProtoReflect.Descriptor instead. +func (*SRv6SIDFlags) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{113} +} + +func (x *SRv6SIDFlags) GetFlag_1() bool { + if x != nil { + return x.Flag_1 + } + return false +} + +type SRv6TLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tlv []*anypb.Any `protobuf:"bytes,1,rep,name=tlv,proto3" json:"tlv,omitempty"` +} + +func (x *SRv6TLV) Reset() { + *x = SRv6TLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[114] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6TLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6TLV) ProtoMessage() {} + +func (x *SRv6TLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[114] + 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 SRv6TLV.ProtoReflect.Descriptor instead. +func (*SRv6TLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{114} +} + +func (x *SRv6TLV) GetTlv() []*anypb.Any { + if x != nil { + return x.Tlv + } + return nil +} + +// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1 +type SRv6InformationSubTLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sid []byte `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"` + Flags *SRv6SIDFlags `protobuf:"bytes,2,opt,name=flags,proto3" json:"flags,omitempty"` + EndpointBehavior uint32 `protobuf:"varint,3,opt,name=endpoint_behavior,json=endpointBehavior,proto3" json:"endpoint_behavior,omitempty"` + // SRv6TLV is one of: + // - SRv6StructureSubSubTLV + SubSubTlvs map[uint32]*SRv6TLV `protobuf:"bytes,4,rep,name=sub_sub_tlvs,json=subSubTlvs,proto3" json:"sub_sub_tlvs,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *SRv6InformationSubTLV) Reset() { + *x = SRv6InformationSubTLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[115] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6InformationSubTLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6InformationSubTLV) ProtoMessage() {} + +func (x *SRv6InformationSubTLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[115] + 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 SRv6InformationSubTLV.ProtoReflect.Descriptor instead. +func (*SRv6InformationSubTLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{115} +} + +func (x *SRv6InformationSubTLV) GetSid() []byte { + if x != nil { + return x.Sid + } + return nil +} + +func (x *SRv6InformationSubTLV) GetFlags() *SRv6SIDFlags { + if x != nil { + return x.Flags + } + return nil +} + +func (x *SRv6InformationSubTLV) GetEndpointBehavior() uint32 { + if x != nil { + return x.EndpointBehavior + } + return 0 +} + +func (x *SRv6InformationSubTLV) GetSubSubTlvs() map[uint32]*SRv6TLV { + if x != nil { + return x.SubSubTlvs + } + return nil +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-2 +type SRv6L3ServiceTLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // SRv6TLV is one of: + // - SRv6InformationSubTLV + SubTlvs map[uint32]*SRv6TLV `protobuf:"bytes,1,rep,name=sub_tlvs,json=subTlvs,proto3" json:"sub_tlvs,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *SRv6L3ServiceTLV) Reset() { + *x = SRv6L3ServiceTLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[116] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6L3ServiceTLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6L3ServiceTLV) ProtoMessage() {} + +func (x *SRv6L3ServiceTLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[116] + 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 SRv6L3ServiceTLV.ProtoReflect.Descriptor instead. +func (*SRv6L3ServiceTLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{116} +} + +func (x *SRv6L3ServiceTLV) GetSubTlvs() map[uint32]*SRv6TLV { + if x != nil { + return x.SubTlvs + } + return nil +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-2 +type SRv6L2ServiceTLV struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // SRv6TLV is one of: + // - SRv6InformationSubTLV + SubTlvs map[uint32]*SRv6TLV `protobuf:"bytes,1,rep,name=sub_tlvs,json=subTlvs,proto3" json:"sub_tlvs,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *SRv6L2ServiceTLV) Reset() { + *x = SRv6L2ServiceTLV{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[117] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SRv6L2ServiceTLV) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SRv6L2ServiceTLV) ProtoMessage() {} + +func (x *SRv6L2ServiceTLV) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[117] + 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 SRv6L2ServiceTLV.ProtoReflect.Descriptor instead. +func (*SRv6L2ServiceTLV) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{117} +} + +func (x *SRv6L2ServiceTLV) GetSubTlvs() map[uint32]*SRv6TLV { + if x != nil { + return x.SubTlvs + } + return nil +} + +// https://tools.ietf.org/html/rfc8669 +type PrefixSID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // tlv is one of: + // - IndexLabelTLV Type 1 (not yet implemented) + // - OriginatorSRGBTLV Type 3 (not yet implemented) + // - SRv6L3ServiceTLV Type 5 + // - SRv6L2ServiceTLV Type 6 + Tlvs []*anypb.Any `protobuf:"bytes,1,rep,name=tlvs,proto3" json:"tlvs,omitempty"` +} + +func (x *PrefixSID) Reset() { + *x = PrefixSID{} + if protoimpl.UnsafeEnabled { + mi := &file_attribute_proto_msgTypes[118] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PrefixSID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrefixSID) ProtoMessage() {} + +func (x *PrefixSID) ProtoReflect() protoreflect.Message { + mi := &file_attribute_proto_msgTypes[118] + 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 PrefixSID.ProtoReflect.Descriptor instead. +func (*PrefixSID) Descriptor() ([]byte, []int) { + return file_attribute_proto_rawDescGZIP(), []int{118} +} + +func (x *PrefixSID) GetTlvs() []*anypb.Any { + if x != nil { + return x.Tlvs + } + return nil +} + +var File_attribute_proto protoreflect.FileDescriptor + +var file_attribute_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x05, 0x61, 0x70, 0x69, 0x70, 0x62, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x67, 0x6f, 0x62, 0x67, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x29, 0x0a, 0x0f, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x22, 0xad, 0x01, 0x0a, 0x09, + 0x41, 0x73, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x41, 0x73, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x5b, + 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x53, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, + 0x0f, 0x0a, 0x0b, 0x41, 0x53, 0x5f, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x02, + 0x12, 0x16, 0x0a, 0x12, 0x41, 0x53, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x45, 0x44, 0x5f, 0x53, 0x45, + 0x51, 0x55, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x53, 0x5f, 0x43, + 0x4f, 0x4e, 0x46, 0x45, 0x44, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x04, 0x22, 0x3f, 0x0a, 0x0f, 0x41, + 0x73, 0x50, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2c, + 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x73, 0x53, 0x65, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2d, 0x0a, 0x10, + 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x22, 0x2a, 0x0a, 0x16, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x45, 0x78, 0x69, 0x74, 0x44, 0x69, 0x73, 0x63, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x6d, 0x65, 0x64, 0x22, 0x33, 0x0a, 0x12, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x72, 0x65, 0x66, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x22, 0x1a, 0x0a, 0x18, + 0x41, 0x74, 0x6f, 0x6d, 0x69, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0x41, 0x0a, 0x13, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, + 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x38, 0x0a, 0x14, 0x43, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x27, 0x0a, 0x15, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x28, + 0x0a, 0x14, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x48, 0x0a, 0x0f, 0x49, 0x50, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x22, 0x67, 0x0a, 0x16, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x65, 0x64, 0x49, 0x50, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x4c, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x2d, 0x0a, 0x11, 0x45, + 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x4c, 0x52, 0x49, + 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, 0x51, 0x0a, 0x1d, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x72, + 0x54, 0x77, 0x6f, 0x4f, 0x63, 0x74, 0x65, 0x74, 0x41, 0x53, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x22, 0x4f, 0x0a, + 0x1b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, + 0x68, 0x65, 0x72, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x22, 0x52, + 0x0a, 0x1e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, + 0x73, 0x68, 0x65, 0x72, 0x46, 0x6f, 0x75, 0x72, 0x4f, 0x63, 0x74, 0x65, 0x74, 0x41, 0x53, 0x4e, + 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x22, 0x45, 0x0a, 0x19, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x53, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x1e, 0x45, 0x56, + 0x50, 0x4e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, + 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, + 0x72, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x65, 0x73, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x52, 0x03, 0x65, 0x73, 0x69, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, + 0xf2, 0x01, 0x0a, 0x1b, 0x45, 0x56, 0x50, 0x4e, 0x4d, 0x41, 0x43, 0x49, 0x50, 0x41, 0x64, 0x76, + 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, + 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x65, 0x73, 0x69, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x74, 0x68, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x65, 0x73, 0x69, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0b, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x12, 0x1f, 0x0a, 0x0b, + 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x22, 0x90, 0x01, 0x0a, 0x26, 0x45, 0x56, 0x50, 0x4e, 0x49, 0x6e, 0x63, + 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x63, 0x61, 0x73, 0x74, 0x45, + 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, + 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x70, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x70, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x18, 0x45, 0x56, 0x50, 0x4e, + 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x65, 0x73, + 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x45, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x65, 0x73, 0x69, 0x12, 0x1d, + 0x0a, 0x0a, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x86, 0x02, + 0x0a, 0x11, 0x45, 0x56, 0x50, 0x4e, 0x49, 0x50, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x65, 0x73, 0x69, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, + 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x03, 0x65, 0x73, 0x69, 0x12, 0x21, 0x0a, + 0x0c, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, 0x67, + 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x22, 0x0a, + 0x0d, 0x69, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x69, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, + 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x77, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x7f, 0x0a, 0x0e, 0x45, 0x56, 0x50, 0x4e, 0x49, 0x50, + 0x4d, 0x53, 0x49, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x21, + 0x0a, 0x0c, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x54, 0x61, + 0x67, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x74, 0x22, 0x7e, 0x0a, 0x0c, 0x53, 0x52, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, + 0x24, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, + 0x69, 0x73, 0x68, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x90, 0x01, 0x0a, 0x19, 0x4c, 0x61, 0x62, 0x65, + 0x6c, 0x65, 0x64, 0x56, 0x50, 0x4e, 0x49, 0x50, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x24, 0x0a, + 0x02, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, + 0x02, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x65, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, + 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x53, 0x0a, 0x19, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x74, 0x22, + 0x75, 0x0a, 0x10, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x49, 0x50, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, + 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3b, 0x0a, 0x0b, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, + 0x65, 0x63, 0x4d, 0x41, 0x43, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x22, 0x3d, 0x0a, 0x15, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x0e, 0x0a, 0x02, + 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x5b, 0x0a, 0x11, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x05, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, + 0x3a, 0x0a, 0x0c, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x4e, 0x4c, 0x52, 0x49, 0x12, + 0x2a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x0f, 0x56, + 0x50, 0x4e, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x70, 0x65, 0x63, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x24, + 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x02, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, + 0x22, 0x34, 0x0a, 0x0a, 0x4f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4c, 0x73, 0x4e, 0x6f, 0x64, + 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x61, + 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1a, 0x0a, + 0x09, 0x62, 0x67, 0x70, 0x5f, 0x6c, 0x73, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x62, 0x67, 0x70, 0x4c, 0x73, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x6f, 0x73, 0x70, + 0x66, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0a, 0x6f, 0x73, 0x70, 0x66, 0x41, 0x72, 0x65, 0x61, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x73, 0x65, 0x75, 0x64, 0x6f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, + 0x67, 0x70, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x70, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, + 0x98, 0x02, 0x0a, 0x10, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6c, 0x69, 0x6e, + 0x6b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x69, 0x6e, 0x6b, + 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x0c, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x64, 0x12, 0x2e, + 0x0a, 0x13, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x49, 0x70, 0x76, 0x34, 0x12, 0x2c, + 0x0a, 0x12, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x5f, + 0x69, 0x70, 0x76, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x65, 0x69, 0x67, + 0x68, 0x62, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x49, 0x70, 0x76, 0x34, 0x12, 0x2e, 0x0a, 0x13, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x5f, 0x69, + 0x70, 0x76, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x49, 0x70, 0x76, 0x36, 0x12, 0x2c, 0x0a, 0x12, + 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x5f, 0x69, 0x70, + 0x76, 0x36, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x49, 0x70, 0x76, 0x36, 0x22, 0x7d, 0x0a, 0x12, 0x4c, 0x73, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, + 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x70, 0x5f, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x70, 0x52, 0x65, 0x61, + 0x63, 0x68, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0f, 0x6f, 0x73, 0x70, + 0x66, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4f, 0x73, 0x70, + 0x66, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x6f, 0x73, 0x70, 0x66, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x44, 0x0a, 0x0a, 0x4c, 0x73, 0x4e, + 0x6f, 0x64, 0x65, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x36, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x22, + 0xc0, 0x01, 0x0a, 0x0a, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x36, + 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, + 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x40, 0x0a, 0x0f, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x52, 0x0e, 0x6c, 0x69, 0x6e, 0x6b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x0e, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x56, + 0x34, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x36, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x46, 0x0a, + 0x11, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x52, 0x10, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x0e, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x56, 0x36, 0x4e, 0x4c, 0x52, 0x49, 0x12, 0x36, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x46, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x10, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x22, 0xcd, 0x01, 0x0a, 0x0c, 0x4c, 0x73, 0x41, + 0x64, 0x64, 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x4c, 0x73, 0x4e, 0x4c, 0x52, 0x49, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x28, 0x0a, 0x04, 0x6e, 0x6c, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x6e, 0x6c, 0x72, 0x69, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x12, 0x34, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x4c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x44, 0x52, 0x0a, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x61, 0x0a, 0x21, 0x4d, 0x55, 0x50, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x77, 0x6f, 0x72, 0x6b, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, + 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, + 0x02, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x60, 0x0a, 0x1e, 0x4d, + 0x55, 0x50, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, + 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, + 0x02, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x91, 0x02, + 0x0a, 0x1f, 0x4d, 0x55, 0x50, 0x54, 0x79, 0x70, 0x65, 0x31, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x27, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, + 0x18, 0x01, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x65, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, + 0x71, 0x66, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x71, 0x66, 0x69, 0x12, 0x36, + 0x0a, 0x17, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x15, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x1f, 0x4d, 0x55, 0x50, 0x54, 0x79, 0x70, 0x65, 0x32, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x65, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x65, + 0x69, 0x64, 0x22, 0x86, 0x01, 0x0a, 0x14, 0x4d, 0x70, 0x52, 0x65, 0x61, 0x63, 0x68, 0x4e, 0x4c, + 0x52, 0x49, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x73, 0x12, + 0x2a, 0x0a, 0x05, 0x6e, 0x6c, 0x72, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x6e, 0x6c, 0x72, 0x69, 0x73, 0x22, 0x6b, 0x0a, 0x16, 0x4d, + 0x70, 0x55, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x4e, 0x4c, 0x52, 0x49, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x05, + 0x6e, 0x6c, 0x72, 0x69, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, + 0x79, 0x52, 0x05, 0x6e, 0x6c, 0x72, 0x69, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x1a, 0x54, 0x77, 0x6f, + 0x4f, 0x63, 0x74, 0x65, 0x74, 0x41, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, + 0x69, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, + 0x73, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x98, 0x01, 0x0a, 0x1b, 0x49, + 0x50, 0x76, 0x34, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, + 0x69, 0x63, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, + 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0c, 0x69, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x73, 0x75, 0x62, 0x54, 0x79, 0x70, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x1b, 0x46, 0x6f, 0x75, 0x72, 0x4f, 0x63, + 0x74, 0x65, 0x74, 0x41, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, + 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x75, + 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x47, 0x0a, 0x15, 0x4c, 0x69, 0x6e, 0x6b, + 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, + 0x61, 0x73, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x22, 0x2a, 0x0a, 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x25, 0x0a, + 0x0d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x30, 0x0a, 0x0d, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x22, 0x4b, 0x0a, 0x0e, 0x4f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x52, 0x0a, + 0x10, 0x45, 0x53, 0x49, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x53, + 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x22, 0x32, 0x0a, 0x13, 0x45, 0x53, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x73, 0x5f, 0x69, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x73, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x55, 0x0a, 0x13, 0x4d, 0x61, 0x63, 0x4d, 0x6f, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, + 0x69, 0x73, 0x5f, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x69, 0x73, 0x53, 0x74, 0x69, 0x63, 0x6b, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75, 0x6d, 0x22, 0x25, 0x0a, 0x11, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6d, 0x61, 0x63, 0x22, 0x3b, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x61, + 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x72, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x04, 0x72, 0x61, 0x74, 0x65, + 0x22, 0x4b, 0x0a, 0x15, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x22, 0x57, 0x0a, + 0x22, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x54, 0x77, 0x6f, 0x4f, 0x63, 0x74, 0x65, + 0x74, 0x41, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x60, 0x0a, 0x23, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x49, 0x50, 0x76, 0x34, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x70, 0x65, + 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x58, 0x0a, 0x23, 0x52, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x46, 0x6f, 0x75, 0x72, 0x4f, 0x63, 0x74, 0x65, 0x74, 0x41, 0x73, 0x53, + 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, + 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x22, 0x2b, 0x0a, 0x15, 0x54, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x52, 0x65, 0x6d, + 0x61, 0x72, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x73, 0x63, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x64, 0x73, 0x63, 0x70, 0x22, + 0x6a, 0x0a, 0x0b, 0x4d, 0x55, 0x50, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x73, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x34, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0a, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x34, 0x22, 0x3b, 0x0a, 0x0f, 0x55, + 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x56, 0x0a, 0x1c, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, + 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x22, 0x40, 0x0a, 0x10, 0x41, 0x73, 0x34, 0x50, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, + 0x73, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x22, 0x44, 0x0a, 0x16, 0x41, 0x73, 0x34, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x61, 0x73, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 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, 0x65, 0x0a, 0x13, 0x50, 0x6d, 0x73, 0x69, + 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, + 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, + 0x4a, 0x0a, 0x1e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, + 0x62, 0x54, 0x4c, 0x56, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x22, 0x37, 0x0a, 0x19, 0x54, + 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x2e, 0x0a, 0x16, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, + 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x1d, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, + 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x53, 0x52, 0x50, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0a, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x56, 0x0a, 0x24, 0x54, + 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, + 0x53, 0x52, 0x43, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x1b, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, + 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x53, 0x52, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x49, + 0x0a, 0x1d, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, + 0x54, 0x4c, 0x56, 0x53, 0x52, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x49, 0x44, 0x12, + 0x28, 0x0a, 0x04, 0x62, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x41, 0x6e, 0x79, 0x52, 0x04, 0x62, 0x73, 0x69, 0x64, 0x22, 0x4e, 0x0a, 0x0c, 0x53, 0x52, 0x42, + 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x49, 0x44, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x5f, 0x66, + 0x6c, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x46, 0x6c, 0x61, 0x67, + 0x12, 0x15, 0x0a, 0x06, 0x69, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x69, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x64, 0x22, 0xb3, 0x01, 0x0a, 0x14, 0x53, 0x52, + 0x76, 0x36, 0x45, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, + 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, + 0x36, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x08, 0x62, 0x65, 0x68, 0x61, 0x76, + 0x69, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6c, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x65, 0x6e, + 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4c, 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x66, + 0x75, 0x6e, 0x63, 0x5f, 0x6c, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, + 0x75, 0x6e, 0x63, 0x4c, 0x65, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x72, 0x67, 0x5f, 0x6c, 0x65, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x61, 0x72, 0x67, 0x4c, 0x65, 0x6e, 0x22, + 0xc4, 0x01, 0x0a, 0x0e, 0x53, 0x52, 0x76, 0x36, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, + 0x49, 0x44, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x73, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x5f, 0x66, + 0x6c, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x69, 0x46, 0x6c, 0x61, 0x67, + 0x12, 0x15, 0x0a, 0x06, 0x62, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x62, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x5b, 0x0a, 0x1b, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x5f, 0x73, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x45, 0x6e, 0x64, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x19, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x22, 0x54, 0x0a, 0x17, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, + 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x53, 0x52, 0x45, 0x4e, 0x4c, + 0x50, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x04, 0x65, 0x6e, 0x6c, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x4e, + 0x4c, 0x50, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x65, 0x6e, 0x6c, 0x70, 0x22, 0x38, 0x0a, 0x08, + 0x53, 0x52, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x6a, 0x0a, 0x0c, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x5f, 0x66, 0x6c, 0x61, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x15, 0x0a, + 0x06, 0x61, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, + 0x46, 0x6c, 0x61, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x62, + 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x62, 0x46, 0x6c, + 0x61, 0x67, 0x22, 0x4f, 0x0a, 0x0c, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x41, 0x12, 0x29, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x22, 0xa8, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x42, 0x12, 0x29, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, + 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, + 0x64, 0x12, 0x5b, 0x0a, 0x1b, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x65, + 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, + 0x52, 0x76, 0x36, 0x45, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, 0x61, 0x76, + 0x69, 0x6f, 0x72, 0x52, 0x19, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x65, 0x68, + 0x61, 0x76, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x22, 0x7b, + 0x0a, 0x1e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, + 0x54, 0x4c, 0x56, 0x53, 0x52, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x27, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x57, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x73, 0x65, 0x67, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, + 0x79, 0x52, 0x08, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3b, 0x0a, 0x1f, 0x54, + 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, + 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 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, 0x32, 0x0a, 0x1c, 0x54, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x55, 0x44, 0x50, + 0x44, 0x65, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x44, 0x0a, 0x18, + 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x53, 0x75, 0x62, 0x54, 0x4c, + 0x56, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x4e, 0x0a, 0x0e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, + 0x70, 0x54, 0x4c, 0x56, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x6c, 0x76, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x74, 0x6c, + 0x76, 0x73, 0x22, 0x41, 0x0a, 0x14, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, + 0x70, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x6c, + 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x6e, 0x63, 0x61, 0x70, 0x54, 0x4c, 0x56, 0x52, + 0x04, 0x74, 0x6c, 0x76, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x1b, 0x49, 0x50, 0x76, 0x36, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, + 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x75, + 0x62, 0x54, 0x79, 0x70, 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, 0x12, + 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x22, 0x60, 0x0a, 0x23, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x49, 0x50, 0x76, 0x36, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 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, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x22, 0x59, 0x0a, 0x1f, 0x49, 0x50, 0x36, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, + 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, + 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x2a, 0x0a, + 0x10, 0x41, 0x69, 0x67, 0x70, 0x54, 0x4c, 0x56, 0x49, 0x47, 0x50, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x3a, 0x0a, 0x0e, 0x41, 0x69, 0x67, + 0x70, 0x54, 0x4c, 0x56, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x39, 0x0a, 0x0d, 0x41, 0x69, 0x67, 0x70, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x6c, 0x76, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x74, 0x6c, 0x76, 0x73, + 0x22, 0x75, 0x0a, 0x0e, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x44, 0x61, 0x74, 0x61, 0x31, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x32, 0x22, 0x54, 0x0a, 0x19, 0x4c, 0x61, 0x72, 0x67, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x9b, 0x01, + 0x0a, 0x0b, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x0a, + 0x08, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, + 0x61, 0x63, 0x68, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x62, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, + 0x61, 0x62, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x76, + 0x36, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x76, 0x36, 0x22, 0x8b, 0x01, 0x0a, 0x0a, + 0x4c, 0x73, 0x49, 0x47, 0x50, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, + 0x77, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1d, + 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x55, 0x6e, 0x69, 0x63, 0x61, 0x73, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, 0x65, 0x5f, + 0x6e, 0x73, 0x73, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, + 0x61, 0x67, 0x61, 0x74, 0x65, 0x4e, 0x73, 0x73, 0x61, 0x22, 0x33, 0x0a, 0x09, 0x4c, 0x73, 0x53, + 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, + 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x8a, + 0x01, 0x0a, 0x10, 0x4c, 0x73, 0x53, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x70, 0x76, 0x34, 0x5f, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, 0x70, 0x76, + 0x34, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x70, + 0x76, 0x36, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x69, 0x70, 0x76, 0x36, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x12, 0x28, 0x0a, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x53, 0x72, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x0a, 0x0e, 0x4c, + 0x73, 0x53, 0x72, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x28, 0x0a, + 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x53, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x06, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xfd, 0x02, 0x0a, 0x0f, 0x4c, 0x73, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x28, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x76, 0x36, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x56, 0x36, 0x12, 0x1b, + 0x0a, 0x09, 0x69, 0x73, 0x69, 0x73, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x08, 0x69, 0x73, 0x69, 0x73, 0x41, 0x72, 0x65, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x6f, + 0x70, 0x61, 0x71, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x70, 0x61, + 0x71, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x73, 0x72, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x53, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0e, 0x73, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x72, 0x5f, 0x61, 0x6c, 0x67, 0x6f, + 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x72, + 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x12, 0x3b, 0x0a, 0x0e, 0x73, 0x72, + 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x53, 0x72, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x0c, 0x73, 0x72, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x9b, 0x04, 0x0a, 0x0f, 0x4c, 0x73, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x26, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x5f, 0x76, 0x36, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x49, 0x64, 0x56, 0x36, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2d, + 0x0a, 0x13, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x5f, 0x76, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x56, 0x36, 0x12, 0x1f, 0x0a, + 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2a, + 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x54, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x67, + 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, + 0x69, 0x67, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x70, 0x61, + 0x71, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x70, 0x61, 0x71, 0x75, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, + 0x31, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, + 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x52, 0x13, 0x72, + 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x12, 0x31, 0x0a, 0x14, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, + 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x02, + 0x52, 0x13, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x42, 0x61, 0x6e, 0x64, + 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x72, 0x5f, 0x61, 0x64, 0x6a, 0x61, + 0x63, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x73, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0e, 0x73, 0x72, 0x41, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x69, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x72, 0x6c, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x05, + 0x73, 0x72, 0x6c, 0x67, 0x73, 0x22, 0x7f, 0x0a, 0x11, 0x4c, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x2e, 0x0a, 0x09, 0x69, 0x67, + 0x70, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x49, 0x47, 0x50, 0x46, 0x6c, 0x61, 0x67, 0x73, + 0x52, 0x08, 0x69, 0x67, 0x70, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x70, + 0x61, 0x71, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6f, 0x70, 0x61, 0x71, + 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x72, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, + 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x72, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x53, 0x69, 0x64, 0x22, 0x97, 0x01, 0x0a, 0x0b, 0x4c, 0x73, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, + 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x30, + 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x22, 0x52, 0x0a, 0x10, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb2, 0x02, 0x0a, 0x16, 0x53, 0x52, 0x76, 0x36, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x62, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x12, + 0x30, 0x0a, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x6c, + 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x66, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x72, + 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x25, 0x0a, 0x0c, 0x53, 0x52, 0x76, + 0x36, 0x53, 0x49, 0x44, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x66, 0x6c, 0x61, + 0x67, 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x31, + 0x22, 0x31, 0x0a, 0x07, 0x53, 0x52, 0x76, 0x36, 0x54, 0x4c, 0x56, 0x12, 0x26, 0x0a, 0x03, 0x74, + 0x6c, 0x76, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x03, + 0x74, 0x6c, 0x76, 0x22, 0xa0, 0x02, 0x0a, 0x15, 0x53, 0x52, 0x76, 0x36, 0x49, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x12, 0x10, 0x0a, + 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, + 0x29, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x53, 0x49, 0x44, 0x46, 0x6c, + 0x61, 0x67, 0x73, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x4e, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x73, + 0x75, 0x62, 0x5f, 0x74, 0x6c, 0x76, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x75, 0x62, 0x54, 0x4c, 0x56, 0x2e, 0x53, 0x75, 0x62, 0x53, + 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x73, 0x75, 0x62, + 0x53, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x1a, 0x4d, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x53, 0x75, + 0x62, 0x54, 0x6c, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x54, 0x4c, 0x56, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9f, 0x01, 0x0a, 0x10, 0x53, 0x52, 0x76, 0x36, 0x4c, + 0x33, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x56, 0x12, 0x3f, 0x0a, 0x08, 0x73, + 0x75, 0x62, 0x5f, 0x74, 0x6c, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x4c, 0x33, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x54, 0x4c, 0x56, 0x2e, 0x53, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x1a, 0x4a, 0x0a, 0x0c, + 0x53, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x54, 0x4c, 0x56, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9f, 0x01, 0x0a, 0x10, 0x53, 0x52, 0x76, + 0x36, 0x4c, 0x32, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x56, 0x12, 0x3f, 0x0a, + 0x08, 0x73, 0x75, 0x62, 0x5f, 0x74, 0x6c, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x4c, 0x32, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x56, 0x2e, 0x53, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x1a, 0x4a, + 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x54, 0x6c, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x52, 0x76, 0x36, 0x54, 0x4c, 0x56, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x35, 0x0a, 0x09, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x53, 0x49, 0x44, 0x12, 0x28, 0x0a, 0x04, 0x74, 0x6c, 0x76, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x74, 0x6c, 0x76, + 0x73, 0x2a, 0xf7, 0x01, 0x0a, 0x0f, 0x4c, 0x73, 0x4f, 0x73, 0x70, 0x66, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x4c, 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, + 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, + 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x52, + 0x41, 0x5f, 0x41, 0x52, 0x45, 0x41, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x4c, 0x53, 0x5f, 0x4f, + 0x53, 0x50, 0x46, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, + 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x41, 0x52, 0x45, 0x41, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x4c, + 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x31, 0x10, 0x03, 0x12, 0x20, 0x0a, + 0x1c, 0x4c, 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x32, 0x10, 0x04, 0x12, + 0x1c, 0x0a, 0x18, 0x4c, 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x53, 0x53, 0x41, 0x31, 0x10, 0x05, 0x12, 0x1c, 0x0a, + 0x18, 0x4c, 0x53, 0x5f, 0x4f, 0x53, 0x50, 0x46, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x53, 0x53, 0x41, 0x32, 0x10, 0x06, 0x2a, 0x73, 0x0a, 0x0a, 0x4c, + 0x73, 0x4e, 0x4c, 0x52, 0x49, 0x54, 0x79, 0x70, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x53, 0x5f, + 0x4e, 0x4c, 0x52, 0x49, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, + 0x0a, 0x0c, 0x4c, 0x53, 0x5f, 0x4e, 0x4c, 0x52, 0x49, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x10, 0x01, + 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x53, 0x5f, 0x4e, 0x4c, 0x52, 0x49, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, + 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x53, 0x5f, 0x4e, 0x4c, 0x52, 0x49, 0x5f, 0x50, 0x52, + 0x45, 0x46, 0x49, 0x58, 0x5f, 0x56, 0x34, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x4c, 0x53, 0x5f, + 0x4e, 0x4c, 0x52, 0x49, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x5f, 0x56, 0x36, 0x10, 0x04, + 0x2a, 0xbb, 0x01, 0x0a, 0x0c, 0x4c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, + 0x44, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, + 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x53, + 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x49, 0x53, 0x49, 0x53, 0x5f, 0x4c, + 0x31, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, + 0x4f, 0x4c, 0x5f, 0x49, 0x53, 0x49, 0x53, 0x5f, 0x4c, 0x32, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, + 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4f, 0x53, 0x50, 0x46, + 0x5f, 0x56, 0x32, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, + 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x04, 0x12, 0x16, 0x0a, + 0x12, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x49, 0x43, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, + 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4f, 0x53, 0x50, 0x46, 0x5f, 0x56, 0x33, 0x10, 0x06, 0x2a, 0xed, + 0x05, 0x0a, 0x0c, 0x53, 0x52, 0x76, 0x36, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, + 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, + 0x03, 0x45, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, + 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x44, 0x5f, + 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, + 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x04, + 0x12, 0x08, 0x0a, 0x04, 0x45, 0x4e, 0x44, 0x58, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x4e, + 0x44, 0x58, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x10, 0x06, 0x12, 0x11, 0x0a, + 0x0d, 0x45, 0x4e, 0x44, 0x58, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x07, + 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x58, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, + 0x50, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x4e, 0x44, 0x54, 0x10, + 0x09, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, + 0x53, 0x50, 0x10, 0x0a, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, + 0x48, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x0b, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x54, 0x5f, + 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x10, 0x0c, 0x12, 0x11, + 0x0a, 0x0d, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x36, 0x5f, 0x45, 0x4e, 0x43, 0x41, 0x50, 0x53, 0x10, + 0x0e, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x4d, 0x10, 0x0f, 0x12, 0x0b, 0x0a, + 0x07, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x58, 0x36, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, + 0x44, 0x5f, 0x44, 0x58, 0x34, 0x10, 0x11, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x44, 0x5f, 0x44, + 0x54, 0x36, 0x10, 0x12, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x54, 0x34, 0x10, + 0x13, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x54, 0x34, 0x36, 0x10, 0x14, 0x12, + 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x58, 0x32, 0x10, 0x15, 0x12, 0x0c, 0x0a, 0x08, + 0x45, 0x4e, 0x44, 0x5f, 0x44, 0x58, 0x32, 0x56, 0x10, 0x16, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, + 0x44, 0x5f, 0x44, 0x54, 0x32, 0x55, 0x10, 0x17, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x4e, 0x44, 0x5f, + 0x44, 0x54, 0x32, 0x4d, 0x10, 0x18, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x36, + 0x5f, 0x45, 0x4e, 0x43, 0x41, 0x50, 0x53, 0x5f, 0x52, 0x65, 0x64, 0x10, 0x1b, 0x12, 0x10, 0x0a, + 0x0c, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x1c, 0x12, + 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, + 0x55, 0x53, 0x44, 0x10, 0x1d, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, + 0x48, 0x5f, 0x55, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x1e, 0x12, 0x18, 0x0a, 0x14, 0x45, + 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x5f, + 0x55, 0x53, 0x44, 0x10, 0x1f, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x4e, 0x44, 0x58, 0x5f, 0x57, 0x49, + 0x54, 0x48, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x20, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x58, + 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x21, 0x12, + 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x58, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x50, + 0x5f, 0x55, 0x53, 0x44, 0x10, 0x22, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x4e, 0x44, 0x58, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, + 0x23, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, + 0x53, 0x44, 0x10, 0x24, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, + 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x25, 0x12, 0x15, 0x0a, 0x11, 0x45, + 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, + 0x10, 0x26, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, + 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x27, 0x12, 0x0e, 0x0a, + 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, 0x50, 0x36, 0x44, 0x10, 0x45, 0x12, 0x0f, 0x0a, + 0x0b, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, 0x50, 0x36, 0x44, 0x49, 0x10, 0x46, 0x12, 0x0e, + 0x0a, 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, 0x50, 0x36, 0x45, 0x10, 0x47, 0x12, 0x0e, + 0x0a, 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, 0x50, 0x34, 0x45, 0x10, 0x48, 0x2a, 0x44, + 0x0a, 0x08, 0x45, 0x4e, 0x4c, 0x50, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, + 0x31, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x32, 0x10, 0x02, 0x12, 0x09, + 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x33, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, + 0x65, 0x34, 0x10, 0x04, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x6f, 0x73, 0x72, 0x67, 0x2f, 0x67, 0x6f, 0x62, 0x67, 0x70, 0x2f, 0x76, 0x33, + 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_attribute_proto_rawDescOnce sync.Once + file_attribute_proto_rawDescData = file_attribute_proto_rawDesc +) + +func file_attribute_proto_rawDescGZIP() []byte { + file_attribute_proto_rawDescOnce.Do(func() { + file_attribute_proto_rawDescData = protoimpl.X.CompressGZIP(file_attribute_proto_rawDescData) + }) + return file_attribute_proto_rawDescData +} + +var file_attribute_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_attribute_proto_msgTypes = make([]protoimpl.MessageInfo, 122) +var file_attribute_proto_goTypes = []interface{}{ + (LsOspfRouteType)(0), // 0: apipb.LsOspfRouteType + (LsNLRIType)(0), // 1: apipb.LsNLRIType + (LsProtocolID)(0), // 2: apipb.LsProtocolID + (SRv6Behavior)(0), // 3: apipb.SRv6Behavior + (ENLPType)(0), // 4: apipb.ENLPType + (AsSegment_Type)(0), // 5: apipb.AsSegment.Type + (*OriginAttribute)(nil), // 6: apipb.OriginAttribute + (*AsSegment)(nil), // 7: apipb.AsSegment + (*AsPathAttribute)(nil), // 8: apipb.AsPathAttribute + (*NextHopAttribute)(nil), // 9: apipb.NextHopAttribute + (*MultiExitDiscAttribute)(nil), // 10: apipb.MultiExitDiscAttribute + (*LocalPrefAttribute)(nil), // 11: apipb.LocalPrefAttribute + (*AtomicAggregateAttribute)(nil), // 12: apipb.AtomicAggregateAttribute + (*AggregatorAttribute)(nil), // 13: apipb.AggregatorAttribute + (*CommunitiesAttribute)(nil), // 14: apipb.CommunitiesAttribute + (*OriginatorIdAttribute)(nil), // 15: apipb.OriginatorIdAttribute + (*ClusterListAttribute)(nil), // 16: apipb.ClusterListAttribute + (*IPAddressPrefix)(nil), // 17: apipb.IPAddressPrefix + (*LabeledIPAddressPrefix)(nil), // 18: apipb.LabeledIPAddressPrefix + (*EncapsulationNLRI)(nil), // 19: apipb.EncapsulationNLRI + (*RouteDistinguisherTwoOctetASN)(nil), // 20: apipb.RouteDistinguisherTwoOctetASN + (*RouteDistinguisherIPAddress)(nil), // 21: apipb.RouteDistinguisherIPAddress + (*RouteDistinguisherFourOctetASN)(nil), // 22: apipb.RouteDistinguisherFourOctetASN + (*EthernetSegmentIdentifier)(nil), // 23: apipb.EthernetSegmentIdentifier + (*EVPNEthernetAutoDiscoveryRoute)(nil), // 24: apipb.EVPNEthernetAutoDiscoveryRoute + (*EVPNMACIPAdvertisementRoute)(nil), // 25: apipb.EVPNMACIPAdvertisementRoute + (*EVPNInclusiveMulticastEthernetTagRoute)(nil), // 26: apipb.EVPNInclusiveMulticastEthernetTagRoute + (*EVPNEthernetSegmentRoute)(nil), // 27: apipb.EVPNEthernetSegmentRoute + (*EVPNIPPrefixRoute)(nil), // 28: apipb.EVPNIPPrefixRoute + (*EVPNIPMSIRoute)(nil), // 29: apipb.EVPNIPMSIRoute + (*SRPolicyNLRI)(nil), // 30: apipb.SRPolicyNLRI + (*LabeledVPNIPAddressPrefix)(nil), // 31: apipb.LabeledVPNIPAddressPrefix + (*RouteTargetMembershipNLRI)(nil), // 32: apipb.RouteTargetMembershipNLRI + (*FlowSpecIPPrefix)(nil), // 33: apipb.FlowSpecIPPrefix + (*FlowSpecMAC)(nil), // 34: apipb.FlowSpecMAC + (*FlowSpecComponentItem)(nil), // 35: apipb.FlowSpecComponentItem + (*FlowSpecComponent)(nil), // 36: apipb.FlowSpecComponent + (*FlowSpecNLRI)(nil), // 37: apipb.FlowSpecNLRI + (*VPNFlowSpecNLRI)(nil), // 38: apipb.VPNFlowSpecNLRI + (*OpaqueNLRI)(nil), // 39: apipb.OpaqueNLRI + (*LsNodeDescriptor)(nil), // 40: apipb.LsNodeDescriptor + (*LsLinkDescriptor)(nil), // 41: apipb.LsLinkDescriptor + (*LsPrefixDescriptor)(nil), // 42: apipb.LsPrefixDescriptor + (*LsNodeNLRI)(nil), // 43: apipb.LsNodeNLRI + (*LsLinkNLRI)(nil), // 44: apipb.LsLinkNLRI + (*LsPrefixV4NLRI)(nil), // 45: apipb.LsPrefixV4NLRI + (*LsPrefixV6NLRI)(nil), // 46: apipb.LsPrefixV6NLRI + (*LsAddrPrefix)(nil), // 47: apipb.LsAddrPrefix + (*MUPInterworkSegmentDiscoveryRoute)(nil), // 48: apipb.MUPInterworkSegmentDiscoveryRoute + (*MUPDirectSegmentDiscoveryRoute)(nil), // 49: apipb.MUPDirectSegmentDiscoveryRoute + (*MUPType1SessionTransformedRoute)(nil), // 50: apipb.MUPType1SessionTransformedRoute + (*MUPType2SessionTransformedRoute)(nil), // 51: apipb.MUPType2SessionTransformedRoute + (*MpReachNLRIAttribute)(nil), // 52: apipb.MpReachNLRIAttribute + (*MpUnreachNLRIAttribute)(nil), // 53: apipb.MpUnreachNLRIAttribute + (*TwoOctetAsSpecificExtended)(nil), // 54: apipb.TwoOctetAsSpecificExtended + (*IPv4AddressSpecificExtended)(nil), // 55: apipb.IPv4AddressSpecificExtended + (*FourOctetAsSpecificExtended)(nil), // 56: apipb.FourOctetAsSpecificExtended + (*LinkBandwidthExtended)(nil), // 57: apipb.LinkBandwidthExtended + (*ValidationExtended)(nil), // 58: apipb.ValidationExtended + (*ColorExtended)(nil), // 59: apipb.ColorExtended + (*EncapExtended)(nil), // 60: apipb.EncapExtended + (*DefaultGatewayExtended)(nil), // 61: apipb.DefaultGatewayExtended + (*OpaqueExtended)(nil), // 62: apipb.OpaqueExtended + (*ESILabelExtended)(nil), // 63: apipb.ESILabelExtended + (*ESImportRouteTarget)(nil), // 64: apipb.ESImportRouteTarget + (*MacMobilityExtended)(nil), // 65: apipb.MacMobilityExtended + (*RouterMacExtended)(nil), // 66: apipb.RouterMacExtended + (*TrafficRateExtended)(nil), // 67: apipb.TrafficRateExtended + (*TrafficActionExtended)(nil), // 68: apipb.TrafficActionExtended + (*RedirectTwoOctetAsSpecificExtended)(nil), // 69: apipb.RedirectTwoOctetAsSpecificExtended + (*RedirectIPv4AddressSpecificExtended)(nil), // 70: apipb.RedirectIPv4AddressSpecificExtended + (*RedirectFourOctetAsSpecificExtended)(nil), // 71: apipb.RedirectFourOctetAsSpecificExtended + (*TrafficRemarkExtended)(nil), // 72: apipb.TrafficRemarkExtended + (*MUPExtended)(nil), // 73: apipb.MUPExtended + (*UnknownExtended)(nil), // 74: apipb.UnknownExtended + (*ExtendedCommunitiesAttribute)(nil), // 75: apipb.ExtendedCommunitiesAttribute + (*As4PathAttribute)(nil), // 76: apipb.As4PathAttribute + (*As4AggregatorAttribute)(nil), // 77: apipb.As4AggregatorAttribute + (*PmsiTunnelAttribute)(nil), // 78: apipb.PmsiTunnelAttribute + (*TunnelEncapSubTLVEncapsulation)(nil), // 79: apipb.TunnelEncapSubTLVEncapsulation + (*TunnelEncapSubTLVProtocol)(nil), // 80: apipb.TunnelEncapSubTLVProtocol + (*TunnelEncapSubTLVColor)(nil), // 81: apipb.TunnelEncapSubTLVColor + (*TunnelEncapSubTLVSRPreference)(nil), // 82: apipb.TunnelEncapSubTLVSRPreference + (*TunnelEncapSubTLVSRCandidatePathName)(nil), // 83: apipb.TunnelEncapSubTLVSRCandidatePathName + (*TunnelEncapSubTLVSRPriority)(nil), // 84: apipb.TunnelEncapSubTLVSRPriority + (*TunnelEncapSubTLVSRBindingSID)(nil), // 85: apipb.TunnelEncapSubTLVSRBindingSID + (*SRBindingSID)(nil), // 86: apipb.SRBindingSID + (*SRv6EndPointBehavior)(nil), // 87: apipb.SRv6EndPointBehavior + (*SRv6BindingSID)(nil), // 88: apipb.SRv6BindingSID + (*TunnelEncapSubTLVSRENLP)(nil), // 89: apipb.TunnelEncapSubTLVSRENLP + (*SRWeight)(nil), // 90: apipb.SRWeight + (*SegmentFlags)(nil), // 91: apipb.SegmentFlags + (*SegmentTypeA)(nil), // 92: apipb.SegmentTypeA + (*SegmentTypeB)(nil), // 93: apipb.SegmentTypeB + (*TunnelEncapSubTLVSRSegmentList)(nil), // 94: apipb.TunnelEncapSubTLVSRSegmentList + (*TunnelEncapSubTLVEgressEndpoint)(nil), // 95: apipb.TunnelEncapSubTLVEgressEndpoint + (*TunnelEncapSubTLVUDPDestPort)(nil), // 96: apipb.TunnelEncapSubTLVUDPDestPort + (*TunnelEncapSubTLVUnknown)(nil), // 97: apipb.TunnelEncapSubTLVUnknown + (*TunnelEncapTLV)(nil), // 98: apipb.TunnelEncapTLV + (*TunnelEncapAttribute)(nil), // 99: apipb.TunnelEncapAttribute + (*IPv6AddressSpecificExtended)(nil), // 100: apipb.IPv6AddressSpecificExtended + (*RedirectIPv6AddressSpecificExtended)(nil), // 101: apipb.RedirectIPv6AddressSpecificExtended + (*IP6ExtendedCommunitiesAttribute)(nil), // 102: apipb.IP6ExtendedCommunitiesAttribute + (*AigpTLVIGPMetric)(nil), // 103: apipb.AigpTLVIGPMetric + (*AigpTLVUnknown)(nil), // 104: apipb.AigpTLVUnknown + (*AigpAttribute)(nil), // 105: apipb.AigpAttribute + (*LargeCommunity)(nil), // 106: apipb.LargeCommunity + (*LargeCommunitiesAttribute)(nil), // 107: apipb.LargeCommunitiesAttribute + (*LsNodeFlags)(nil), // 108: apipb.LsNodeFlags + (*LsIGPFlags)(nil), // 109: apipb.LsIGPFlags + (*LsSrRange)(nil), // 110: apipb.LsSrRange + (*LsSrCapabilities)(nil), // 111: apipb.LsSrCapabilities + (*LsSrLocalBlock)(nil), // 112: apipb.LsSrLocalBlock + (*LsAttributeNode)(nil), // 113: apipb.LsAttributeNode + (*LsAttributeLink)(nil), // 114: apipb.LsAttributeLink + (*LsAttributePrefix)(nil), // 115: apipb.LsAttributePrefix + (*LsAttribute)(nil), // 116: apipb.LsAttribute + (*UnknownAttribute)(nil), // 117: apipb.UnknownAttribute + (*SRv6StructureSubSubTLV)(nil), // 118: apipb.SRv6StructureSubSubTLV + (*SRv6SIDFlags)(nil), // 119: apipb.SRv6SIDFlags + (*SRv6TLV)(nil), // 120: apipb.SRv6TLV + (*SRv6InformationSubTLV)(nil), // 121: apipb.SRv6InformationSubTLV + (*SRv6L3ServiceTLV)(nil), // 122: apipb.SRv6L3ServiceTLV + (*SRv6L2ServiceTLV)(nil), // 123: apipb.SRv6L2ServiceTLV + (*PrefixSID)(nil), // 124: apipb.PrefixSID + nil, // 125: apipb.SRv6InformationSubTLV.SubSubTlvsEntry + nil, // 126: apipb.SRv6L3ServiceTLV.SubTlvsEntry + nil, // 127: apipb.SRv6L2ServiceTLV.SubTlvsEntry + (*anypb.Any)(nil), // 128: google.protobuf.Any + (*Family)(nil), // 129: apipb.Family +} +var file_attribute_proto_depIdxs = []int32{ + 5, // 0: apipb.AsSegment.type:type_name -> apipb.AsSegment.Type + 7, // 1: apipb.AsPathAttribute.segments:type_name -> apipb.AsSegment + 128, // 2: apipb.EVPNEthernetAutoDiscoveryRoute.rd:type_name -> google.protobuf.Any + 23, // 3: apipb.EVPNEthernetAutoDiscoveryRoute.esi:type_name -> apipb.EthernetSegmentIdentifier + 128, // 4: apipb.EVPNMACIPAdvertisementRoute.rd:type_name -> google.protobuf.Any + 23, // 5: apipb.EVPNMACIPAdvertisementRoute.esi:type_name -> apipb.EthernetSegmentIdentifier + 128, // 6: apipb.EVPNInclusiveMulticastEthernetTagRoute.rd:type_name -> google.protobuf.Any + 128, // 7: apipb.EVPNEthernetSegmentRoute.rd:type_name -> google.protobuf.Any + 23, // 8: apipb.EVPNEthernetSegmentRoute.esi:type_name -> apipb.EthernetSegmentIdentifier + 128, // 9: apipb.EVPNIPPrefixRoute.rd:type_name -> google.protobuf.Any + 23, // 10: apipb.EVPNIPPrefixRoute.esi:type_name -> apipb.EthernetSegmentIdentifier + 128, // 11: apipb.EVPNIPMSIRoute.rd:type_name -> google.protobuf.Any + 128, // 12: apipb.EVPNIPMSIRoute.rt:type_name -> google.protobuf.Any + 128, // 13: apipb.LabeledVPNIPAddressPrefix.rd:type_name -> google.protobuf.Any + 128, // 14: apipb.RouteTargetMembershipNLRI.rt:type_name -> google.protobuf.Any + 35, // 15: apipb.FlowSpecComponent.items:type_name -> apipb.FlowSpecComponentItem + 128, // 16: apipb.FlowSpecNLRI.rules:type_name -> google.protobuf.Any + 128, // 17: apipb.VPNFlowSpecNLRI.rd:type_name -> google.protobuf.Any + 128, // 18: apipb.VPNFlowSpecNLRI.rules:type_name -> google.protobuf.Any + 0, // 19: apipb.LsPrefixDescriptor.ospf_route_type:type_name -> apipb.LsOspfRouteType + 40, // 20: apipb.LsNodeNLRI.local_node:type_name -> apipb.LsNodeDescriptor + 40, // 21: apipb.LsLinkNLRI.local_node:type_name -> apipb.LsNodeDescriptor + 40, // 22: apipb.LsLinkNLRI.remote_node:type_name -> apipb.LsNodeDescriptor + 41, // 23: apipb.LsLinkNLRI.link_descriptor:type_name -> apipb.LsLinkDescriptor + 40, // 24: apipb.LsPrefixV4NLRI.local_node:type_name -> apipb.LsNodeDescriptor + 42, // 25: apipb.LsPrefixV4NLRI.prefix_descriptor:type_name -> apipb.LsPrefixDescriptor + 40, // 26: apipb.LsPrefixV6NLRI.local_node:type_name -> apipb.LsNodeDescriptor + 42, // 27: apipb.LsPrefixV6NLRI.prefix_descriptor:type_name -> apipb.LsPrefixDescriptor + 1, // 28: apipb.LsAddrPrefix.type:type_name -> apipb.LsNLRIType + 128, // 29: apipb.LsAddrPrefix.nlri:type_name -> google.protobuf.Any + 2, // 30: apipb.LsAddrPrefix.protocol_id:type_name -> apipb.LsProtocolID + 128, // 31: apipb.MUPInterworkSegmentDiscoveryRoute.rd:type_name -> google.protobuf.Any + 128, // 32: apipb.MUPDirectSegmentDiscoveryRoute.rd:type_name -> google.protobuf.Any + 128, // 33: apipb.MUPType1SessionTransformedRoute.rd:type_name -> google.protobuf.Any + 128, // 34: apipb.MUPType2SessionTransformedRoute.rd:type_name -> google.protobuf.Any + 129, // 35: apipb.MpReachNLRIAttribute.family:type_name -> apipb.Family + 128, // 36: apipb.MpReachNLRIAttribute.nlris:type_name -> google.protobuf.Any + 129, // 37: apipb.MpUnreachNLRIAttribute.family:type_name -> apipb.Family + 128, // 38: apipb.MpUnreachNLRIAttribute.nlris:type_name -> google.protobuf.Any + 128, // 39: apipb.ExtendedCommunitiesAttribute.communities:type_name -> google.protobuf.Any + 7, // 40: apipb.As4PathAttribute.segments:type_name -> apipb.AsSegment + 128, // 41: apipb.TunnelEncapSubTLVSRBindingSID.bsid:type_name -> google.protobuf.Any + 3, // 42: apipb.SRv6EndPointBehavior.behavior:type_name -> apipb.SRv6Behavior + 87, // 43: apipb.SRv6BindingSID.endpoint_behavior_structure:type_name -> apipb.SRv6EndPointBehavior + 4, // 44: apipb.TunnelEncapSubTLVSRENLP.enlp:type_name -> apipb.ENLPType + 91, // 45: apipb.SegmentTypeA.flags:type_name -> apipb.SegmentFlags + 91, // 46: apipb.SegmentTypeB.flags:type_name -> apipb.SegmentFlags + 87, // 47: apipb.SegmentTypeB.endpoint_behavior_structure:type_name -> apipb.SRv6EndPointBehavior + 90, // 48: apipb.TunnelEncapSubTLVSRSegmentList.weight:type_name -> apipb.SRWeight + 128, // 49: apipb.TunnelEncapSubTLVSRSegmentList.segments:type_name -> google.protobuf.Any + 128, // 50: apipb.TunnelEncapTLV.tlvs:type_name -> google.protobuf.Any + 98, // 51: apipb.TunnelEncapAttribute.tlvs:type_name -> apipb.TunnelEncapTLV + 128, // 52: apipb.IP6ExtendedCommunitiesAttribute.communities:type_name -> google.protobuf.Any + 128, // 53: apipb.AigpAttribute.tlvs:type_name -> google.protobuf.Any + 106, // 54: apipb.LargeCommunitiesAttribute.communities:type_name -> apipb.LargeCommunity + 110, // 55: apipb.LsSrCapabilities.ranges:type_name -> apipb.LsSrRange + 110, // 56: apipb.LsSrLocalBlock.ranges:type_name -> apipb.LsSrRange + 108, // 57: apipb.LsAttributeNode.flags:type_name -> apipb.LsNodeFlags + 111, // 58: apipb.LsAttributeNode.sr_capabilities:type_name -> apipb.LsSrCapabilities + 112, // 59: apipb.LsAttributeNode.sr_local_block:type_name -> apipb.LsSrLocalBlock + 109, // 60: apipb.LsAttributePrefix.igp_flags:type_name -> apipb.LsIGPFlags + 113, // 61: apipb.LsAttribute.node:type_name -> apipb.LsAttributeNode + 114, // 62: apipb.LsAttribute.link:type_name -> apipb.LsAttributeLink + 115, // 63: apipb.LsAttribute.prefix:type_name -> apipb.LsAttributePrefix + 128, // 64: apipb.SRv6TLV.tlv:type_name -> google.protobuf.Any + 119, // 65: apipb.SRv6InformationSubTLV.flags:type_name -> apipb.SRv6SIDFlags + 125, // 66: apipb.SRv6InformationSubTLV.sub_sub_tlvs:type_name -> apipb.SRv6InformationSubTLV.SubSubTlvsEntry + 126, // 67: apipb.SRv6L3ServiceTLV.sub_tlvs:type_name -> apipb.SRv6L3ServiceTLV.SubTlvsEntry + 127, // 68: apipb.SRv6L2ServiceTLV.sub_tlvs:type_name -> apipb.SRv6L2ServiceTLV.SubTlvsEntry + 128, // 69: apipb.PrefixSID.tlvs:type_name -> google.protobuf.Any + 120, // 70: apipb.SRv6InformationSubTLV.SubSubTlvsEntry.value:type_name -> apipb.SRv6TLV + 120, // 71: apipb.SRv6L3ServiceTLV.SubTlvsEntry.value:type_name -> apipb.SRv6TLV + 120, // 72: apipb.SRv6L2ServiceTLV.SubTlvsEntry.value:type_name -> apipb.SRv6TLV + 73, // [73:73] is the sub-list for method output_type + 73, // [73:73] is the sub-list for method input_type + 73, // [73:73] is the sub-list for extension type_name + 73, // [73:73] is the sub-list for extension extendee + 0, // [0:73] is the sub-list for field type_name +} + +func init() { file_attribute_proto_init() } +func file_attribute_proto_init() { + if File_attribute_proto != nil { + return + } + file_gobgp_proto_init() + if !protoimpl.UnsafeEnabled { + file_attribute_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OriginAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AsSegment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AsPathAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NextHopAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MultiExitDiscAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalPrefAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AtomicAggregateAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AggregatorAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommunitiesAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OriginatorIdAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClusterListAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IPAddressPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LabeledIPAddressPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EncapsulationNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteDistinguisherTwoOctetASN); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteDistinguisherIPAddress); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteDistinguisherFourOctetASN); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EthernetSegmentIdentifier); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNEthernetAutoDiscoveryRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNMACIPAdvertisementRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNInclusiveMulticastEthernetTagRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNEthernetSegmentRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNIPPrefixRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EVPNIPMSIRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRPolicyNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LabeledVPNIPAddressPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteTargetMembershipNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlowSpecIPPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlowSpecMAC); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlowSpecComponentItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlowSpecComponent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FlowSpecNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VPNFlowSpecNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OpaqueNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsNodeDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsLinkDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsPrefixDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsNodeNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsLinkNLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsPrefixV4NLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsPrefixV6NLRI); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsAddrPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MUPInterworkSegmentDiscoveryRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MUPDirectSegmentDiscoveryRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MUPType1SessionTransformedRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MUPType2SessionTransformedRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MpReachNLRIAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MpUnreachNLRIAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TwoOctetAsSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IPv4AddressSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FourOctetAsSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LinkBandwidthExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ValidationExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ColorExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EncapExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DefaultGatewayExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OpaqueExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ESILabelExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ESImportRouteTarget); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MacMobilityExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouterMacExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TrafficRateExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TrafficActionExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RedirectTwoOctetAsSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RedirectIPv4AddressSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RedirectFourOctetAsSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TrafficRemarkExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MUPExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnknownExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtendedCommunitiesAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*As4PathAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*As4AggregatorAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PmsiTunnelAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVEncapsulation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVProtocol); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVColor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRPreference); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRCandidatePathName); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRPriority); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRBindingSID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRBindingSID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6EndPointBehavior); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6BindingSID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRENLP); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRWeight); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SegmentFlags); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SegmentTypeA); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SegmentTypeB); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVSRSegmentList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVEgressEndpoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVUDPDestPort); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapSubTLVUnknown); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapTLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TunnelEncapAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IPv6AddressSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RedirectIPv6AddressSpecificExtended); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IP6ExtendedCommunitiesAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AigpTLVIGPMetric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AigpTLVUnknown); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AigpAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LargeCommunity); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LargeCommunitiesAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsNodeFlags); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsIGPFlags); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsSrRange); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsSrCapabilities); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsSrLocalBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsAttributeNode); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsAttributeLink); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[109].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsAttributePrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LsAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnknownAttribute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6StructureSubSubTLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[113].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6SIDFlags); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6TLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6InformationSubTLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[116].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6L3ServiceTLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[117].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SRv6L2ServiceTLV); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attribute_proto_msgTypes[118].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PrefixSID); 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_attribute_proto_rawDesc, + NumEnums: 6, + NumMessages: 122, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_attribute_proto_goTypes, + DependencyIndexes: file_attribute_proto_depIdxs, + EnumInfos: file_attribute_proto_enumTypes, + MessageInfos: file_attribute_proto_msgTypes, + }.Build() + File_attribute_proto = out.File + file_attribute_proto_rawDesc = nil + file_attribute_proto_goTypes = nil + file_attribute_proto_depIdxs = nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/attribute.proto b/vendor/github.com/osrg/gobgp/v3/api/attribute.proto new file mode 100644 index 000000000..cc60a1633 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/attribute.proto @@ -0,0 +1,892 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +syntax = "proto3"; + +package apipb; +option go_package = "github.com/osrg/gobgp/v3/api;apipb"; + +import "google/protobuf/any.proto"; +import "gobgp.proto"; + + +message OriginAttribute { uint32 origin = 1; } + +message AsSegment { + enum Type { + UNKNOWN = 0; AS_SET = 1; AS_SEQUENCE = 2; + AS_CONFED_SEQUENCE = 3; AS_CONFED_SET = 4; + } + Type type = 1; + repeated uint32 numbers = 2; +} + +message AsPathAttribute { repeated AsSegment segments = 1; } + +message NextHopAttribute { string next_hop = 1; } + +message MultiExitDiscAttribute { uint32 med = 1; } + +message LocalPrefAttribute { uint32 local_pref = 1; } + +message AtomicAggregateAttribute {} + +message AggregatorAttribute { + uint32 asn = 1; + string address = 2; +} + +message CommunitiesAttribute { repeated uint32 communities = 1; } + +message OriginatorIdAttribute { string id = 1; } + +message ClusterListAttribute { repeated string ids = 1; } + +// IPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=1 +// - AFI=2, SAFI=1 +message IPAddressPrefix { + uint32 prefix_len = 1; + string prefix = 2; +} + +// LabeledIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=4 +// - AFI=2, SAFI=4 +message LabeledIPAddressPrefix { + repeated uint32 labels = 1; + uint32 prefix_len = 2; + string prefix = 3; +} + +// EncapsulationNLRI represents the NLRI for: +// - AFI=1, SAFI=7 +// - AFI=2, SAFI=7 +message EncapsulationNLRI { string address = 1; } + +message RouteDistinguisherTwoOctetASN { + uint32 admin = 1; + uint32 assigned = 2; +} + +message RouteDistinguisherIPAddress { + string admin = 1; + uint32 assigned = 2; +} + +message RouteDistinguisherFourOctetASN { + uint32 admin = 1; + uint32 assigned = 2; +} + +message EthernetSegmentIdentifier { + uint32 type = 1; + bytes value = 2; +} + +// EVPNEthernetAutoDiscoveryRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=1 +message EVPNEthernetAutoDiscoveryRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + EthernetSegmentIdentifier esi = 2; + uint32 ethernet_tag = 3; + uint32 label = 4; +} + +// EVPNMACIPAdvertisementRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=2 +message EVPNMACIPAdvertisementRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + EthernetSegmentIdentifier esi = 2; + uint32 ethernet_tag = 3; + string mac_address = 4; + string ip_address = 5; + repeated uint32 labels = 6; +} + +// EVPNInclusiveMulticastEthernetTagRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=3 +message EVPNInclusiveMulticastEthernetTagRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + uint32 ethernet_tag = 2; + string ip_address = 3; +} + +// EVPNEthernetSegmentRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=4 +message EVPNEthernetSegmentRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + EthernetSegmentIdentifier esi = 2; + string ip_address = 3; +} + +// EVPNIPPrefixRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=5 +message EVPNIPPrefixRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + EthernetSegmentIdentifier esi = 2; + uint32 ethernet_tag = 3; + string ip_prefix = 4; + uint32 ip_prefix_len = 5; + string gw_address = 6; + uint32 label = 7; +} + +// EVPNIPMSIRoute represents the NLRI for: +// - AFI=25, SAFI=70, RouteType=9 +message EVPNIPMSIRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + uint32 ethernet_tag = 2; + google.protobuf.Any rt = 3; +} + +// SRPolicyNLRI represents the NLRI for: +// - AFI=1, SAFI=73 +// - AFI=2, SAFI=73 +message SRPolicyNLRI { + // length field carries the length of NLRI portion expressed in bits + uint32 length = 1; + // distinguisher field carries 4-octet value uniquely identifying the policy + // in the context of tuple. + uint32 distinguisher = 2; + // color field carries 4-octet value identifying (with the endpoint) the + // policy. The color is used to match the color of the destination + // prefixes to steer traffic into the SR Policy + uint32 color = 3; + // endpoint field identifies the endpoint of a policy. The Endpoint may + // represent a single node or a set of nodes (e.g., an anycast + // address). The Endpoint is an IPv4 (4-octet) address or an IPv6 + // (16-octet) address according to the AFI of the NLRI. + bytes endpoint = 4; +} + +// LabeledVPNIPAddressPrefix represents the NLRI for: +// - AFI=1, SAFI=128 +// - AFI=2, SAFI=128 +message LabeledVPNIPAddressPrefix { + repeated uint32 labels = 1; + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + google.protobuf.Any rd = 2; + uint32 prefix_len = 3; + string prefix = 4; +} + +// RouteTargetMembershipNLRI represents the NLRI for: +// - AFI=1, SAFI=132 +message RouteTargetMembershipNLRI { + uint32 asn = 1; + // One of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + google.protobuf.Any rt = 2; +} + +message FlowSpecIPPrefix { + uint32 type = 1; + uint32 prefix_len = 2; + string prefix = 3; + // IPv6 only + uint32 offset = 4; +} + +message FlowSpecMAC { + uint32 type = 1; + string address = 2; +} + +message FlowSpecComponentItem { + // Operator for Numeric type, Operand for Bitmask type + uint32 op = 1; + uint64 value = 2; +} + +message FlowSpecComponent { + uint32 type = 1; + repeated FlowSpecComponentItem items = 2; +} + +// FlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=133 +// - AFI=2, SAFI=133 +message FlowSpecNLRI { + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + repeated google.protobuf.Any rules = 1; +} + +// VPNFlowSpecNLRI represents the NLRI for: +// - AFI=1, SAFI=134 +// - AFI=2, SAFI=134 +// - AFI=25, SAFI=134 +message VPNFlowSpecNLRI { + // One of: + // - RouteDistinguisherTwoOctetAS + // - RouteDistinguisherIPAddressAS + // - RouteDistinguisherFourOctetAS + google.protobuf.Any rd = 1; + // One of: + // - FlowSpecIPPrefix + // - FlowSpecMAC + // - FlowSpecComponent + repeated google.protobuf.Any rules = 2; +} + +// OpaqueNLRI represents the NLRI for: +// - AFI=16397, SAFI=241 +message OpaqueNLRI { + bytes key = 1; + bytes value = 2; +} + +message LsNodeDescriptor { + uint32 asn = 1; + uint32 bgp_ls_id = 2; + uint32 ospf_area_id = 3; + bool pseudonode = 4; + string igp_router_id = 5; +} + +message LsLinkDescriptor { + uint32 link_local_id = 1; + uint32 link_remote_id = 2; + string interface_addr_ipv4 = 3; + string neighbor_addr_ipv4 = 4; + string interface_addr_ipv6 = 5; + string neighbor_addr_ipv6 = 6; +} + +enum LsOspfRouteType { + LS_OSPF_ROUTE_TYPE_UNKNOWN = 0; + LS_OSPF_ROUTE_TYPE_INTRA_AREA = 1; + LS_OSPF_ROUTE_TYPE_INTER_AREA = 2; + LS_OSPF_ROUTE_TYPE_EXTERNAL1 = 3; + LS_OSPF_ROUTE_TYPE_EXTERNAL2 = 4; + LS_OSPF_ROUTE_TYPE_NSSA1 = 5; + LS_OSPF_ROUTE_TYPE_NSSA2 = 6; +} + +message LsPrefixDescriptor { + repeated string ip_reachability = 1; + LsOspfRouteType ospf_route_type = 2; +} + +message LsNodeNLRI { LsNodeDescriptor local_node = 1; } + +message LsLinkNLRI { + LsNodeDescriptor local_node = 1; + LsNodeDescriptor remote_node = 2; + LsLinkDescriptor link_descriptor = 3; +} + +message LsPrefixV4NLRI { + LsNodeDescriptor local_node = 1; + LsPrefixDescriptor prefix_descriptor = 2; +} + +message LsPrefixV6NLRI { + LsNodeDescriptor local_node = 1; + LsPrefixDescriptor prefix_descriptor = 2; +} + +// Based om RFC 7752, Table 1. +enum LsNLRIType { + LS_NLRI_UNKNOWN = 0; LS_NLRI_NODE = 1; LS_NLRI_LINK = 2; + LS_NLRI_PREFIX_V4 = 3; + LS_NLRI_PREFIX_V6 = 4; +} + +enum LsProtocolID { + LS_PROTOCOL_UNKNOWN = 0; LS_PROTOCOL_ISIS_L1 = 1; LS_PROTOCOL_ISIS_L2 = 2; + LS_PROTOCOL_OSPF_V2 = 3; + LS_PROTOCOL_DIRECT = 4; + LS_PROTOCOL_STATIC = 5; + LS_PROTOCOL_OSPF_V3 = 6; +} + +// LsAddrPrefix represents the NLRI for: +// - AFI=16388, SAFI=71 +message LsAddrPrefix { + LsNLRIType type = 1; + // One of: + // - LsNodeNLRI + // - LsLinkNLRI + // - LsPrefixV4NLRI + // - LsPrefixV6NLRI + google.protobuf.Any nlri = 2; + uint32 length = 3; + LsProtocolID protocol_id = 4; + uint64 identifier = 5; +} + +message MUPInterworkSegmentDiscoveryRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + string prefix = 2; +} + +message MUPDirectSegmentDiscoveryRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + string address = 2; +} + +message MUPType1SessionTransformedRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + uint32 prefix_length = 2 [deprecated = true]; + string prefix = 3; + uint32 teid = 4; + uint32 qfi = 5; + uint32 endpoint_address_length = 6; + string endpoint_address = 7; +} + +message MUPType2SessionTransformedRoute { + // One of: + // - RouteDistinguisherTwoOctetASN + // - RouteDistinguisherIPAddress + // - RouteDistinguisherFourOctetASN + google.protobuf.Any rd = 1; + uint32 endpoint_address_length = 2; + string endpoint_address = 3; + uint32 teid = 4; +} + +message MpReachNLRIAttribute { + apipb.Family family = 1; + repeated string next_hops = 2; + // Each NLRI must be one of: + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - EVPNIPMSIRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + // - LsAddrPrefix + // - SR Policy NLRI + // - MUPInterworkSegmentDiscoveryRoute + // - MUPDirectSegmentDiscoveryRoute + // - MUPType1SessionTransformedRoute + // - MUPType2SessionTransformedRoute + repeated google.protobuf.Any nlris = 3; +} + +message MpUnreachNLRIAttribute { + apipb.Family family = 1; + // The same as NLRI field of MpReachNLRIAttribute + repeated google.protobuf.Any nlris = 3; +} + +message TwoOctetAsSpecificExtended { + bool is_transitive = 1; + uint32 sub_type = 2; + uint32 asn = 3; + uint32 local_admin = 4; +} + +message IPv4AddressSpecificExtended { + bool is_transitive = 1; + uint32 sub_type = 2; + string address = 3; + uint32 local_admin = 4; +} + +message FourOctetAsSpecificExtended { + bool is_transitive = 1; + uint32 sub_type = 2; + uint32 asn = 3; + uint32 local_admin = 4; +} + +message LinkBandwidthExtended { + uint32 asn = 1; + float bandwidth = 2; +} + +message ValidationExtended { uint32 state = 1; } + +message ColorExtended { uint32 color = 1; } + +message EncapExtended { uint32 tunnel_type = 1; } + +message DefaultGatewayExtended {} + +message OpaqueExtended { + bool is_transitive = 1; + bytes value = 3; +} + +message ESILabelExtended { + bool is_single_active = 1; + uint32 label = 2; +} + +message ESImportRouteTarget { string es_import = 1; } + +message MacMobilityExtended { + bool is_sticky = 1; + uint32 sequence_num = 2; +} + +message RouterMacExtended { string mac = 1; } + +message TrafficRateExtended { + uint32 asn = 1; + float rate = 2; +} + +message TrafficActionExtended { + bool terminal = 1; + bool sample = 2; +} + +message RedirectTwoOctetAsSpecificExtended { + uint32 asn = 1; + uint32 local_admin = 2; +} + +message RedirectIPv4AddressSpecificExtended { + string address = 1; + uint32 local_admin = 2; +} + +message RedirectFourOctetAsSpecificExtended { + uint32 asn = 1; + uint32 local_admin = 2; +} + +message TrafficRemarkExtended { uint32 dscp = 1; } + +message MUPExtended { + uint32 sub_type = 1; + uint32 segment_id2 = 2; + uint32 segment_id4 = 3; +} + +message UnknownExtended { + uint32 type = 1; + bytes value = 2; +} + +message ExtendedCommunitiesAttribute { + // Each Community must be one of: + // - TwoOctetAsSpecificExtended + // - IPv4AddressSpecificExtended + // - FourOctetAsSpecificExtended + // - OpaqueExtended + // - ESILabelExtended + // - MacMobilityExtended + // - RouterMacExtended + // - TrafficRateExtended + // - TrafficActionExtended + // - RedirectTwoOctetAsSpecificExtended + // - RedirectIPv4AddressSpecificExtended + // - RedirectFourOctetAsSpecificExtended + // - TrafficRemarkExtended + // - MUPExtended + // - UnknownExtended + repeated google.protobuf.Any communities = 1; +} + +message As4PathAttribute { repeated AsSegment segments = 1; } + +message As4AggregatorAttribute { + uint32 asn = 2; + string address = 3; +} + +message PmsiTunnelAttribute { + uint32 flags = 1; + uint32 type = 2; + uint32 label = 3; + bytes id = 4; +} + +message TunnelEncapSubTLVEncapsulation { + uint32 key = 1; + bytes cookie = 2; +} + +message TunnelEncapSubTLVProtocol { uint32 protocol = 1; } + +message TunnelEncapSubTLVColor { uint32 color = 1; } + +message TunnelEncapSubTLVSRPreference { + uint32 flags = 1; + uint32 preference = 2; +} + +message TunnelEncapSubTLVSRCandidatePathName { string candidate_path_name = 1; } + +message TunnelEncapSubTLVSRPriority { uint32 priority = 1; } + +message TunnelEncapSubTLVSRBindingSID { + // bsid must be one of: + // - SRBindingSID + // - SRv6BindingSID + google.protobuf.Any bsid = 1; +} + +message SRBindingSID { + bool s_flag = 1; + bool i_flag = 2; + bytes sid = 3; +} + +enum SRv6Behavior { + RESERVED = 0; END = 1; END_WITH_PSP = 2; END_WITH_USP = 3; + END_WITH_PSP_USP = 4; + ENDX = 5; + ENDX_WITH_PSP = 6; + ENDX_WITH_USP = 7; + ENDX_WITH_PSP_USP = 8; + ENDT = 9; + ENDT_WITH_PSP = 10; + ENDT_WITH_USP = 11; + ENDT_WITH_PSP_USP = 12; + END_B6_ENCAPS = 14; + END_BM = 15; + END_DX6 = 16; + END_DX4 = 17; + END_DT6 = 18; + END_DT4 = 19; + END_DT46 = 20; + END_DX2 = 21; + END_DX2V = 22; + END_DT2U = 23; + END_DT2M = 24; + END_B6_ENCAPS_Red = 27; + END_WITH_USD = 28; + END_WITH_PSP_USD = 29; + END_WITH_USP_USD = 30; + END_WITH_PSP_USP_USD = 31; + ENDX_WITH_USD = 32; + ENDX_WITH_PSP_USD = 33; + ENDX_WITH_USP_USD = 34; + ENDX_WITH_PSP_USP_USD = 35; + ENDT_WITH_USD = 36; + ENDT_WITH_PSP_USD = 37; + ENDT_WITH_USP_USD = 38; + ENDT_WITH_PSP_USP_USD = 39; + ENDM_GTP6D = 69; // 0x0045 + ENDM_GTP6DI = 70; // 0x0046 + ENDM_GTP6E = 71; // 0x0047 + ENDM_GTP4E = 72; // 0x0048 +} + +message SRv6EndPointBehavior { + SRv6Behavior behavior = 1; + uint32 block_len = 2; + uint32 node_len = 3; + uint32 func_len = 4; + uint32 arg_len = 5; +} + +message SRv6BindingSID { + bool s_flag = 1; + bool i_flag = 2; + bool b_flag = 3; + bytes sid = 4; + SRv6EndPointBehavior endpoint_behavior_structure = 5; +} + +enum ENLPType { Reserved = 0; Type1 = 1; Type2 = 2; Type3 = 3; Type4 = 4; } + +message TunnelEncapSubTLVSRENLP { + uint32 flags = 1; + ENLPType enlp = 2; +} + +message SRWeight { + uint32 flags = 1; + uint32 weight = 2; +} + +message SegmentFlags { + bool v_flag = 1; + bool a_flag = 2; + bool s_flag = 3; + bool b_flag = 4; +} + +message SegmentTypeA { + SegmentFlags flags = 1; + uint32 label = 2; +} + +message SegmentTypeB { + SegmentFlags flags = 1; + bytes sid = 2; + SRv6EndPointBehavior endpoint_behavior_structure = 3; +} + +message TunnelEncapSubTLVSRSegmentList { + SRWeight weight = 1; + // segments must be one of: + // - SegmentTypeA + // - SegmentTypeB + repeated google.protobuf.Any segments = 2; +} + +message TunnelEncapSubTLVEgressEndpoint { + string address = 1; +} + +message TunnelEncapSubTLVUDPDestPort { + uint32 port = 1; +} + +message TunnelEncapSubTLVUnknown { + uint32 type = 1; + bytes value = 2; +} + +message TunnelEncapTLV { + uint32 type = 1; + // Each TLV must be one of: + // - TunnelEncapSubTLVEncapsulation + // - TunnelEncapSubTLVProtocol + // - TunnelEncapSubTLVColor + // - TunnelEncapSubTLVSRPolicy + // - TunnelEncapSubTLVUnknown + repeated google.protobuf.Any tlvs = 2; +} + +message TunnelEncapAttribute { repeated TunnelEncapTLV tlvs = 1; } + +message IPv6AddressSpecificExtended { + bool is_transitive = 1; + uint32 sub_type = 2; + string address = 3; + uint32 local_admin = 4; +} + +message RedirectIPv6AddressSpecificExtended { + string address = 1; + uint32 local_admin = 2; +} + +message IP6ExtendedCommunitiesAttribute { + // Each Community must be one of: + // - IPv6AddressSpecificExtended + // - RedirectIPv6AddressSpecificExtended + repeated google.protobuf.Any communities = 1; +} + +message AigpTLVIGPMetric { uint64 metric = 1; } + +message AigpTLVUnknown { + uint32 type = 1; + bytes value = 2; +} + +message AigpAttribute { + // Each TLV must be one of: + // - AigpTLVIGPMetric + // - AigpTLVUnknown + repeated google.protobuf.Any tlvs = 1; +} + +message LargeCommunity { + uint32 global_admin = 1; + uint32 local_data1 = 2; + uint32 local_data2 = 3; +} + +message LargeCommunitiesAttribute { repeated LargeCommunity communities = 1; } + +message LsNodeFlags { + bool overload = 1; + bool attached = 2; + bool external = 3; + bool abr = 4; + bool router = 5; + bool v6 = 6; +} + +message LsIGPFlags { + bool down = 1; + bool no_unicast = 2; + bool local_address = 3; + bool propagate_nssa = 4; +} + +message LsSrRange { + uint32 begin = 1; + uint32 end = 2; +} + +message LsSrCapabilities { + bool ipv4_supported = 1; + bool ipv6_supported = 2; + repeated LsSrRange ranges = 3; +} + +message LsSrLocalBlock { repeated LsSrRange ranges = 1; } + +message LsAttributeNode { + string name = 1; + LsNodeFlags flags = 2; + string local_router_id = 3; + string local_router_id_v6 = 4; + bytes isis_area = 5; + bytes opaque = 6; + + LsSrCapabilities sr_capabilities = 7; + bytes sr_algorithms = 8; + LsSrLocalBlock sr_local_block = 9; +} + +message LsAttributeLink { + string name = 1; + string local_router_id = 2; + string local_router_id_v6 = 3; + string remote_router_id = 4; + string remote_router_id_v6 = 5; + uint32 admin_group = 6; + uint32 default_te_metric = 7; + uint32 igp_metric = 8; + bytes opaque = 9; + + float bandwidth = 10; + float reservable_bandwidth = 11; + repeated float unreserved_bandwidth = 12; + + uint32 sr_adjacency_sid = 13; + repeated uint32 srlgs = 14; +} + +message LsAttributePrefix { + LsIGPFlags igp_flags = 1; + bytes opaque = 2; + + uint32 sr_prefix_sid = 3; +} + +message LsAttribute { + LsAttributeNode node = 1; + LsAttributeLink link = 2; + LsAttributePrefix prefix = 3; +} + +message UnknownAttribute { + uint32 flags = 1; + uint32 type = 2; + bytes value = 3; +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-3.2.1 +message SRv6StructureSubSubTLV { + uint32 locator_block_length = 1; + uint32 locator_node_length = 2; + uint32 function_length = 3; + uint32 argument_length = 4; + uint32 transposition_length = 5; + uint32 transposition_offset = 6; +} + +message SRv6SIDFlags { + // Placeholder for future sid flags + bool flag_1 = 1; +} + +message SRv6TLV { repeated google.protobuf.Any tlv = 1; } + +// https://tools.ietf.org/html/draft-dawra-bess-srv6-services-02#section-2.1.1 +message SRv6InformationSubTLV { + bytes sid = 1; + SRv6SIDFlags flags = 2; + uint32 endpoint_behavior = 3; + // SRv6TLV is one of: + // - SRv6StructureSubSubTLV + map sub_sub_tlvs = 4; +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-2 +message SRv6L3ServiceTLV { + // SRv6TLV is one of: + // - SRv6InformationSubTLV + map sub_tlvs = 1; +} + +// https://www.rfc-editor.org/rfc/rfc9252.html#section-2 +message SRv6L2ServiceTLV { + // SRv6TLV is one of: + // - SRv6InformationSubTLV + map sub_tlvs = 1; +} + +// https://tools.ietf.org/html/rfc8669 +message PrefixSID { + // tlv is one of: + // - IndexLabelTLV Type 1 (not yet implemented) + // - OriginatorSRGBTLV Type 3 (not yet implemented) + // - SRv6L3ServiceTLV Type 5 + // - SRv6L2ServiceTLV Type 6 + repeated google.protobuf.Any tlvs = 1; +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/capability.pb.go b/vendor/github.com/osrg/gobgp/v3/api/capability.pb.go new file mode 100644 index 000000000..4ad1ffe93 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/capability.pb.go @@ -0,0 +1,1252 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.19.1 +// source: capability.proto + +package apipb + +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 AddPathCapabilityTuple_Mode int32 + +const ( + AddPathCapabilityTuple_NONE AddPathCapabilityTuple_Mode = 0 + AddPathCapabilityTuple_RECEIVE AddPathCapabilityTuple_Mode = 1 + AddPathCapabilityTuple_SEND AddPathCapabilityTuple_Mode = 2 + AddPathCapabilityTuple_BOTH AddPathCapabilityTuple_Mode = 3 +) + +// Enum value maps for AddPathCapabilityTuple_Mode. +var ( + AddPathCapabilityTuple_Mode_name = map[int32]string{ + 0: "NONE", + 1: "RECEIVE", + 2: "SEND", + 3: "BOTH", + } + AddPathCapabilityTuple_Mode_value = map[string]int32{ + "NONE": 0, + "RECEIVE": 1, + "SEND": 2, + "BOTH": 3, + } +) + +func (x AddPathCapabilityTuple_Mode) Enum() *AddPathCapabilityTuple_Mode { + p := new(AddPathCapabilityTuple_Mode) + *p = x + return p +} + +func (x AddPathCapabilityTuple_Mode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AddPathCapabilityTuple_Mode) Descriptor() protoreflect.EnumDescriptor { + return file_capability_proto_enumTypes[0].Descriptor() +} + +func (AddPathCapabilityTuple_Mode) Type() protoreflect.EnumType { + return &file_capability_proto_enumTypes[0] +} + +func (x AddPathCapabilityTuple_Mode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AddPathCapabilityTuple_Mode.Descriptor instead. +func (AddPathCapabilityTuple_Mode) EnumDescriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{8, 0} +} + +type MultiProtocolCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` +} + +func (x *MultiProtocolCapability) Reset() { + *x = MultiProtocolCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MultiProtocolCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MultiProtocolCapability) ProtoMessage() {} + +func (x *MultiProtocolCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 MultiProtocolCapability.ProtoReflect.Descriptor instead. +func (*MultiProtocolCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{0} +} + +func (x *MultiProtocolCapability) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +type RouteRefreshCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RouteRefreshCapability) Reset() { + *x = RouteRefreshCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteRefreshCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteRefreshCapability) ProtoMessage() {} + +func (x *RouteRefreshCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 RouteRefreshCapability.ProtoReflect.Descriptor instead. +func (*RouteRefreshCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{1} +} + +type CarryingLabelInfoCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CarryingLabelInfoCapability) Reset() { + *x = CarryingLabelInfoCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CarryingLabelInfoCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CarryingLabelInfoCapability) ProtoMessage() {} + +func (x *CarryingLabelInfoCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 CarryingLabelInfoCapability.ProtoReflect.Descriptor instead. +func (*CarryingLabelInfoCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{2} +} + +type ExtendedNexthopCapabilityTuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NlriFamily *Family `protobuf:"bytes,1,opt,name=nlri_family,json=nlriFamily,proto3" json:"nlri_family,omitempty"` + // Nexthop AFI must be either + // gobgp.IPv4 or + // gobgp.IPv6. + NexthopFamily *Family `protobuf:"bytes,2,opt,name=nexthop_family,json=nexthopFamily,proto3" json:"nexthop_family,omitempty"` +} + +func (x *ExtendedNexthopCapabilityTuple) Reset() { + *x = ExtendedNexthopCapabilityTuple{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtendedNexthopCapabilityTuple) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtendedNexthopCapabilityTuple) ProtoMessage() {} + +func (x *ExtendedNexthopCapabilityTuple) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 ExtendedNexthopCapabilityTuple.ProtoReflect.Descriptor instead. +func (*ExtendedNexthopCapabilityTuple) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{3} +} + +func (x *ExtendedNexthopCapabilityTuple) GetNlriFamily() *Family { + if x != nil { + return x.NlriFamily + } + return nil +} + +func (x *ExtendedNexthopCapabilityTuple) GetNexthopFamily() *Family { + if x != nil { + return x.NexthopFamily + } + return nil +} + +type ExtendedNexthopCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tuples []*ExtendedNexthopCapabilityTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` +} + +func (x *ExtendedNexthopCapability) Reset() { + *x = ExtendedNexthopCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtendedNexthopCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtendedNexthopCapability) ProtoMessage() {} + +func (x *ExtendedNexthopCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 ExtendedNexthopCapability.ProtoReflect.Descriptor instead. +func (*ExtendedNexthopCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{4} +} + +func (x *ExtendedNexthopCapability) GetTuples() []*ExtendedNexthopCapabilityTuple { + if x != nil { + return x.Tuples + } + return nil +} + +type GracefulRestartCapabilityTuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Flags uint32 `protobuf:"varint,2,opt,name=flags,proto3" json:"flags,omitempty"` +} + +func (x *GracefulRestartCapabilityTuple) Reset() { + *x = GracefulRestartCapabilityTuple{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GracefulRestartCapabilityTuple) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GracefulRestartCapabilityTuple) ProtoMessage() {} + +func (x *GracefulRestartCapabilityTuple) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 GracefulRestartCapabilityTuple.ProtoReflect.Descriptor instead. +func (*GracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{5} +} + +func (x *GracefulRestartCapabilityTuple) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *GracefulRestartCapabilityTuple) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +type GracefulRestartCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flags uint32 `protobuf:"varint,1,opt,name=flags,proto3" json:"flags,omitempty"` + Time uint32 `protobuf:"varint,2,opt,name=time,proto3" json:"time,omitempty"` + Tuples []*GracefulRestartCapabilityTuple `protobuf:"bytes,3,rep,name=tuples,proto3" json:"tuples,omitempty"` +} + +func (x *GracefulRestartCapability) Reset() { + *x = GracefulRestartCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GracefulRestartCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GracefulRestartCapability) ProtoMessage() {} + +func (x *GracefulRestartCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 GracefulRestartCapability.ProtoReflect.Descriptor instead. +func (*GracefulRestartCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{6} +} + +func (x *GracefulRestartCapability) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *GracefulRestartCapability) GetTime() uint32 { + if x != nil { + return x.Time + } + return 0 +} + +func (x *GracefulRestartCapability) GetTuples() []*GracefulRestartCapabilityTuple { + if x != nil { + return x.Tuples + } + return nil +} + +type FourOctetASNCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` +} + +func (x *FourOctetASNCapability) Reset() { + *x = FourOctetASNCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FourOctetASNCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FourOctetASNCapability) ProtoMessage() {} + +func (x *FourOctetASNCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 FourOctetASNCapability.ProtoReflect.Descriptor instead. +func (*FourOctetASNCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{7} +} + +func (x *FourOctetASNCapability) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +type AddPathCapabilityTuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Mode AddPathCapabilityTuple_Mode `protobuf:"varint,2,opt,name=mode,proto3,enum=apipb.AddPathCapabilityTuple_Mode" json:"mode,omitempty"` +} + +func (x *AddPathCapabilityTuple) Reset() { + *x = AddPathCapabilityTuple{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathCapabilityTuple) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathCapabilityTuple) ProtoMessage() {} + +func (x *AddPathCapabilityTuple) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 AddPathCapabilityTuple.ProtoReflect.Descriptor instead. +func (*AddPathCapabilityTuple) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{8} +} + +func (x *AddPathCapabilityTuple) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *AddPathCapabilityTuple) GetMode() AddPathCapabilityTuple_Mode { + if x != nil { + return x.Mode + } + return AddPathCapabilityTuple_NONE +} + +type AddPathCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tuples []*AddPathCapabilityTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` +} + +func (x *AddPathCapability) Reset() { + *x = AddPathCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathCapability) ProtoMessage() {} + +func (x *AddPathCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 AddPathCapability.ProtoReflect.Descriptor instead. +func (*AddPathCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{9} +} + +func (x *AddPathCapability) GetTuples() []*AddPathCapabilityTuple { + if x != nil { + return x.Tuples + } + return nil +} + +type EnhancedRouteRefreshCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EnhancedRouteRefreshCapability) Reset() { + *x = EnhancedRouteRefreshCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnhancedRouteRefreshCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnhancedRouteRefreshCapability) ProtoMessage() {} + +func (x *EnhancedRouteRefreshCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 EnhancedRouteRefreshCapability.ProtoReflect.Descriptor instead. +func (*EnhancedRouteRefreshCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{10} +} + +type LongLivedGracefulRestartCapabilityTuple struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Flags uint32 `protobuf:"varint,2,opt,name=flags,proto3" json:"flags,omitempty"` + Time uint32 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` +} + +func (x *LongLivedGracefulRestartCapabilityTuple) Reset() { + *x = LongLivedGracefulRestartCapabilityTuple{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LongLivedGracefulRestartCapabilityTuple) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LongLivedGracefulRestartCapabilityTuple) ProtoMessage() {} + +func (x *LongLivedGracefulRestartCapabilityTuple) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 LongLivedGracefulRestartCapabilityTuple.ProtoReflect.Descriptor instead. +func (*LongLivedGracefulRestartCapabilityTuple) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{11} +} + +func (x *LongLivedGracefulRestartCapabilityTuple) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *LongLivedGracefulRestartCapabilityTuple) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + +func (x *LongLivedGracefulRestartCapabilityTuple) GetTime() uint32 { + if x != nil { + return x.Time + } + return 0 +} + +type LongLivedGracefulRestartCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tuples []*LongLivedGracefulRestartCapabilityTuple `protobuf:"bytes,1,rep,name=tuples,proto3" json:"tuples,omitempty"` +} + +func (x *LongLivedGracefulRestartCapability) Reset() { + *x = LongLivedGracefulRestartCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LongLivedGracefulRestartCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LongLivedGracefulRestartCapability) ProtoMessage() {} + +func (x *LongLivedGracefulRestartCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 LongLivedGracefulRestartCapability.ProtoReflect.Descriptor instead. +func (*LongLivedGracefulRestartCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{12} +} + +func (x *LongLivedGracefulRestartCapability) GetTuples() []*LongLivedGracefulRestartCapabilityTuple { + if x != nil { + return x.Tuples + } + return nil +} + +type RouteRefreshCiscoCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RouteRefreshCiscoCapability) Reset() { + *x = RouteRefreshCiscoCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteRefreshCiscoCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteRefreshCiscoCapability) ProtoMessage() {} + +func (x *RouteRefreshCiscoCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 RouteRefreshCiscoCapability.ProtoReflect.Descriptor instead. +func (*RouteRefreshCiscoCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{13} +} + +type FqdnCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HostName string `protobuf:"bytes,1,opt,name=host_name,json=hostName,proto3" json:"host_name,omitempty"` + DomainName string `protobuf:"bytes,2,opt,name=domain_name,json=domainName,proto3" json:"domain_name,omitempty"` +} + +func (x *FqdnCapability) Reset() { + *x = FqdnCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FqdnCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FqdnCapability) ProtoMessage() {} + +func (x *FqdnCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 FqdnCapability.ProtoReflect.Descriptor instead. +func (*FqdnCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{14} +} + +func (x *FqdnCapability) GetHostName() string { + if x != nil { + return x.HostName + } + return "" +} + +func (x *FqdnCapability) GetDomainName() string { + if x != nil { + return x.DomainName + } + return "" +} + +type UnknownCapability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *UnknownCapability) Reset() { + *x = UnknownCapability{} + if protoimpl.UnsafeEnabled { + mi := &file_capability_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnknownCapability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnknownCapability) ProtoMessage() {} + +func (x *UnknownCapability) ProtoReflect() protoreflect.Message { + mi := &file_capability_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 UnknownCapability.ProtoReflect.Descriptor instead. +func (*UnknownCapability) Descriptor() ([]byte, []int) { + return file_capability_proto_rawDescGZIP(), []int{15} +} + +func (x *UnknownCapability) GetCode() uint32 { + if x != nil { + return x.Code + } + return 0 +} + +func (x *UnknownCapability) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +var File_capability_proto protoreflect.FileDescriptor + +var file_capability_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x05, 0x61, 0x70, 0x69, 0x70, 0x62, 0x1a, 0x0b, 0x67, 0x6f, 0x62, 0x67, 0x70, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x40, 0x0a, 0x17, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x22, 0x1d, 0x0a, 0x1b, 0x43, 0x61, 0x72, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x22, 0x86, 0x01, 0x0a, 0x1e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4e, 0x65, + 0x78, 0x74, 0x68, 0x6f, 0x70, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, + 0x75, 0x70, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x0b, 0x6e, 0x6c, 0x72, 0x69, 0x5f, 0x66, 0x61, 0x6d, + 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0a, 0x6e, 0x6c, 0x72, 0x69, 0x46, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x0e, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x5f, + 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0d, 0x6e, 0x65, 0x78, + 0x74, 0x68, 0x6f, 0x70, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x5a, 0x0a, 0x19, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x43, 0x61, 0x70, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x43, + 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, + 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x1e, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, + 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, + 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x19, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, + 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, + 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, + 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x2a, 0x0a, 0x16, + 0x46, 0x6f, 0x75, 0x72, 0x4f, 0x63, 0x74, 0x65, 0x74, 0x41, 0x53, 0x4e, 0x43, 0x61, 0x70, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x22, 0xaa, 0x01, 0x0a, 0x16, 0x41, 0x64, 0x64, + 0x50, 0x61, 0x74, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, 0x75, + 0x70, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x36, 0x0a, 0x04, 0x6d, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, + 0x64, 0x65, 0x22, 0x31, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, + 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x10, + 0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x42, + 0x4f, 0x54, 0x48, 0x10, 0x03, 0x22, 0x4a, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, + 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x74, 0x75, + 0x70, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, + 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x45, 0x6e, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x22, 0x7a, 0x0a, 0x27, 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, + 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, + 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x25, + 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, + 0x6c, 0x0a, 0x22, 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, + 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x6f, + 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x54, 0x75, 0x70, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x75, 0x70, 0x6c, 0x65, 0x73, 0x22, 0x1d, 0x0a, + 0x1b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x43, 0x69, 0x73, + 0x63, 0x6f, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x4e, 0x0a, 0x0e, + 0x46, 0x71, 0x64, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1b, + 0x0a, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x3d, 0x0a, 0x11, + 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x24, 0x5a, 0x22, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x73, 0x72, 0x67, 0x2f, 0x67, + 0x6f, 0x62, 0x67, 0x70, 0x2f, 0x76, 0x33, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_capability_proto_rawDescOnce sync.Once + file_capability_proto_rawDescData = file_capability_proto_rawDesc +) + +func file_capability_proto_rawDescGZIP() []byte { + file_capability_proto_rawDescOnce.Do(func() { + file_capability_proto_rawDescData = protoimpl.X.CompressGZIP(file_capability_proto_rawDescData) + }) + return file_capability_proto_rawDescData +} + +var file_capability_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_capability_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_capability_proto_goTypes = []interface{}{ + (AddPathCapabilityTuple_Mode)(0), // 0: apipb.AddPathCapabilityTuple.Mode + (*MultiProtocolCapability)(nil), // 1: apipb.MultiProtocolCapability + (*RouteRefreshCapability)(nil), // 2: apipb.RouteRefreshCapability + (*CarryingLabelInfoCapability)(nil), // 3: apipb.CarryingLabelInfoCapability + (*ExtendedNexthopCapabilityTuple)(nil), // 4: apipb.ExtendedNexthopCapabilityTuple + (*ExtendedNexthopCapability)(nil), // 5: apipb.ExtendedNexthopCapability + (*GracefulRestartCapabilityTuple)(nil), // 6: apipb.GracefulRestartCapabilityTuple + (*GracefulRestartCapability)(nil), // 7: apipb.GracefulRestartCapability + (*FourOctetASNCapability)(nil), // 8: apipb.FourOctetASNCapability + (*AddPathCapabilityTuple)(nil), // 9: apipb.AddPathCapabilityTuple + (*AddPathCapability)(nil), // 10: apipb.AddPathCapability + (*EnhancedRouteRefreshCapability)(nil), // 11: apipb.EnhancedRouteRefreshCapability + (*LongLivedGracefulRestartCapabilityTuple)(nil), // 12: apipb.LongLivedGracefulRestartCapabilityTuple + (*LongLivedGracefulRestartCapability)(nil), // 13: apipb.LongLivedGracefulRestartCapability + (*RouteRefreshCiscoCapability)(nil), // 14: apipb.RouteRefreshCiscoCapability + (*FqdnCapability)(nil), // 15: apipb.FqdnCapability + (*UnknownCapability)(nil), // 16: apipb.UnknownCapability + (*Family)(nil), // 17: apipb.Family +} +var file_capability_proto_depIdxs = []int32{ + 17, // 0: apipb.MultiProtocolCapability.family:type_name -> apipb.Family + 17, // 1: apipb.ExtendedNexthopCapabilityTuple.nlri_family:type_name -> apipb.Family + 17, // 2: apipb.ExtendedNexthopCapabilityTuple.nexthop_family:type_name -> apipb.Family + 4, // 3: apipb.ExtendedNexthopCapability.tuples:type_name -> apipb.ExtendedNexthopCapabilityTuple + 17, // 4: apipb.GracefulRestartCapabilityTuple.family:type_name -> apipb.Family + 6, // 5: apipb.GracefulRestartCapability.tuples:type_name -> apipb.GracefulRestartCapabilityTuple + 17, // 6: apipb.AddPathCapabilityTuple.family:type_name -> apipb.Family + 0, // 7: apipb.AddPathCapabilityTuple.mode:type_name -> apipb.AddPathCapabilityTuple.Mode + 9, // 8: apipb.AddPathCapability.tuples:type_name -> apipb.AddPathCapabilityTuple + 17, // 9: apipb.LongLivedGracefulRestartCapabilityTuple.family:type_name -> apipb.Family + 12, // 10: apipb.LongLivedGracefulRestartCapability.tuples:type_name -> apipb.LongLivedGracefulRestartCapabilityTuple + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_capability_proto_init() } +func file_capability_proto_init() { + if File_capability_proto != nil { + return + } + file_gobgp_proto_init() + if !protoimpl.UnsafeEnabled { + file_capability_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MultiProtocolCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteRefreshCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CarryingLabelInfoCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtendedNexthopCapabilityTuple); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtendedNexthopCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GracefulRestartCapabilityTuple); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GracefulRestartCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FourOctetASNCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathCapabilityTuple); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnhancedRouteRefreshCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LongLivedGracefulRestartCapabilityTuple); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LongLivedGracefulRestartCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteRefreshCiscoCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FqdnCapability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_capability_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnknownCapability); 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_capability_proto_rawDesc, + NumEnums: 1, + NumMessages: 16, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_capability_proto_goTypes, + DependencyIndexes: file_capability_proto_depIdxs, + EnumInfos: file_capability_proto_enumTypes, + MessageInfos: file_capability_proto_msgTypes, + }.Build() + File_capability_proto = out.File + file_capability_proto_rawDesc = nil + file_capability_proto_goTypes = nil + file_capability_proto_depIdxs = nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/capability.proto b/vendor/github.com/osrg/gobgp/v3/api/capability.proto new file mode 100644 index 000000000..cb7f36691 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/capability.proto @@ -0,0 +1,105 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +syntax = "proto3"; + +package apipb; +option go_package = "github.com/osrg/gobgp/v3/api;apipb"; + +import "gobgp.proto"; + +message MultiProtocolCapability { + apipb.Family family = 1; +} + +message RouteRefreshCapability { +} + +message CarryingLabelInfoCapability { +} + +message ExtendedNexthopCapabilityTuple { + apipb.Family nlri_family = 1; + // Nexthop AFI must be either + // gobgp.IPv4 or + // gobgp.IPv6. + apipb.Family nexthop_family = 2; +} + +message ExtendedNexthopCapability { + repeated ExtendedNexthopCapabilityTuple tuples = 1; +} + +message GracefulRestartCapabilityTuple { + apipb.Family family = 1; + uint32 flags = 2; +} + +message GracefulRestartCapability { + uint32 flags = 1; + uint32 time = 2; + repeated GracefulRestartCapabilityTuple tuples = 3; +} + +message FourOctetASNCapability { + uint32 asn = 1; +} + +message AddPathCapabilityTuple { + apipb.Family family = 1; + enum Mode { + NONE = 0; + RECEIVE = 1; + SEND = 2; + BOTH = 3; + } + Mode mode = 2; +} + +message AddPathCapability { + repeated AddPathCapabilityTuple tuples = 1; +} + +message EnhancedRouteRefreshCapability { +} + +message LongLivedGracefulRestartCapabilityTuple { + apipb.Family family = 1; + uint32 flags = 2; + uint32 time = 3; +} + +message LongLivedGracefulRestartCapability { + repeated LongLivedGracefulRestartCapabilityTuple tuples = 1; +} + +message RouteRefreshCiscoCapability { +} + +message FqdnCapability { + string host_name = 1; + string domain_name = 2; +} + +message UnknownCapability { + uint32 code = 1; + bytes value = 2; +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/gobgp.pb.go b/vendor/github.com/osrg/gobgp/v3/api/gobgp.pb.go new file mode 100644 index 000000000..251f72be9 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/gobgp.pb.go @@ -0,0 +1,15721 @@ +// Copyright (C) 2015-2017 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.19.1 +// source: gobgp.proto + +package apipb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + emptypb "google.golang.org/protobuf/types/known/emptypb" + 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 TableType int32 + +const ( + TableType_GLOBAL TableType = 0 + TableType_LOCAL TableType = 1 + TableType_ADJ_IN TableType = 2 + TableType_ADJ_OUT TableType = 3 + TableType_VRF TableType = 4 +) + +// Enum value maps for TableType. +var ( + TableType_name = map[int32]string{ + 0: "GLOBAL", + 1: "LOCAL", + 2: "ADJ_IN", + 3: "ADJ_OUT", + 4: "VRF", + } + TableType_value = map[string]int32{ + "GLOBAL": 0, + "LOCAL": 1, + "ADJ_IN": 2, + "ADJ_OUT": 3, + "VRF": 4, + } +) + +func (x TableType) Enum() *TableType { + p := new(TableType) + *p = x + return p +} + +func (x TableType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TableType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[0].Descriptor() +} + +func (TableType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[0] +} + +func (x TableType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TableType.Descriptor instead. +func (TableType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{0} +} + +type PeerType int32 + +const ( + PeerType_INTERNAL PeerType = 0 + PeerType_EXTERNAL PeerType = 1 +) + +// Enum value maps for PeerType. +var ( + PeerType_name = map[int32]string{ + 0: "INTERNAL", + 1: "EXTERNAL", + } + PeerType_value = map[string]int32{ + "INTERNAL": 0, + "EXTERNAL": 1, + } +) + +func (x PeerType) Enum() *PeerType { + p := new(PeerType) + *p = x + return p +} + +func (x PeerType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PeerType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[1].Descriptor() +} + +func (PeerType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[1] +} + +func (x PeerType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PeerType.Descriptor instead. +func (PeerType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{1} +} + +type RemovePrivate int32 + +const ( + RemovePrivate_REMOVE_NONE RemovePrivate = 0 + RemovePrivate_REMOVE_ALL RemovePrivate = 1 + RemovePrivate_REPLACE RemovePrivate = 2 +) + +// Enum value maps for RemovePrivate. +var ( + RemovePrivate_name = map[int32]string{ + 0: "REMOVE_NONE", + 1: "REMOVE_ALL", + 2: "REPLACE", + } + RemovePrivate_value = map[string]int32{ + "REMOVE_NONE": 0, + "REMOVE_ALL": 1, + "REPLACE": 2, + } +) + +func (x RemovePrivate) Enum() *RemovePrivate { + p := new(RemovePrivate) + *p = x + return p +} + +func (x RemovePrivate) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RemovePrivate) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[2].Descriptor() +} + +func (RemovePrivate) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[2] +} + +func (x RemovePrivate) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RemovePrivate.Descriptor instead. +func (RemovePrivate) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{2} +} + +type DefinedType int32 + +const ( + DefinedType_PREFIX DefinedType = 0 + DefinedType_NEIGHBOR DefinedType = 1 + DefinedType_TAG DefinedType = 2 + DefinedType_AS_PATH DefinedType = 3 + DefinedType_COMMUNITY DefinedType = 4 + DefinedType_EXT_COMMUNITY DefinedType = 5 + DefinedType_LARGE_COMMUNITY DefinedType = 6 + DefinedType_NEXT_HOP DefinedType = 7 +) + +// Enum value maps for DefinedType. +var ( + DefinedType_name = map[int32]string{ + 0: "PREFIX", + 1: "NEIGHBOR", + 2: "TAG", + 3: "AS_PATH", + 4: "COMMUNITY", + 5: "EXT_COMMUNITY", + 6: "LARGE_COMMUNITY", + 7: "NEXT_HOP", + } + DefinedType_value = map[string]int32{ + "PREFIX": 0, + "NEIGHBOR": 1, + "TAG": 2, + "AS_PATH": 3, + "COMMUNITY": 4, + "EXT_COMMUNITY": 5, + "LARGE_COMMUNITY": 6, + "NEXT_HOP": 7, + } +) + +func (x DefinedType) Enum() *DefinedType { + p := new(DefinedType) + *p = x + return p +} + +func (x DefinedType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DefinedType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[3].Descriptor() +} + +func (DefinedType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[3] +} + +func (x DefinedType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DefinedType.Descriptor instead. +func (DefinedType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{3} +} + +type RouteAction int32 + +const ( + RouteAction_NONE RouteAction = 0 + RouteAction_ACCEPT RouteAction = 1 + RouteAction_REJECT RouteAction = 2 +) + +// Enum value maps for RouteAction. +var ( + RouteAction_name = map[int32]string{ + 0: "NONE", + 1: "ACCEPT", + 2: "REJECT", + } + RouteAction_value = map[string]int32{ + "NONE": 0, + "ACCEPT": 1, + "REJECT": 2, + } +) + +func (x RouteAction) Enum() *RouteAction { + p := new(RouteAction) + *p = x + return p +} + +func (x RouteAction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RouteAction) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[4].Descriptor() +} + +func (RouteAction) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[4] +} + +func (x RouteAction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RouteAction.Descriptor instead. +func (RouteAction) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4} +} + +type PolicyDirection int32 + +const ( + PolicyDirection_UNKNOWN PolicyDirection = 0 + PolicyDirection_IMPORT PolicyDirection = 1 + PolicyDirection_EXPORT PolicyDirection = 2 +) + +// Enum value maps for PolicyDirection. +var ( + PolicyDirection_name = map[int32]string{ + 0: "UNKNOWN", + 1: "IMPORT", + 2: "EXPORT", + } + PolicyDirection_value = map[string]int32{ + "UNKNOWN": 0, + "IMPORT": 1, + "EXPORT": 2, + } +) + +func (x PolicyDirection) Enum() *PolicyDirection { + p := new(PolicyDirection) + *p = x + return p +} + +func (x PolicyDirection) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PolicyDirection) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[5].Descriptor() +} + +func (PolicyDirection) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[5] +} + +func (x PolicyDirection) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PolicyDirection.Descriptor instead. +func (PolicyDirection) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{5} +} + +type WatchEventRequest_Table_Filter_Type int32 + +const ( + WatchEventRequest_Table_Filter_BEST WatchEventRequest_Table_Filter_Type = 0 + WatchEventRequest_Table_Filter_ADJIN WatchEventRequest_Table_Filter_Type = 1 + WatchEventRequest_Table_Filter_POST_POLICY WatchEventRequest_Table_Filter_Type = 2 +) + +// Enum value maps for WatchEventRequest_Table_Filter_Type. +var ( + WatchEventRequest_Table_Filter_Type_name = map[int32]string{ + 0: "BEST", + 1: "ADJIN", + 2: "POST_POLICY", + } + WatchEventRequest_Table_Filter_Type_value = map[string]int32{ + "BEST": 0, + "ADJIN": 1, + "POST_POLICY": 2, + } +) + +func (x WatchEventRequest_Table_Filter_Type) Enum() *WatchEventRequest_Table_Filter_Type { + p := new(WatchEventRequest_Table_Filter_Type) + *p = x + return p +} + +func (x WatchEventRequest_Table_Filter_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WatchEventRequest_Table_Filter_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[6].Descriptor() +} + +func (WatchEventRequest_Table_Filter_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[6] +} + +func (x WatchEventRequest_Table_Filter_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WatchEventRequest_Table_Filter_Type.Descriptor instead. +func (WatchEventRequest_Table_Filter_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4, 1, 0, 0} +} + +type WatchEventResponse_PeerEvent_Type int32 + +const ( + WatchEventResponse_PeerEvent_UNKNOWN WatchEventResponse_PeerEvent_Type = 0 + WatchEventResponse_PeerEvent_INIT WatchEventResponse_PeerEvent_Type = 1 + WatchEventResponse_PeerEvent_END_OF_INIT WatchEventResponse_PeerEvent_Type = 2 + WatchEventResponse_PeerEvent_STATE WatchEventResponse_PeerEvent_Type = 3 +) + +// Enum value maps for WatchEventResponse_PeerEvent_Type. +var ( + WatchEventResponse_PeerEvent_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "INIT", + 2: "END_OF_INIT", + 3: "STATE", + } + WatchEventResponse_PeerEvent_Type_value = map[string]int32{ + "UNKNOWN": 0, + "INIT": 1, + "END_OF_INIT": 2, + "STATE": 3, + } +) + +func (x WatchEventResponse_PeerEvent_Type) Enum() *WatchEventResponse_PeerEvent_Type { + p := new(WatchEventResponse_PeerEvent_Type) + *p = x + return p +} + +func (x WatchEventResponse_PeerEvent_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WatchEventResponse_PeerEvent_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[7].Descriptor() +} + +func (WatchEventResponse_PeerEvent_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[7] +} + +func (x WatchEventResponse_PeerEvent_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WatchEventResponse_PeerEvent_Type.Descriptor instead. +func (WatchEventResponse_PeerEvent_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{5, 0, 0} +} + +type ResetPeerRequest_SoftResetDirection int32 + +const ( + ResetPeerRequest_IN ResetPeerRequest_SoftResetDirection = 0 + ResetPeerRequest_OUT ResetPeerRequest_SoftResetDirection = 1 + ResetPeerRequest_BOTH ResetPeerRequest_SoftResetDirection = 2 +) + +// Enum value maps for ResetPeerRequest_SoftResetDirection. +var ( + ResetPeerRequest_SoftResetDirection_name = map[int32]string{ + 0: "IN", + 1: "OUT", + 2: "BOTH", + } + ResetPeerRequest_SoftResetDirection_value = map[string]int32{ + "IN": 0, + "OUT": 1, + "BOTH": 2, + } +) + +func (x ResetPeerRequest_SoftResetDirection) Enum() *ResetPeerRequest_SoftResetDirection { + p := new(ResetPeerRequest_SoftResetDirection) + *p = x + return p +} + +func (x ResetPeerRequest_SoftResetDirection) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ResetPeerRequest_SoftResetDirection) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[8].Descriptor() +} + +func (ResetPeerRequest_SoftResetDirection) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[8] +} + +func (x ResetPeerRequest_SoftResetDirection) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ResetPeerRequest_SoftResetDirection.Descriptor instead. +func (ResetPeerRequest_SoftResetDirection) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{12, 0} +} + +// API representation of table.LookupOption +type TableLookupPrefix_Type int32 + +const ( + TableLookupPrefix_EXACT TableLookupPrefix_Type = 0 + TableLookupPrefix_LONGER TableLookupPrefix_Type = 1 + TableLookupPrefix_SHORTER TableLookupPrefix_Type = 2 +) + +// Enum value maps for TableLookupPrefix_Type. +var ( + TableLookupPrefix_Type_name = map[int32]string{ + 0: "EXACT", + 1: "LONGER", + 2: "SHORTER", + } + TableLookupPrefix_Type_value = map[string]int32{ + "EXACT": 0, + "LONGER": 1, + "SHORTER": 2, + } +) + +func (x TableLookupPrefix_Type) Enum() *TableLookupPrefix_Type { + p := new(TableLookupPrefix_Type) + *p = x + return p +} + +func (x TableLookupPrefix_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TableLookupPrefix_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[9].Descriptor() +} + +func (TableLookupPrefix_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[9] +} + +func (x TableLookupPrefix_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TableLookupPrefix_Type.Descriptor instead. +func (TableLookupPrefix_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{29, 0} +} + +type ListPathRequest_SortType int32 + +const ( + ListPathRequest_NONE ListPathRequest_SortType = 0 + ListPathRequest_PREFIX ListPathRequest_SortType = 1 +) + +// Enum value maps for ListPathRequest_SortType. +var ( + ListPathRequest_SortType_name = map[int32]string{ + 0: "NONE", + 1: "PREFIX", + } + ListPathRequest_SortType_value = map[string]int32{ + "NONE": 0, + "PREFIX": 1, + } +) + +func (x ListPathRequest_SortType) Enum() *ListPathRequest_SortType { + p := new(ListPathRequest_SortType) + *p = x + return p +} + +func (x ListPathRequest_SortType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ListPathRequest_SortType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[10].Descriptor() +} + +func (ListPathRequest_SortType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[10] +} + +func (x ListPathRequest_SortType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ListPathRequest_SortType.Descriptor instead. +func (ListPathRequest_SortType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{30, 0} +} + +type EnableMrtRequest_DumpType int32 + +const ( + EnableMrtRequest_UPDATES EnableMrtRequest_DumpType = 0 + EnableMrtRequest_TABLE EnableMrtRequest_DumpType = 1 +) + +// Enum value maps for EnableMrtRequest_DumpType. +var ( + EnableMrtRequest_DumpType_name = map[int32]string{ + 0: "UPDATES", + 1: "TABLE", + } + EnableMrtRequest_DumpType_value = map[string]int32{ + "UPDATES": 0, + "TABLE": 1, + } +) + +func (x EnableMrtRequest_DumpType) Enum() *EnableMrtRequest_DumpType { + p := new(EnableMrtRequest_DumpType) + *p = x + return p +} + +func (x EnableMrtRequest_DumpType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (EnableMrtRequest_DumpType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[11].Descriptor() +} + +func (EnableMrtRequest_DumpType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[11] +} + +func (x EnableMrtRequest_DumpType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use EnableMrtRequest_DumpType.Descriptor instead. +func (EnableMrtRequest_DumpType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{67, 0} +} + +type AddBmpRequest_MonitoringPolicy int32 + +const ( + AddBmpRequest_PRE AddBmpRequest_MonitoringPolicy = 0 + AddBmpRequest_POST AddBmpRequest_MonitoringPolicy = 1 + AddBmpRequest_BOTH AddBmpRequest_MonitoringPolicy = 2 + AddBmpRequest_LOCAL AddBmpRequest_MonitoringPolicy = 3 + AddBmpRequest_ALL AddBmpRequest_MonitoringPolicy = 4 +) + +// Enum value maps for AddBmpRequest_MonitoringPolicy. +var ( + AddBmpRequest_MonitoringPolicy_name = map[int32]string{ + 0: "PRE", + 1: "POST", + 2: "BOTH", + 3: "LOCAL", + 4: "ALL", + } + AddBmpRequest_MonitoringPolicy_value = map[string]int32{ + "PRE": 0, + "POST": 1, + "BOTH": 2, + "LOCAL": 3, + "ALL": 4, + } +) + +func (x AddBmpRequest_MonitoringPolicy) Enum() *AddBmpRequest_MonitoringPolicy { + p := new(AddBmpRequest_MonitoringPolicy) + *p = x + return p +} + +func (x AddBmpRequest_MonitoringPolicy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AddBmpRequest_MonitoringPolicy) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[12].Descriptor() +} + +func (AddBmpRequest_MonitoringPolicy) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[12] +} + +func (x AddBmpRequest_MonitoringPolicy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AddBmpRequest_MonitoringPolicy.Descriptor instead. +func (AddBmpRequest_MonitoringPolicy) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{69, 0} +} + +type Family_Afi int32 + +const ( + Family_AFI_UNKNOWN Family_Afi = 0 + Family_AFI_IP Family_Afi = 1 + Family_AFI_IP6 Family_Afi = 2 + Family_AFI_L2VPN Family_Afi = 25 + Family_AFI_LS Family_Afi = 16388 + Family_AFI_OPAQUE Family_Afi = 16397 +) + +// Enum value maps for Family_Afi. +var ( + Family_Afi_name = map[int32]string{ + 0: "AFI_UNKNOWN", + 1: "AFI_IP", + 2: "AFI_IP6", + 25: "AFI_L2VPN", + 16388: "AFI_LS", + 16397: "AFI_OPAQUE", + } + Family_Afi_value = map[string]int32{ + "AFI_UNKNOWN": 0, + "AFI_IP": 1, + "AFI_IP6": 2, + "AFI_L2VPN": 25, + "AFI_LS": 16388, + "AFI_OPAQUE": 16397, + } +) + +func (x Family_Afi) Enum() *Family_Afi { + p := new(Family_Afi) + *p = x + return p +} + +func (x Family_Afi) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Family_Afi) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[13].Descriptor() +} + +func (Family_Afi) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[13] +} + +func (x Family_Afi) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Family_Afi.Descriptor instead. +func (Family_Afi) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{73, 0} +} + +type Family_Safi int32 + +const ( + Family_SAFI_UNKNOWN Family_Safi = 0 + Family_SAFI_UNICAST Family_Safi = 1 + Family_SAFI_MULTICAST Family_Safi = 2 + Family_SAFI_MPLS_LABEL Family_Safi = 4 + Family_SAFI_ENCAPSULATION Family_Safi = 7 + Family_SAFI_VPLS Family_Safi = 65 + Family_SAFI_EVPN Family_Safi = 70 + Family_SAFI_LS Family_Safi = 71 + Family_SAFI_SR_POLICY Family_Safi = 73 + Family_SAFI_MUP Family_Safi = 85 + Family_SAFI_MPLS_VPN Family_Safi = 128 + Family_SAFI_MPLS_VPN_MULTICAST Family_Safi = 129 + Family_SAFI_ROUTE_TARGET_CONSTRAINTS Family_Safi = 132 + Family_SAFI_FLOW_SPEC_UNICAST Family_Safi = 133 + Family_SAFI_FLOW_SPEC_VPN Family_Safi = 134 + Family_SAFI_KEY_VALUE Family_Safi = 241 +) + +// Enum value maps for Family_Safi. +var ( + Family_Safi_name = map[int32]string{ + 0: "SAFI_UNKNOWN", + 1: "SAFI_UNICAST", + 2: "SAFI_MULTICAST", + 4: "SAFI_MPLS_LABEL", + 7: "SAFI_ENCAPSULATION", + 65: "SAFI_VPLS", + 70: "SAFI_EVPN", + 71: "SAFI_LS", + 73: "SAFI_SR_POLICY", + 85: "SAFI_MUP", + 128: "SAFI_MPLS_VPN", + 129: "SAFI_MPLS_VPN_MULTICAST", + 132: "SAFI_ROUTE_TARGET_CONSTRAINTS", + 133: "SAFI_FLOW_SPEC_UNICAST", + 134: "SAFI_FLOW_SPEC_VPN", + 241: "SAFI_KEY_VALUE", + } + Family_Safi_value = map[string]int32{ + "SAFI_UNKNOWN": 0, + "SAFI_UNICAST": 1, + "SAFI_MULTICAST": 2, + "SAFI_MPLS_LABEL": 4, + "SAFI_ENCAPSULATION": 7, + "SAFI_VPLS": 65, + "SAFI_EVPN": 70, + "SAFI_LS": 71, + "SAFI_SR_POLICY": 73, + "SAFI_MUP": 85, + "SAFI_MPLS_VPN": 128, + "SAFI_MPLS_VPN_MULTICAST": 129, + "SAFI_ROUTE_TARGET_CONSTRAINTS": 132, + "SAFI_FLOW_SPEC_UNICAST": 133, + "SAFI_FLOW_SPEC_VPN": 134, + "SAFI_KEY_VALUE": 241, + } +) + +func (x Family_Safi) Enum() *Family_Safi { + p := new(Family_Safi) + *p = x + return p +} + +func (x Family_Safi) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Family_Safi) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[14].Descriptor() +} + +func (Family_Safi) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[14] +} + +func (x Family_Safi) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Family_Safi.Descriptor instead. +func (Family_Safi) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{73, 1} +} + +type Validation_State int32 + +const ( + Validation_STATE_NONE Validation_State = 0 + Validation_STATE_NOT_FOUND Validation_State = 1 + Validation_STATE_VALID Validation_State = 2 + Validation_STATE_INVALID Validation_State = 3 +) + +// Enum value maps for Validation_State. +var ( + Validation_State_name = map[int32]string{ + 0: "STATE_NONE", + 1: "STATE_NOT_FOUND", + 2: "STATE_VALID", + 3: "STATE_INVALID", + } + Validation_State_value = map[string]int32{ + "STATE_NONE": 0, + "STATE_NOT_FOUND": 1, + "STATE_VALID": 2, + "STATE_INVALID": 3, + } +) + +func (x Validation_State) Enum() *Validation_State { + p := new(Validation_State) + *p = x + return p +} + +func (x Validation_State) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Validation_State) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[15].Descriptor() +} + +func (Validation_State) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[15] +} + +func (x Validation_State) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Validation_State.Descriptor instead. +func (Validation_State) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{74, 0} +} + +type Validation_Reason int32 + +const ( + Validation_REASON_NONE Validation_Reason = 0 + Validation_REASON_ASN Validation_Reason = 1 + Validation_REASON_LENGTH Validation_Reason = 2 +) + +// Enum value maps for Validation_Reason. +var ( + Validation_Reason_name = map[int32]string{ + 0: "REASON_NONE", + 1: "REASON_ASN", + 2: "REASON_LENGTH", + } + Validation_Reason_value = map[string]int32{ + "REASON_NONE": 0, + "REASON_ASN": 1, + "REASON_LENGTH": 2, + } +) + +func (x Validation_Reason) Enum() *Validation_Reason { + p := new(Validation_Reason) + *p = x + return p +} + +func (x Validation_Reason) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Validation_Reason) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[16].Descriptor() +} + +func (Validation_Reason) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[16] +} + +func (x Validation_Reason) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Validation_Reason.Descriptor instead. +func (Validation_Reason) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{74, 1} +} + +type PeerState_SessionState int32 + +const ( + PeerState_UNKNOWN PeerState_SessionState = 0 + PeerState_IDLE PeerState_SessionState = 1 + PeerState_CONNECT PeerState_SessionState = 2 + PeerState_ACTIVE PeerState_SessionState = 3 + PeerState_OPENSENT PeerState_SessionState = 4 + PeerState_OPENCONFIRM PeerState_SessionState = 5 + PeerState_ESTABLISHED PeerState_SessionState = 6 +) + +// Enum value maps for PeerState_SessionState. +var ( + PeerState_SessionState_name = map[int32]string{ + 0: "UNKNOWN", + 1: "IDLE", + 2: "CONNECT", + 3: "ACTIVE", + 4: "OPENSENT", + 5: "OPENCONFIRM", + 6: "ESTABLISHED", + } + PeerState_SessionState_value = map[string]int32{ + "UNKNOWN": 0, + "IDLE": 1, + "CONNECT": 2, + "ACTIVE": 3, + "OPENSENT": 4, + "OPENCONFIRM": 5, + "ESTABLISHED": 6, + } +) + +func (x PeerState_SessionState) Enum() *PeerState_SessionState { + p := new(PeerState_SessionState) + *p = x + return p +} + +func (x PeerState_SessionState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PeerState_SessionState) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[17].Descriptor() +} + +func (PeerState_SessionState) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[17] +} + +func (x PeerState_SessionState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PeerState_SessionState.Descriptor instead. +func (PeerState_SessionState) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{88, 0} +} + +type PeerState_AdminState int32 + +const ( + PeerState_UP PeerState_AdminState = 0 + PeerState_DOWN PeerState_AdminState = 1 + PeerState_PFX_CT PeerState_AdminState = 2 // prefix counter over limit +) + +// Enum value maps for PeerState_AdminState. +var ( + PeerState_AdminState_name = map[int32]string{ + 0: "UP", + 1: "DOWN", + 2: "PFX_CT", + } + PeerState_AdminState_value = map[string]int32{ + "UP": 0, + "DOWN": 1, + "PFX_CT": 2, + } +) + +func (x PeerState_AdminState) Enum() *PeerState_AdminState { + p := new(PeerState_AdminState) + *p = x + return p +} + +func (x PeerState_AdminState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PeerState_AdminState) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[18].Descriptor() +} + +func (PeerState_AdminState) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[18] +} + +func (x PeerState_AdminState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PeerState_AdminState.Descriptor instead. +func (PeerState_AdminState) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{88, 1} +} + +type MatchSet_Type int32 + +const ( + MatchSet_ANY MatchSet_Type = 0 + MatchSet_ALL MatchSet_Type = 1 + MatchSet_INVERT MatchSet_Type = 2 +) + +// Enum value maps for MatchSet_Type. +var ( + MatchSet_Type_name = map[int32]string{ + 0: "ANY", + 1: "ALL", + 2: "INVERT", + } + MatchSet_Type_value = map[string]int32{ + "ANY": 0, + "ALL": 1, + "INVERT": 2, + } +) + +func (x MatchSet_Type) Enum() *MatchSet_Type { + p := new(MatchSet_Type) + *p = x + return p +} + +func (x MatchSet_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MatchSet_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[19].Descriptor() +} + +func (MatchSet_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[19] +} + +func (x MatchSet_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MatchSet_Type.Descriptor instead. +func (MatchSet_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{127, 0} +} + +type AsPathLength_Type int32 + +const ( + AsPathLength_EQ AsPathLength_Type = 0 + AsPathLength_GE AsPathLength_Type = 1 + AsPathLength_LE AsPathLength_Type = 2 +) + +// Enum value maps for AsPathLength_Type. +var ( + AsPathLength_Type_name = map[int32]string{ + 0: "EQ", + 1: "GE", + 2: "LE", + } + AsPathLength_Type_value = map[string]int32{ + "EQ": 0, + "GE": 1, + "LE": 2, + } +) + +func (x AsPathLength_Type) Enum() *AsPathLength_Type { + p := new(AsPathLength_Type) + *p = x + return p +} + +func (x AsPathLength_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AsPathLength_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[20].Descriptor() +} + +func (AsPathLength_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[20] +} + +func (x AsPathLength_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AsPathLength_Type.Descriptor instead. +func (AsPathLength_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{128, 0} +} + +type Conditions_RouteType int32 + +const ( + Conditions_ROUTE_TYPE_NONE Conditions_RouteType = 0 + Conditions_ROUTE_TYPE_INTERNAL Conditions_RouteType = 1 + Conditions_ROUTE_TYPE_EXTERNAL Conditions_RouteType = 2 + Conditions_ROUTE_TYPE_LOCAL Conditions_RouteType = 3 +) + +// Enum value maps for Conditions_RouteType. +var ( + Conditions_RouteType_name = map[int32]string{ + 0: "ROUTE_TYPE_NONE", + 1: "ROUTE_TYPE_INTERNAL", + 2: "ROUTE_TYPE_EXTERNAL", + 3: "ROUTE_TYPE_LOCAL", + } + Conditions_RouteType_value = map[string]int32{ + "ROUTE_TYPE_NONE": 0, + "ROUTE_TYPE_INTERNAL": 1, + "ROUTE_TYPE_EXTERNAL": 2, + "ROUTE_TYPE_LOCAL": 3, + } +) + +func (x Conditions_RouteType) Enum() *Conditions_RouteType { + p := new(Conditions_RouteType) + *p = x + return p +} + +func (x Conditions_RouteType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Conditions_RouteType) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[21].Descriptor() +} + +func (Conditions_RouteType) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[21] +} + +func (x Conditions_RouteType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Conditions_RouteType.Descriptor instead. +func (Conditions_RouteType) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{129, 0} +} + +type CommunityAction_Type int32 + +const ( + CommunityAction_ADD CommunityAction_Type = 0 + CommunityAction_REMOVE CommunityAction_Type = 1 + CommunityAction_REPLACE CommunityAction_Type = 2 +) + +// Enum value maps for CommunityAction_Type. +var ( + CommunityAction_Type_name = map[int32]string{ + 0: "ADD", + 1: "REMOVE", + 2: "REPLACE", + } + CommunityAction_Type_value = map[string]int32{ + "ADD": 0, + "REMOVE": 1, + "REPLACE": 2, + } +) + +func (x CommunityAction_Type) Enum() *CommunityAction_Type { + p := new(CommunityAction_Type) + *p = x + return p +} + +func (x CommunityAction_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CommunityAction_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[22].Descriptor() +} + +func (CommunityAction_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[22] +} + +func (x CommunityAction_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CommunityAction_Type.Descriptor instead. +func (CommunityAction_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{130, 0} +} + +type MedAction_Type int32 + +const ( + MedAction_MOD MedAction_Type = 0 + MedAction_REPLACE MedAction_Type = 1 +) + +// Enum value maps for MedAction_Type. +var ( + MedAction_Type_name = map[int32]string{ + 0: "MOD", + 1: "REPLACE", + } + MedAction_Type_value = map[string]int32{ + "MOD": 0, + "REPLACE": 1, + } +) + +func (x MedAction_Type) Enum() *MedAction_Type { + p := new(MedAction_Type) + *p = x + return p +} + +func (x MedAction_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MedAction_Type) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[23].Descriptor() +} + +func (MedAction_Type) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[23] +} + +func (x MedAction_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MedAction_Type.Descriptor instead. +func (MedAction_Type) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{131, 0} +} + +type SetLogLevelRequest_Level int32 + +const ( + SetLogLevelRequest_PANIC SetLogLevelRequest_Level = 0 + SetLogLevelRequest_FATAL SetLogLevelRequest_Level = 1 + SetLogLevelRequest_ERROR SetLogLevelRequest_Level = 2 + SetLogLevelRequest_WARN SetLogLevelRequest_Level = 3 + SetLogLevelRequest_INFO SetLogLevelRequest_Level = 4 + SetLogLevelRequest_DEBUG SetLogLevelRequest_Level = 5 + SetLogLevelRequest_TRACE SetLogLevelRequest_Level = 6 +) + +// Enum value maps for SetLogLevelRequest_Level. +var ( + SetLogLevelRequest_Level_name = map[int32]string{ + 0: "PANIC", + 1: "FATAL", + 2: "ERROR", + 3: "WARN", + 4: "INFO", + 5: "DEBUG", + 6: "TRACE", + } + SetLogLevelRequest_Level_value = map[string]int32{ + "PANIC": 0, + "FATAL": 1, + "ERROR": 2, + "WARN": 3, + "INFO": 4, + "DEBUG": 5, + "TRACE": 6, + } +) + +func (x SetLogLevelRequest_Level) Enum() *SetLogLevelRequest_Level { + p := new(SetLogLevelRequest_Level) + *p = x + return p +} + +func (x SetLogLevelRequest_Level) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SetLogLevelRequest_Level) Descriptor() protoreflect.EnumDescriptor { + return file_gobgp_proto_enumTypes[24].Descriptor() +} + +func (SetLogLevelRequest_Level) Type() protoreflect.EnumType { + return &file_gobgp_proto_enumTypes[24] +} + +func (x SetLogLevelRequest_Level) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SetLogLevelRequest_Level.Descriptor instead. +func (SetLogLevelRequest_Level) EnumDescriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{148, 0} +} + +type StartBgpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Global *Global `protobuf:"bytes,1,opt,name=global,proto3" json:"global,omitempty"` +} + +func (x *StartBgpRequest) Reset() { + *x = StartBgpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StartBgpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartBgpRequest) ProtoMessage() {} + +func (x *StartBgpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 StartBgpRequest.ProtoReflect.Descriptor instead. +func (*StartBgpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{0} +} + +func (x *StartBgpRequest) GetGlobal() *Global { + if x != nil { + return x.Global + } + return nil +} + +type StopBgpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *StopBgpRequest) Reset() { + *x = StopBgpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StopBgpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StopBgpRequest) ProtoMessage() {} + +func (x *StopBgpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 StopBgpRequest.ProtoReflect.Descriptor instead. +func (*StopBgpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{1} +} + +type GetBgpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetBgpRequest) Reset() { + *x = GetBgpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBgpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBgpRequest) ProtoMessage() {} + +func (x *GetBgpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 GetBgpRequest.ProtoReflect.Descriptor instead. +func (*GetBgpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{2} +} + +type GetBgpResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Global *Global `protobuf:"bytes,1,opt,name=global,proto3" json:"global,omitempty"` +} + +func (x *GetBgpResponse) Reset() { + *x = GetBgpResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetBgpResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetBgpResponse) ProtoMessage() {} + +func (x *GetBgpResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 GetBgpResponse.ProtoReflect.Descriptor instead. +func (*GetBgpResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{3} +} + +func (x *GetBgpResponse) GetGlobal() *Global { + if x != nil { + return x.Global + } + return nil +} + +type WatchEventRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Peer *WatchEventRequest_Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` + Table *WatchEventRequest_Table `protobuf:"bytes,2,opt,name=table,proto3" json:"table,omitempty"` +} + +func (x *WatchEventRequest) Reset() { + *x = WatchEventRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventRequest) ProtoMessage() {} + +func (x *WatchEventRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 WatchEventRequest.ProtoReflect.Descriptor instead. +func (*WatchEventRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4} +} + +func (x *WatchEventRequest) GetPeer() *WatchEventRequest_Peer { + if x != nil { + return x.Peer + } + return nil +} + +func (x *WatchEventRequest) GetTable() *WatchEventRequest_Table { + if x != nil { + return x.Table + } + return nil +} + +type WatchEventResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Event: + // *WatchEventResponse_Peer + // *WatchEventResponse_Table + Event isWatchEventResponse_Event `protobuf_oneof:"event"` +} + +func (x *WatchEventResponse) Reset() { + *x = WatchEventResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventResponse) ProtoMessage() {} + +func (x *WatchEventResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 WatchEventResponse.ProtoReflect.Descriptor instead. +func (*WatchEventResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{5} +} + +func (m *WatchEventResponse) GetEvent() isWatchEventResponse_Event { + if m != nil { + return m.Event + } + return nil +} + +func (x *WatchEventResponse) GetPeer() *WatchEventResponse_PeerEvent { + if x, ok := x.GetEvent().(*WatchEventResponse_Peer); ok { + return x.Peer + } + return nil +} + +func (x *WatchEventResponse) GetTable() *WatchEventResponse_TableEvent { + if x, ok := x.GetEvent().(*WatchEventResponse_Table); ok { + return x.Table + } + return nil +} + +type isWatchEventResponse_Event interface { + isWatchEventResponse_Event() +} + +type WatchEventResponse_Peer struct { + Peer *WatchEventResponse_PeerEvent `protobuf:"bytes,2,opt,name=peer,proto3,oneof"` +} + +type WatchEventResponse_Table struct { + Table *WatchEventResponse_TableEvent `protobuf:"bytes,3,opt,name=table,proto3,oneof"` +} + +func (*WatchEventResponse_Peer) isWatchEventResponse_Event() {} + +func (*WatchEventResponse_Table) isWatchEventResponse_Event() {} + +type AddPeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Peer *Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` +} + +func (x *AddPeerRequest) Reset() { + *x = AddPeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPeerRequest) ProtoMessage() {} + +func (x *AddPeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 AddPeerRequest.ProtoReflect.Descriptor instead. +func (*AddPeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{6} +} + +func (x *AddPeerRequest) GetPeer() *Peer { + if x != nil { + return x.Peer + } + return nil +} + +type DeletePeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Interface string `protobuf:"bytes,2,opt,name=interface,proto3" json:"interface,omitempty"` +} + +func (x *DeletePeerRequest) Reset() { + *x = DeletePeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePeerRequest) ProtoMessage() {} + +func (x *DeletePeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 DeletePeerRequest.ProtoReflect.Descriptor instead. +func (*DeletePeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{7} +} + +func (x *DeletePeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DeletePeerRequest) GetInterface() string { + if x != nil { + return x.Interface + } + return "" +} + +type ListPeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + EnableAdvertised bool `protobuf:"varint,2,opt,name=enableAdvertised,proto3" json:"enableAdvertised,omitempty"` +} + +func (x *ListPeerRequest) Reset() { + *x = ListPeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPeerRequest) ProtoMessage() {} + +func (x *ListPeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 ListPeerRequest.ProtoReflect.Descriptor instead. +func (*ListPeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{8} +} + +func (x *ListPeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *ListPeerRequest) GetEnableAdvertised() bool { + if x != nil { + return x.EnableAdvertised + } + return false +} + +type ListPeerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Peer *Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` +} + +func (x *ListPeerResponse) Reset() { + *x = ListPeerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPeerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPeerResponse) ProtoMessage() {} + +func (x *ListPeerResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 ListPeerResponse.ProtoReflect.Descriptor instead. +func (*ListPeerResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{9} +} + +func (x *ListPeerResponse) GetPeer() *Peer { + if x != nil { + return x.Peer + } + return nil +} + +type UpdatePeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Peer *Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` + // Calls SoftResetIn after updating the peer configuration if needed. + DoSoftResetIn bool `protobuf:"varint,2,opt,name=do_soft_reset_in,json=doSoftResetIn,proto3" json:"do_soft_reset_in,omitempty"` +} + +func (x *UpdatePeerRequest) Reset() { + *x = UpdatePeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdatePeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePeerRequest) ProtoMessage() {} + +func (x *UpdatePeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 UpdatePeerRequest.ProtoReflect.Descriptor instead. +func (*UpdatePeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{10} +} + +func (x *UpdatePeerRequest) GetPeer() *Peer { + if x != nil { + return x.Peer + } + return nil +} + +func (x *UpdatePeerRequest) GetDoSoftResetIn() bool { + if x != nil { + return x.DoSoftResetIn + } + return false +} + +type UpdatePeerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Indicates whether calling SoftResetIn is required due to this update. If + // "true" is set, the client should call SoftResetIn manually. If + // "do_soft_reset_in = true" is set in the request, always returned with + // "false". + NeedsSoftResetIn bool `protobuf:"varint,1,opt,name=needs_soft_reset_in,json=needsSoftResetIn,proto3" json:"needs_soft_reset_in,omitempty"` +} + +func (x *UpdatePeerResponse) Reset() { + *x = UpdatePeerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdatePeerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePeerResponse) ProtoMessage() {} + +func (x *UpdatePeerResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 UpdatePeerResponse.ProtoReflect.Descriptor instead. +func (*UpdatePeerResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{11} +} + +func (x *UpdatePeerResponse) GetNeedsSoftResetIn() bool { + if x != nil { + return x.NeedsSoftResetIn + } + return false +} + +type ResetPeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Communication string `protobuf:"bytes,2,opt,name=communication,proto3" json:"communication,omitempty"` + Soft bool `protobuf:"varint,3,opt,name=soft,proto3" json:"soft,omitempty"` + Direction ResetPeerRequest_SoftResetDirection `protobuf:"varint,4,opt,name=direction,proto3,enum=apipb.ResetPeerRequest_SoftResetDirection" json:"direction,omitempty"` +} + +func (x *ResetPeerRequest) Reset() { + *x = ResetPeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetPeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetPeerRequest) ProtoMessage() {} + +func (x *ResetPeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 ResetPeerRequest.ProtoReflect.Descriptor instead. +func (*ResetPeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{12} +} + +func (x *ResetPeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *ResetPeerRequest) GetCommunication() string { + if x != nil { + return x.Communication + } + return "" +} + +func (x *ResetPeerRequest) GetSoft() bool { + if x != nil { + return x.Soft + } + return false +} + +func (x *ResetPeerRequest) GetDirection() ResetPeerRequest_SoftResetDirection { + if x != nil { + return x.Direction + } + return ResetPeerRequest_IN +} + +type ShutdownPeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Communication string `protobuf:"bytes,2,opt,name=communication,proto3" json:"communication,omitempty"` +} + +func (x *ShutdownPeerRequest) Reset() { + *x = ShutdownPeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ShutdownPeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShutdownPeerRequest) ProtoMessage() {} + +func (x *ShutdownPeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 ShutdownPeerRequest.ProtoReflect.Descriptor instead. +func (*ShutdownPeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{13} +} + +func (x *ShutdownPeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *ShutdownPeerRequest) GetCommunication() string { + if x != nil { + return x.Communication + } + return "" +} + +type EnablePeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *EnablePeerRequest) Reset() { + *x = EnablePeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnablePeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnablePeerRequest) ProtoMessage() {} + +func (x *EnablePeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 EnablePeerRequest.ProtoReflect.Descriptor instead. +func (*EnablePeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{14} +} + +func (x *EnablePeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type DisablePeerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Communication string `protobuf:"bytes,2,opt,name=communication,proto3" json:"communication,omitempty"` +} + +func (x *DisablePeerRequest) Reset() { + *x = DisablePeerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisablePeerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisablePeerRequest) ProtoMessage() {} + +func (x *DisablePeerRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_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 DisablePeerRequest.ProtoReflect.Descriptor instead. +func (*DisablePeerRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{15} +} + +func (x *DisablePeerRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DisablePeerRequest) GetCommunication() string { + if x != nil { + return x.Communication + } + return "" +} + +type AddPeerGroupRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` +} + +func (x *AddPeerGroupRequest) Reset() { + *x = AddPeerGroupRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPeerGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPeerGroupRequest) ProtoMessage() {} + +func (x *AddPeerGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[16] + 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 AddPeerGroupRequest.ProtoReflect.Descriptor instead. +func (*AddPeerGroupRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{16} +} + +func (x *AddPeerGroupRequest) GetPeerGroup() *PeerGroup { + if x != nil { + return x.PeerGroup + } + return nil +} + +type DeletePeerGroupRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *DeletePeerGroupRequest) Reset() { + *x = DeletePeerGroupRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePeerGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePeerGroupRequest) ProtoMessage() {} + +func (x *DeletePeerGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[17] + 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 DeletePeerGroupRequest.ProtoReflect.Descriptor instead. +func (*DeletePeerGroupRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{17} +} + +func (x *DeletePeerGroupRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type UpdatePeerGroupRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` + DoSoftResetIn bool `protobuf:"varint,2,opt,name=do_soft_reset_in,json=doSoftResetIn,proto3" json:"do_soft_reset_in,omitempty"` +} + +func (x *UpdatePeerGroupRequest) Reset() { + *x = UpdatePeerGroupRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdatePeerGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePeerGroupRequest) ProtoMessage() {} + +func (x *UpdatePeerGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[18] + 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 UpdatePeerGroupRequest.ProtoReflect.Descriptor instead. +func (*UpdatePeerGroupRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{18} +} + +func (x *UpdatePeerGroupRequest) GetPeerGroup() *PeerGroup { + if x != nil { + return x.PeerGroup + } + return nil +} + +func (x *UpdatePeerGroupRequest) GetDoSoftResetIn() bool { + if x != nil { + return x.DoSoftResetIn + } + return false +} + +type UpdatePeerGroupResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NeedsSoftResetIn bool `protobuf:"varint,1,opt,name=needs_soft_reset_in,json=needsSoftResetIn,proto3" json:"needs_soft_reset_in,omitempty"` +} + +func (x *UpdatePeerGroupResponse) Reset() { + *x = UpdatePeerGroupResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdatePeerGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdatePeerGroupResponse) ProtoMessage() {} + +func (x *UpdatePeerGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[19] + 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 UpdatePeerGroupResponse.ProtoReflect.Descriptor instead. +func (*UpdatePeerGroupResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{19} +} + +func (x *UpdatePeerGroupResponse) GetNeedsSoftResetIn() bool { + if x != nil { + return x.NeedsSoftResetIn + } + return false +} + +type ListPeerGroupRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerGroupName string `protobuf:"bytes,1,opt,name=peer_group_name,json=peerGroupName,proto3" json:"peer_group_name,omitempty"` +} + +func (x *ListPeerGroupRequest) Reset() { + *x = ListPeerGroupRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPeerGroupRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPeerGroupRequest) ProtoMessage() {} + +func (x *ListPeerGroupRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[20] + 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 ListPeerGroupRequest.ProtoReflect.Descriptor instead. +func (*ListPeerGroupRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{20} +} + +func (x *ListPeerGroupRequest) GetPeerGroupName() string { + if x != nil { + return x.PeerGroupName + } + return "" +} + +type ListPeerGroupResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerGroup *PeerGroup `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` +} + +func (x *ListPeerGroupResponse) Reset() { + *x = ListPeerGroupResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPeerGroupResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPeerGroupResponse) ProtoMessage() {} + +func (x *ListPeerGroupResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[21] + 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 ListPeerGroupResponse.ProtoReflect.Descriptor instead. +func (*ListPeerGroupResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{21} +} + +func (x *ListPeerGroupResponse) GetPeerGroup() *PeerGroup { + if x != nil { + return x.PeerGroup + } + return nil +} + +type AddDynamicNeighborRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DynamicNeighbor *DynamicNeighbor `protobuf:"bytes,1,opt,name=dynamic_neighbor,json=dynamicNeighbor,proto3" json:"dynamic_neighbor,omitempty"` +} + +func (x *AddDynamicNeighborRequest) Reset() { + *x = AddDynamicNeighborRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddDynamicNeighborRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddDynamicNeighborRequest) ProtoMessage() {} + +func (x *AddDynamicNeighborRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[22] + 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 AddDynamicNeighborRequest.ProtoReflect.Descriptor instead. +func (*AddDynamicNeighborRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{22} +} + +func (x *AddDynamicNeighborRequest) GetDynamicNeighbor() *DynamicNeighbor { + if x != nil { + return x.DynamicNeighbor + } + return nil +} + +type DeleteDynamicNeighborRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` + PeerGroup string `protobuf:"bytes,2,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` +} + +func (x *DeleteDynamicNeighborRequest) Reset() { + *x = DeleteDynamicNeighborRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteDynamicNeighborRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteDynamicNeighborRequest) ProtoMessage() {} + +func (x *DeleteDynamicNeighborRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[23] + 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 DeleteDynamicNeighborRequest.ProtoReflect.Descriptor instead. +func (*DeleteDynamicNeighborRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{23} +} + +func (x *DeleteDynamicNeighborRequest) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *DeleteDynamicNeighborRequest) GetPeerGroup() string { + if x != nil { + return x.PeerGroup + } + return "" +} + +type ListDynamicNeighborRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PeerGroup string `protobuf:"bytes,1,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` +} + +func (x *ListDynamicNeighborRequest) Reset() { + *x = ListDynamicNeighborRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDynamicNeighborRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDynamicNeighborRequest) ProtoMessage() {} + +func (x *ListDynamicNeighborRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[24] + 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 ListDynamicNeighborRequest.ProtoReflect.Descriptor instead. +func (*ListDynamicNeighborRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{24} +} + +func (x *ListDynamicNeighborRequest) GetPeerGroup() string { + if x != nil { + return x.PeerGroup + } + return "" +} + +type ListDynamicNeighborResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DynamicNeighbor *DynamicNeighbor `protobuf:"bytes,1,opt,name=dynamic_neighbor,json=dynamicNeighbor,proto3" json:"dynamic_neighbor,omitempty"` +} + +func (x *ListDynamicNeighborResponse) Reset() { + *x = ListDynamicNeighborResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDynamicNeighborResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDynamicNeighborResponse) ProtoMessage() {} + +func (x *ListDynamicNeighborResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[25] + 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 ListDynamicNeighborResponse.ProtoReflect.Descriptor instead. +func (*ListDynamicNeighborResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{25} +} + +func (x *ListDynamicNeighborResponse) GetDynamicNeighbor() *DynamicNeighbor { + if x != nil { + return x.DynamicNeighbor + } + return nil +} + +type AddPathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TableType TableType `protobuf:"varint,1,opt,name=table_type,json=tableType,proto3,enum=apipb.TableType" json:"table_type,omitempty"` + VrfId string `protobuf:"bytes,2,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + Path *Path `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` +} + +func (x *AddPathRequest) Reset() { + *x = AddPathRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathRequest) ProtoMessage() {} + +func (x *AddPathRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[26] + 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 AddPathRequest.ProtoReflect.Descriptor instead. +func (*AddPathRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{26} +} + +func (x *AddPathRequest) GetTableType() TableType { + if x != nil { + return x.TableType + } + return TableType_GLOBAL +} + +func (x *AddPathRequest) GetVrfId() string { + if x != nil { + return x.VrfId + } + return "" +} + +func (x *AddPathRequest) GetPath() *Path { + if x != nil { + return x.Path + } + return nil +} + +type AddPathResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid []byte `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` +} + +func (x *AddPathResponse) Reset() { + *x = AddPathResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathResponse) ProtoMessage() {} + +func (x *AddPathResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[27] + 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 AddPathResponse.ProtoReflect.Descriptor instead. +func (*AddPathResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{27} +} + +func (x *AddPathResponse) GetUuid() []byte { + if x != nil { + return x.Uuid + } + return nil +} + +type DeletePathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TableType TableType `protobuf:"varint,1,opt,name=table_type,json=tableType,proto3,enum=apipb.TableType" json:"table_type,omitempty"` + VrfId string `protobuf:"bytes,2,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + Family *Family `protobuf:"bytes,3,opt,name=family,proto3" json:"family,omitempty"` + Path *Path `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` + Uuid []byte `protobuf:"bytes,5,opt,name=uuid,proto3" json:"uuid,omitempty"` +} + +func (x *DeletePathRequest) Reset() { + *x = DeletePathRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePathRequest) ProtoMessage() {} + +func (x *DeletePathRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[28] + 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 DeletePathRequest.ProtoReflect.Descriptor instead. +func (*DeletePathRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{28} +} + +func (x *DeletePathRequest) GetTableType() TableType { + if x != nil { + return x.TableType + } + return TableType_GLOBAL +} + +func (x *DeletePathRequest) GetVrfId() string { + if x != nil { + return x.VrfId + } + return "" +} + +func (x *DeletePathRequest) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *DeletePathRequest) GetPath() *Path { + if x != nil { + return x.Path + } + return nil +} + +func (x *DeletePathRequest) GetUuid() []byte { + if x != nil { + return x.Uuid + } + return nil +} + +// API representation of table.LookupPrefix +type TableLookupPrefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` + Type TableLookupPrefix_Type `protobuf:"varint,2,opt,name=type,proto3,enum=apipb.TableLookupPrefix_Type" json:"type,omitempty"` +} + +func (x *TableLookupPrefix) Reset() { + *x = TableLookupPrefix{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TableLookupPrefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TableLookupPrefix) ProtoMessage() {} + +func (x *TableLookupPrefix) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[29] + 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 TableLookupPrefix.ProtoReflect.Descriptor instead. +func (*TableLookupPrefix) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{29} +} + +func (x *TableLookupPrefix) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *TableLookupPrefix) GetType() TableLookupPrefix_Type { + if x != nil { + return x.Type + } + return TableLookupPrefix_EXACT +} + +type ListPathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TableType TableType `protobuf:"varint,1,opt,name=table_type,json=tableType,proto3,enum=apipb.TableType" json:"table_type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Family *Family `protobuf:"bytes,3,opt,name=family,proto3" json:"family,omitempty"` + Prefixes []*TableLookupPrefix `protobuf:"bytes,4,rep,name=prefixes,proto3" json:"prefixes,omitempty"` + SortType ListPathRequest_SortType `protobuf:"varint,5,opt,name=sort_type,json=sortType,proto3,enum=apipb.ListPathRequest_SortType" json:"sort_type,omitempty"` + EnableFiltered bool `protobuf:"varint,6,opt,name=enable_filtered,json=enableFiltered,proto3" json:"enable_filtered,omitempty"` + EnableNlriBinary bool `protobuf:"varint,7,opt,name=enable_nlri_binary,json=enableNlriBinary,proto3" json:"enable_nlri_binary,omitempty"` + EnableAttributeBinary bool `protobuf:"varint,8,opt,name=enable_attribute_binary,json=enableAttributeBinary,proto3" json:"enable_attribute_binary,omitempty"` +} + +func (x *ListPathRequest) Reset() { + *x = ListPathRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPathRequest) ProtoMessage() {} + +func (x *ListPathRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[30] + 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 ListPathRequest.ProtoReflect.Descriptor instead. +func (*ListPathRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{30} +} + +func (x *ListPathRequest) GetTableType() TableType { + if x != nil { + return x.TableType + } + return TableType_GLOBAL +} + +func (x *ListPathRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ListPathRequest) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *ListPathRequest) GetPrefixes() []*TableLookupPrefix { + if x != nil { + return x.Prefixes + } + return nil +} + +func (x *ListPathRequest) GetSortType() ListPathRequest_SortType { + if x != nil { + return x.SortType + } + return ListPathRequest_NONE +} + +func (x *ListPathRequest) GetEnableFiltered() bool { + if x != nil { + return x.EnableFiltered + } + return false +} + +func (x *ListPathRequest) GetEnableNlriBinary() bool { + if x != nil { + return x.EnableNlriBinary + } + return false +} + +func (x *ListPathRequest) GetEnableAttributeBinary() bool { + if x != nil { + return x.EnableAttributeBinary + } + return false +} + +type ListPathResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Destination *Destination `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"` +} + +func (x *ListPathResponse) Reset() { + *x = ListPathResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPathResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPathResponse) ProtoMessage() {} + +func (x *ListPathResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[31] + 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 ListPathResponse.ProtoReflect.Descriptor instead. +func (*ListPathResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{31} +} + +func (x *ListPathResponse) GetDestination() *Destination { + if x != nil { + return x.Destination + } + return nil +} + +type AddPathStreamRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TableType TableType `protobuf:"varint,1,opt,name=table_type,json=tableType,proto3,enum=apipb.TableType" json:"table_type,omitempty"` + VrfId string `protobuf:"bytes,2,opt,name=vrf_id,json=vrfId,proto3" json:"vrf_id,omitempty"` + Paths []*Path `protobuf:"bytes,3,rep,name=paths,proto3" json:"paths,omitempty"` +} + +func (x *AddPathStreamRequest) Reset() { + *x = AddPathStreamRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathStreamRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathStreamRequest) ProtoMessage() {} + +func (x *AddPathStreamRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[32] + 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 AddPathStreamRequest.ProtoReflect.Descriptor instead. +func (*AddPathStreamRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{32} +} + +func (x *AddPathStreamRequest) GetTableType() TableType { + if x != nil { + return x.TableType + } + return TableType_GLOBAL +} + +func (x *AddPathStreamRequest) GetVrfId() string { + if x != nil { + return x.VrfId + } + return "" +} + +func (x *AddPathStreamRequest) GetPaths() []*Path { + if x != nil { + return x.Paths + } + return nil +} + +type GetTableRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TableType TableType `protobuf:"varint,1,opt,name=table_type,json=tableType,proto3,enum=apipb.TableType" json:"table_type,omitempty"` + Family *Family `protobuf:"bytes,2,opt,name=family,proto3" json:"family,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetTableRequest) Reset() { + *x = GetTableRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTableRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTableRequest) ProtoMessage() {} + +func (x *GetTableRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[33] + 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 GetTableRequest.ProtoReflect.Descriptor instead. +func (*GetTableRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{33} +} + +func (x *GetTableRequest) GetTableType() TableType { + if x != nil { + return x.TableType + } + return TableType_GLOBAL +} + +func (x *GetTableRequest) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *GetTableRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GetTableResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NumDestination uint64 `protobuf:"varint,1,opt,name=num_destination,json=numDestination,proto3" json:"num_destination,omitempty"` + NumPath uint64 `protobuf:"varint,2,opt,name=num_path,json=numPath,proto3" json:"num_path,omitempty"` + NumAccepted uint64 `protobuf:"varint,3,opt,name=num_accepted,json=numAccepted,proto3" json:"num_accepted,omitempty"` // only meaningful when type == ADJ_IN +} + +func (x *GetTableResponse) Reset() { + *x = GetTableResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTableResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTableResponse) ProtoMessage() {} + +func (x *GetTableResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[34] + 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 GetTableResponse.ProtoReflect.Descriptor instead. +func (*GetTableResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{34} +} + +func (x *GetTableResponse) GetNumDestination() uint64 { + if x != nil { + return x.NumDestination + } + return 0 +} + +func (x *GetTableResponse) GetNumPath() uint64 { + if x != nil { + return x.NumPath + } + return 0 +} + +func (x *GetTableResponse) GetNumAccepted() uint64 { + if x != nil { + return x.NumAccepted + } + return 0 +} + +type AddVrfRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Vrf *Vrf `protobuf:"bytes,1,opt,name=vrf,proto3" json:"vrf,omitempty"` +} + +func (x *AddVrfRequest) Reset() { + *x = AddVrfRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddVrfRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddVrfRequest) ProtoMessage() {} + +func (x *AddVrfRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[35] + 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 AddVrfRequest.ProtoReflect.Descriptor instead. +func (*AddVrfRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{35} +} + +func (x *AddVrfRequest) GetVrf() *Vrf { + if x != nil { + return x.Vrf + } + return nil +} + +type DeleteVrfRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *DeleteVrfRequest) Reset() { + *x = DeleteVrfRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteVrfRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteVrfRequest) ProtoMessage() {} + +func (x *DeleteVrfRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[36] + 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 DeleteVrfRequest.ProtoReflect.Descriptor instead. +func (*DeleteVrfRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{36} +} + +func (x *DeleteVrfRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListVrfRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ListVrfRequest) Reset() { + *x = ListVrfRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListVrfRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListVrfRequest) ProtoMessage() {} + +func (x *ListVrfRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[37] + 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 ListVrfRequest.ProtoReflect.Descriptor instead. +func (*ListVrfRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{37} +} + +func (x *ListVrfRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListVrfResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Vrf *Vrf `protobuf:"bytes,1,opt,name=vrf,proto3" json:"vrf,omitempty"` +} + +func (x *ListVrfResponse) Reset() { + *x = ListVrfResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListVrfResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListVrfResponse) ProtoMessage() {} + +func (x *ListVrfResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[38] + 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 ListVrfResponse.ProtoReflect.Descriptor instead. +func (*ListVrfResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{38} +} + +func (x *ListVrfResponse) GetVrf() *Vrf { + if x != nil { + return x.Vrf + } + return nil +} + +type AddPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy *Policy `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` + // if this flag is set, gobgpd won't define new statements + // but refer existing statements using statement's names in this arguments. + ReferExistingStatements bool `protobuf:"varint,2,opt,name=refer_existing_statements,json=referExistingStatements,proto3" json:"refer_existing_statements,omitempty"` +} + +func (x *AddPolicyRequest) Reset() { + *x = AddPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPolicyRequest) ProtoMessage() {} + +func (x *AddPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[39] + 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 AddPolicyRequest.ProtoReflect.Descriptor instead. +func (*AddPolicyRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{39} +} + +func (x *AddPolicyRequest) GetPolicy() *Policy { + if x != nil { + return x.Policy + } + return nil +} + +func (x *AddPolicyRequest) GetReferExistingStatements() bool { + if x != nil { + return x.ReferExistingStatements + } + return false +} + +type DeletePolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy *Policy `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` + // if this flag is set, gobgpd won't delete any statements + // even if some statements get not used by any policy by this operation. + PreserveStatements bool `protobuf:"varint,2,opt,name=preserve_statements,json=preserveStatements,proto3" json:"preserve_statements,omitempty"` + All bool `protobuf:"varint,3,opt,name=all,proto3" json:"all,omitempty"` +} + +func (x *DeletePolicyRequest) Reset() { + *x = DeletePolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePolicyRequest) ProtoMessage() {} + +func (x *DeletePolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[40] + 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 DeletePolicyRequest.ProtoReflect.Descriptor instead. +func (*DeletePolicyRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{40} +} + +func (x *DeletePolicyRequest) GetPolicy() *Policy { + if x != nil { + return x.Policy + } + return nil +} + +func (x *DeletePolicyRequest) GetPreserveStatements() bool { + if x != nil { + return x.PreserveStatements + } + return false +} + +func (x *DeletePolicyRequest) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +type ListPolicyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ListPolicyRequest) Reset() { + *x = ListPolicyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPolicyRequest) ProtoMessage() {} + +func (x *ListPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[41] + 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 ListPolicyRequest.ProtoReflect.Descriptor instead. +func (*ListPolicyRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{41} +} + +func (x *ListPolicyRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListPolicyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy *Policy `protobuf:"bytes,1,opt,name=policy,proto3" json:"policy,omitempty"` +} + +func (x *ListPolicyResponse) Reset() { + *x = ListPolicyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPolicyResponse) ProtoMessage() {} + +func (x *ListPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[42] + 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 ListPolicyResponse.ProtoReflect.Descriptor instead. +func (*ListPolicyResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{42} +} + +func (x *ListPolicyResponse) GetPolicy() *Policy { + if x != nil { + return x.Policy + } + return nil +} + +type SetPoliciesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedSets []*DefinedSet `protobuf:"bytes,1,rep,name=defined_sets,json=definedSets,proto3" json:"defined_sets,omitempty"` + Policies []*Policy `protobuf:"bytes,2,rep,name=policies,proto3" json:"policies,omitempty"` + Assignments []*PolicyAssignment `protobuf:"bytes,3,rep,name=assignments,proto3" json:"assignments,omitempty"` +} + +func (x *SetPoliciesRequest) Reset() { + *x = SetPoliciesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetPoliciesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetPoliciesRequest) ProtoMessage() {} + +func (x *SetPoliciesRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[43] + 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 SetPoliciesRequest.ProtoReflect.Descriptor instead. +func (*SetPoliciesRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{43} +} + +func (x *SetPoliciesRequest) GetDefinedSets() []*DefinedSet { + if x != nil { + return x.DefinedSets + } + return nil +} + +func (x *SetPoliciesRequest) GetPolicies() []*Policy { + if x != nil { + return x.Policies + } + return nil +} + +func (x *SetPoliciesRequest) GetAssignments() []*PolicyAssignment { + if x != nil { + return x.Assignments + } + return nil +} + +type AddDefinedSetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedSet *DefinedSet `protobuf:"bytes,1,opt,name=defined_set,json=definedSet,proto3" json:"defined_set,omitempty"` +} + +func (x *AddDefinedSetRequest) Reset() { + *x = AddDefinedSetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddDefinedSetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddDefinedSetRequest) ProtoMessage() {} + +func (x *AddDefinedSetRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[44] + 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 AddDefinedSetRequest.ProtoReflect.Descriptor instead. +func (*AddDefinedSetRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{44} +} + +func (x *AddDefinedSetRequest) GetDefinedSet() *DefinedSet { + if x != nil { + return x.DefinedSet + } + return nil +} + +type DeleteDefinedSetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedSet *DefinedSet `protobuf:"bytes,1,opt,name=defined_set,json=definedSet,proto3" json:"defined_set,omitempty"` + All bool `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"` +} + +func (x *DeleteDefinedSetRequest) Reset() { + *x = DeleteDefinedSetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteDefinedSetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteDefinedSetRequest) ProtoMessage() {} + +func (x *DeleteDefinedSetRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[45] + 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 DeleteDefinedSetRequest.ProtoReflect.Descriptor instead. +func (*DeleteDefinedSetRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{45} +} + +func (x *DeleteDefinedSetRequest) GetDefinedSet() *DefinedSet { + if x != nil { + return x.DefinedSet + } + return nil +} + +func (x *DeleteDefinedSetRequest) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +type ListDefinedSetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedType DefinedType `protobuf:"varint,1,opt,name=defined_type,json=definedType,proto3,enum=apipb.DefinedType" json:"defined_type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ListDefinedSetRequest) Reset() { + *x = ListDefinedSetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDefinedSetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDefinedSetRequest) ProtoMessage() {} + +func (x *ListDefinedSetRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[46] + 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 ListDefinedSetRequest.ProtoReflect.Descriptor instead. +func (*ListDefinedSetRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{46} +} + +func (x *ListDefinedSetRequest) GetDefinedType() DefinedType { + if x != nil { + return x.DefinedType + } + return DefinedType_PREFIX +} + +func (x *ListDefinedSetRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListDefinedSetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedSet *DefinedSet `protobuf:"bytes,1,opt,name=defined_set,json=definedSet,proto3" json:"defined_set,omitempty"` +} + +func (x *ListDefinedSetResponse) Reset() { + *x = ListDefinedSetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDefinedSetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDefinedSetResponse) ProtoMessage() {} + +func (x *ListDefinedSetResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[47] + 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 ListDefinedSetResponse.ProtoReflect.Descriptor instead. +func (*ListDefinedSetResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{47} +} + +func (x *ListDefinedSetResponse) GetDefinedSet() *DefinedSet { + if x != nil { + return x.DefinedSet + } + return nil +} + +type AddStatementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Statement *Statement `protobuf:"bytes,1,opt,name=statement,proto3" json:"statement,omitempty"` +} + +func (x *AddStatementRequest) Reset() { + *x = AddStatementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddStatementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddStatementRequest) ProtoMessage() {} + +func (x *AddStatementRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[48] + 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 AddStatementRequest.ProtoReflect.Descriptor instead. +func (*AddStatementRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{48} +} + +func (x *AddStatementRequest) GetStatement() *Statement { + if x != nil { + return x.Statement + } + return nil +} + +type DeleteStatementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Statement *Statement `protobuf:"bytes,1,opt,name=statement,proto3" json:"statement,omitempty"` + All bool `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"` +} + +func (x *DeleteStatementRequest) Reset() { + *x = DeleteStatementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteStatementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteStatementRequest) ProtoMessage() {} + +func (x *DeleteStatementRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[49] + 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 DeleteStatementRequest.ProtoReflect.Descriptor instead. +func (*DeleteStatementRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{49} +} + +func (x *DeleteStatementRequest) GetStatement() *Statement { + if x != nil { + return x.Statement + } + return nil +} + +func (x *DeleteStatementRequest) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +type ListStatementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ListStatementRequest) Reset() { + *x = ListStatementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListStatementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStatementRequest) ProtoMessage() {} + +func (x *ListStatementRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[50] + 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 ListStatementRequest.ProtoReflect.Descriptor instead. +func (*ListStatementRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{50} +} + +func (x *ListStatementRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type ListStatementResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Statement *Statement `protobuf:"bytes,1,opt,name=statement,proto3" json:"statement,omitempty"` +} + +func (x *ListStatementResponse) Reset() { + *x = ListStatementResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListStatementResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListStatementResponse) ProtoMessage() {} + +func (x *ListStatementResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[51] + 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 ListStatementResponse.ProtoReflect.Descriptor instead. +func (*ListStatementResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{51} +} + +func (x *ListStatementResponse) GetStatement() *Statement { + if x != nil { + return x.Statement + } + return nil +} + +type AddPolicyAssignmentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` +} + +func (x *AddPolicyAssignmentRequest) Reset() { + *x = AddPolicyAssignmentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPolicyAssignmentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPolicyAssignmentRequest) ProtoMessage() {} + +func (x *AddPolicyAssignmentRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[52] + 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 AddPolicyAssignmentRequest.ProtoReflect.Descriptor instead. +func (*AddPolicyAssignmentRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{52} +} + +func (x *AddPolicyAssignmentRequest) GetAssignment() *PolicyAssignment { + if x != nil { + return x.Assignment + } + return nil +} + +type DeletePolicyAssignmentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` + All bool `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"` +} + +func (x *DeletePolicyAssignmentRequest) Reset() { + *x = DeletePolicyAssignmentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletePolicyAssignmentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletePolicyAssignmentRequest) ProtoMessage() {} + +func (x *DeletePolicyAssignmentRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[53] + 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 DeletePolicyAssignmentRequest.ProtoReflect.Descriptor instead. +func (*DeletePolicyAssignmentRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{53} +} + +func (x *DeletePolicyAssignmentRequest) GetAssignment() *PolicyAssignment { + if x != nil { + return x.Assignment + } + return nil +} + +func (x *DeletePolicyAssignmentRequest) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +type ListPolicyAssignmentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Direction PolicyDirection `protobuf:"varint,2,opt,name=direction,proto3,enum=apipb.PolicyDirection" json:"direction,omitempty"` +} + +func (x *ListPolicyAssignmentRequest) Reset() { + *x = ListPolicyAssignmentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPolicyAssignmentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPolicyAssignmentRequest) ProtoMessage() {} + +func (x *ListPolicyAssignmentRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[54] + 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 ListPolicyAssignmentRequest.ProtoReflect.Descriptor instead. +func (*ListPolicyAssignmentRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{54} +} + +func (x *ListPolicyAssignmentRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ListPolicyAssignmentRequest) GetDirection() PolicyDirection { + if x != nil { + return x.Direction + } + return PolicyDirection_UNKNOWN +} + +type ListPolicyAssignmentResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` +} + +func (x *ListPolicyAssignmentResponse) Reset() { + *x = ListPolicyAssignmentResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListPolicyAssignmentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListPolicyAssignmentResponse) ProtoMessage() {} + +func (x *ListPolicyAssignmentResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[55] + 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 ListPolicyAssignmentResponse.ProtoReflect.Descriptor instead. +func (*ListPolicyAssignmentResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{55} +} + +func (x *ListPolicyAssignmentResponse) GetAssignment() *PolicyAssignment { + if x != nil { + return x.Assignment + } + return nil +} + +type SetPolicyAssignmentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Assignment *PolicyAssignment `protobuf:"bytes,1,opt,name=assignment,proto3" json:"assignment,omitempty"` +} + +func (x *SetPolicyAssignmentRequest) Reset() { + *x = SetPolicyAssignmentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetPolicyAssignmentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetPolicyAssignmentRequest) ProtoMessage() {} + +func (x *SetPolicyAssignmentRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[56] + 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 SetPolicyAssignmentRequest.ProtoReflect.Descriptor instead. +func (*SetPolicyAssignmentRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{56} +} + +func (x *SetPolicyAssignmentRequest) GetAssignment() *PolicyAssignment { + if x != nil { + return x.Assignment + } + return nil +} + +type AddRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` + Lifetime int64 `protobuf:"varint,3,opt,name=lifetime,proto3" json:"lifetime,omitempty"` +} + +func (x *AddRpkiRequest) Reset() { + *x = AddRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddRpkiRequest) ProtoMessage() {} + +func (x *AddRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[57] + 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 AddRpkiRequest.ProtoReflect.Descriptor instead. +func (*AddRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{57} +} + +func (x *AddRpkiRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *AddRpkiRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *AddRpkiRequest) GetLifetime() int64 { + if x != nil { + return x.Lifetime + } + return 0 +} + +type DeleteRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *DeleteRpkiRequest) Reset() { + *x = DeleteRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRpkiRequest) ProtoMessage() {} + +func (x *DeleteRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[58] + 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 DeleteRpkiRequest.ProtoReflect.Descriptor instead. +func (*DeleteRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{58} +} + +func (x *DeleteRpkiRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DeleteRpkiRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type ListRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` +} + +func (x *ListRpkiRequest) Reset() { + *x = ListRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRpkiRequest) ProtoMessage() {} + +func (x *ListRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[59] + 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 ListRpkiRequest.ProtoReflect.Descriptor instead. +func (*ListRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{59} +} + +func (x *ListRpkiRequest) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +type ListRpkiResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Server *Rpki `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"` +} + +func (x *ListRpkiResponse) Reset() { + *x = ListRpkiResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRpkiResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRpkiResponse) ProtoMessage() {} + +func (x *ListRpkiResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[60] + 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 ListRpkiResponse.ProtoReflect.Descriptor instead. +func (*ListRpkiResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{60} +} + +func (x *ListRpkiResponse) GetServer() *Rpki { + if x != nil { + return x.Server + } + return nil +} + +type EnableRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *EnableRpkiRequest) Reset() { + *x = EnableRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableRpkiRequest) ProtoMessage() {} + +func (x *EnableRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[61] + 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 EnableRpkiRequest.ProtoReflect.Descriptor instead. +func (*EnableRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{61} +} + +func (x *EnableRpkiRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *EnableRpkiRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type DisableRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *DisableRpkiRequest) Reset() { + *x = DisableRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableRpkiRequest) ProtoMessage() {} + +func (x *DisableRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[62] + 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 DisableRpkiRequest.ProtoReflect.Descriptor instead. +func (*DisableRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{62} +} + +func (x *DisableRpkiRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DisableRpkiRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type ResetRpkiRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` + Soft bool `protobuf:"varint,3,opt,name=soft,proto3" json:"soft,omitempty"` +} + +func (x *ResetRpkiRequest) Reset() { + *x = ResetRpkiRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetRpkiRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetRpkiRequest) ProtoMessage() {} + +func (x *ResetRpkiRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[63] + 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 ResetRpkiRequest.ProtoReflect.Descriptor instead. +func (*ResetRpkiRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{63} +} + +func (x *ResetRpkiRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *ResetRpkiRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *ResetRpkiRequest) GetSoft() bool { + if x != nil { + return x.Soft + } + return false +} + +type ListRpkiTableRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` +} + +func (x *ListRpkiTableRequest) Reset() { + *x = ListRpkiTableRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRpkiTableRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRpkiTableRequest) ProtoMessage() {} + +func (x *ListRpkiTableRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[64] + 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 ListRpkiTableRequest.ProtoReflect.Descriptor instead. +func (*ListRpkiTableRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{64} +} + +func (x *ListRpkiTableRequest) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +type ListRpkiTableResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Roa *Roa `protobuf:"bytes,1,opt,name=roa,proto3" json:"roa,omitempty"` +} + +func (x *ListRpkiTableResponse) Reset() { + *x = ListRpkiTableResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListRpkiTableResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRpkiTableResponse) ProtoMessage() {} + +func (x *ListRpkiTableResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[65] + 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 ListRpkiTableResponse.ProtoReflect.Descriptor instead. +func (*ListRpkiTableResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{65} +} + +func (x *ListRpkiTableResponse) GetRoa() *Roa { + if x != nil { + return x.Roa + } + return nil +} + +type EnableZebraRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + RouteTypes []string `protobuf:"bytes,2,rep,name=route_types,json=routeTypes,proto3" json:"route_types,omitempty"` + Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` + NexthopTriggerEnable bool `protobuf:"varint,4,opt,name=nexthop_trigger_enable,json=nexthopTriggerEnable,proto3" json:"nexthop_trigger_enable,omitempty"` + NexthopTriggerDelay uint32 `protobuf:"varint,5,opt,name=nexthop_trigger_delay,json=nexthopTriggerDelay,proto3" json:"nexthop_trigger_delay,omitempty"` + MplsLabelRangeSize uint32 `protobuf:"varint,6,opt,name=mpls_label_range_size,json=mplsLabelRangeSize,proto3" json:"mpls_label_range_size,omitempty"` + SoftwareName string `protobuf:"bytes,7,opt,name=software_name,json=softwareName,proto3" json:"software_name,omitempty"` +} + +func (x *EnableZebraRequest) Reset() { + *x = EnableZebraRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableZebraRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableZebraRequest) ProtoMessage() {} + +func (x *EnableZebraRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[66] + 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 EnableZebraRequest.ProtoReflect.Descriptor instead. +func (*EnableZebraRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{66} +} + +func (x *EnableZebraRequest) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *EnableZebraRequest) GetRouteTypes() []string { + if x != nil { + return x.RouteTypes + } + return nil +} + +func (x *EnableZebraRequest) GetVersion() uint32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *EnableZebraRequest) GetNexthopTriggerEnable() bool { + if x != nil { + return x.NexthopTriggerEnable + } + return false +} + +func (x *EnableZebraRequest) GetNexthopTriggerDelay() uint32 { + if x != nil { + return x.NexthopTriggerDelay + } + return 0 +} + +func (x *EnableZebraRequest) GetMplsLabelRangeSize() uint32 { + if x != nil { + return x.MplsLabelRangeSize + } + return 0 +} + +func (x *EnableZebraRequest) GetSoftwareName() string { + if x != nil { + return x.SoftwareName + } + return "" +} + +type EnableMrtRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type EnableMrtRequest_DumpType `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.EnableMrtRequest_DumpType" json:"type,omitempty"` + Filename string `protobuf:"bytes,2,opt,name=filename,proto3" json:"filename,omitempty"` + DumpInterval uint64 `protobuf:"varint,3,opt,name=dump_interval,json=dumpInterval,proto3" json:"dump_interval,omitempty"` + RotationInterval uint64 `protobuf:"varint,4,opt,name=rotation_interval,json=rotationInterval,proto3" json:"rotation_interval,omitempty"` +} + +func (x *EnableMrtRequest) Reset() { + *x = EnableMrtRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableMrtRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableMrtRequest) ProtoMessage() {} + +func (x *EnableMrtRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[67] + 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 EnableMrtRequest.ProtoReflect.Descriptor instead. +func (*EnableMrtRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{67} +} + +func (x *EnableMrtRequest) GetType() EnableMrtRequest_DumpType { + if x != nil { + return x.Type + } + return EnableMrtRequest_UPDATES +} + +func (x *EnableMrtRequest) GetFilename() string { + if x != nil { + return x.Filename + } + return "" +} + +func (x *EnableMrtRequest) GetDumpInterval() uint64 { + if x != nil { + return x.DumpInterval + } + return 0 +} + +func (x *EnableMrtRequest) GetRotationInterval() uint64 { + if x != nil { + return x.RotationInterval + } + return 0 +} + +type DisableMrtRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` +} + +func (x *DisableMrtRequest) Reset() { + *x = DisableMrtRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableMrtRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableMrtRequest) ProtoMessage() {} + +func (x *DisableMrtRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[68] + 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 DisableMrtRequest.ProtoReflect.Descriptor instead. +func (*DisableMrtRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{68} +} + +func (x *DisableMrtRequest) GetFilename() string { + if x != nil { + return x.Filename + } + return "" +} + +type AddBmpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` + Policy AddBmpRequest_MonitoringPolicy `protobuf:"varint,3,opt,name=policy,proto3,enum=apipb.AddBmpRequest_MonitoringPolicy" json:"policy,omitempty"` + StatisticsTimeout int32 `protobuf:"varint,4,opt,name=StatisticsTimeout,proto3" json:"StatisticsTimeout,omitempty"` + SysName string `protobuf:"bytes,5,opt,name=SysName,proto3" json:"SysName,omitempty"` + SysDescr string `protobuf:"bytes,6,opt,name=SysDescr,proto3" json:"SysDescr,omitempty"` +} + +func (x *AddBmpRequest) Reset() { + *x = AddBmpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddBmpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddBmpRequest) ProtoMessage() {} + +func (x *AddBmpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[69] + 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 AddBmpRequest.ProtoReflect.Descriptor instead. +func (*AddBmpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{69} +} + +func (x *AddBmpRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *AddBmpRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *AddBmpRequest) GetPolicy() AddBmpRequest_MonitoringPolicy { + if x != nil { + return x.Policy + } + return AddBmpRequest_PRE +} + +func (x *AddBmpRequest) GetStatisticsTimeout() int32 { + if x != nil { + return x.StatisticsTimeout + } + return 0 +} + +func (x *AddBmpRequest) GetSysName() string { + if x != nil { + return x.SysName + } + return "" +} + +func (x *AddBmpRequest) GetSysDescr() string { + if x != nil { + return x.SysDescr + } + return "" +} + +type DeleteBmpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *DeleteBmpRequest) Reset() { + *x = DeleteBmpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteBmpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteBmpRequest) ProtoMessage() {} + +func (x *DeleteBmpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[70] + 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 DeleteBmpRequest.ProtoReflect.Descriptor instead. +func (*DeleteBmpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{70} +} + +func (x *DeleteBmpRequest) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *DeleteBmpRequest) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type ListBmpRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListBmpRequest) Reset() { + *x = ListBmpRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListBmpRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBmpRequest) ProtoMessage() {} + +func (x *ListBmpRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[71] + 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 ListBmpRequest.ProtoReflect.Descriptor instead. +func (*ListBmpRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{71} +} + +type ListBmpResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Station *ListBmpResponse_BmpStation `protobuf:"bytes,1,opt,name=station,proto3" json:"station,omitempty"` +} + +func (x *ListBmpResponse) Reset() { + *x = ListBmpResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListBmpResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBmpResponse) ProtoMessage() {} + +func (x *ListBmpResponse) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[72] + 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 ListBmpResponse.ProtoReflect.Descriptor instead. +func (*ListBmpResponse) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{72} +} + +func (x *ListBmpResponse) GetStation() *ListBmpResponse_BmpStation { + if x != nil { + return x.Station + } + return nil +} + +type Family struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Afi Family_Afi `protobuf:"varint,1,opt,name=afi,proto3,enum=apipb.Family_Afi" json:"afi,omitempty"` + Safi Family_Safi `protobuf:"varint,2,opt,name=safi,proto3,enum=apipb.Family_Safi" json:"safi,omitempty"` +} + +func (x *Family) Reset() { + *x = Family{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Family) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Family) ProtoMessage() {} + +func (x *Family) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[73] + 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 Family.ProtoReflect.Descriptor instead. +func (*Family) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{73} +} + +func (x *Family) GetAfi() Family_Afi { + if x != nil { + return x.Afi + } + return Family_AFI_UNKNOWN +} + +func (x *Family) GetSafi() Family_Safi { + if x != nil { + return x.Safi + } + return Family_SAFI_UNKNOWN +} + +type Validation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + State Validation_State `protobuf:"varint,1,opt,name=state,proto3,enum=apipb.Validation_State" json:"state,omitempty"` + Reason Validation_Reason `protobuf:"varint,2,opt,name=reason,proto3,enum=apipb.Validation_Reason" json:"reason,omitempty"` + Matched []*Roa `protobuf:"bytes,3,rep,name=matched,proto3" json:"matched,omitempty"` + UnmatchedAsn []*Roa `protobuf:"bytes,4,rep,name=unmatched_asn,json=unmatchedAsn,proto3" json:"unmatched_asn,omitempty"` + UnmatchedLength []*Roa `protobuf:"bytes,5,rep,name=unmatched_length,json=unmatchedLength,proto3" json:"unmatched_length,omitempty"` +} + +func (x *Validation) Reset() { + *x = Validation{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Validation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Validation) ProtoMessage() {} + +func (x *Validation) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[74] + 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 Validation.ProtoReflect.Descriptor instead. +func (*Validation) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{74} +} + +func (x *Validation) GetState() Validation_State { + if x != nil { + return x.State + } + return Validation_STATE_NONE +} + +func (x *Validation) GetReason() Validation_Reason { + if x != nil { + return x.Reason + } + return Validation_REASON_NONE +} + +func (x *Validation) GetMatched() []*Roa { + if x != nil { + return x.Matched + } + return nil +} + +func (x *Validation) GetUnmatchedAsn() []*Roa { + if x != nil { + return x.UnmatchedAsn + } + return nil +} + +func (x *Validation) GetUnmatchedLength() []*Roa { + if x != nil { + return x.UnmatchedLength + } + return nil +} + +type Path struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // One of the following defined in "api/attribute.proto": + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - EVPNIPMSIRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + // - LsAddrPrefix + // - SRPolicyNLRI + // - MUPInterworkSegmentDiscoveryRoute + // - MUPDirectSegmentDiscoveryRoute + // - MUPType1SessionTransformedRoute + // - MUPType2SessionTransformedRoute + Nlri *anypb.Any `protobuf:"bytes,1,opt,name=nlri,proto3" json:"nlri,omitempty"` + // Each attribute must be one of *Attribute defined in + // "api/attribute.proto". + Pattrs []*anypb.Any `protobuf:"bytes,2,rep,name=pattrs,proto3" json:"pattrs,omitempty"` + Age *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=age,proto3" json:"age,omitempty"` + Best bool `protobuf:"varint,4,opt,name=best,proto3" json:"best,omitempty"` + IsWithdraw bool `protobuf:"varint,5,opt,name=is_withdraw,json=isWithdraw,proto3" json:"is_withdraw,omitempty"` + Validation *Validation `protobuf:"bytes,7,opt,name=validation,proto3" json:"validation,omitempty"` + NoImplicitWithdraw bool `protobuf:"varint,8,opt,name=no_implicit_withdraw,json=noImplicitWithdraw,proto3" json:"no_implicit_withdraw,omitempty"` + Family *Family `protobuf:"bytes,9,opt,name=family,proto3" json:"family,omitempty"` + SourceAsn uint32 `protobuf:"varint,10,opt,name=source_asn,json=sourceAsn,proto3" json:"source_asn,omitempty"` + SourceId string `protobuf:"bytes,11,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` + Filtered bool `protobuf:"varint,12,opt,name=filtered,proto3" json:"filtered,omitempty"` + Stale bool `protobuf:"varint,13,opt,name=stale,proto3" json:"stale,omitempty"` + IsFromExternal bool `protobuf:"varint,14,opt,name=is_from_external,json=isFromExternal,proto3" json:"is_from_external,omitempty"` + NeighborIp string `protobuf:"bytes,15,opt,name=neighbor_ip,json=neighborIp,proto3" json:"neighbor_ip,omitempty"` + Uuid []byte `protobuf:"bytes,16,opt,name=uuid,proto3" json:"uuid,omitempty"` // only paths installed by AddPath API have this + IsNexthopInvalid bool `protobuf:"varint,17,opt,name=is_nexthop_invalid,json=isNexthopInvalid,proto3" json:"is_nexthop_invalid,omitempty"` + Identifier uint32 `protobuf:"varint,18,opt,name=identifier,proto3" json:"identifier,omitempty"` + LocalIdentifier uint32 `protobuf:"varint,19,opt,name=local_identifier,json=localIdentifier,proto3" json:"local_identifier,omitempty"` + NlriBinary []byte `protobuf:"bytes,20,opt,name=nlri_binary,json=nlriBinary,proto3" json:"nlri_binary,omitempty"` + PattrsBinary [][]byte `protobuf:"bytes,21,rep,name=pattrs_binary,json=pattrsBinary,proto3" json:"pattrs_binary,omitempty"` +} + +func (x *Path) Reset() { + *x = Path{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Path) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Path) ProtoMessage() {} + +func (x *Path) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[75] + 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 Path.ProtoReflect.Descriptor instead. +func (*Path) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{75} +} + +func (x *Path) GetNlri() *anypb.Any { + if x != nil { + return x.Nlri + } + return nil +} + +func (x *Path) GetPattrs() []*anypb.Any { + if x != nil { + return x.Pattrs + } + return nil +} + +func (x *Path) GetAge() *timestamppb.Timestamp { + if x != nil { + return x.Age + } + return nil +} + +func (x *Path) GetBest() bool { + if x != nil { + return x.Best + } + return false +} + +func (x *Path) GetIsWithdraw() bool { + if x != nil { + return x.IsWithdraw + } + return false +} + +func (x *Path) GetValidation() *Validation { + if x != nil { + return x.Validation + } + return nil +} + +func (x *Path) GetNoImplicitWithdraw() bool { + if x != nil { + return x.NoImplicitWithdraw + } + return false +} + +func (x *Path) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *Path) GetSourceAsn() uint32 { + if x != nil { + return x.SourceAsn + } + return 0 +} + +func (x *Path) GetSourceId() string { + if x != nil { + return x.SourceId + } + return "" +} + +func (x *Path) GetFiltered() bool { + if x != nil { + return x.Filtered + } + return false +} + +func (x *Path) GetStale() bool { + if x != nil { + return x.Stale + } + return false +} + +func (x *Path) GetIsFromExternal() bool { + if x != nil { + return x.IsFromExternal + } + return false +} + +func (x *Path) GetNeighborIp() string { + if x != nil { + return x.NeighborIp + } + return "" +} + +func (x *Path) GetUuid() []byte { + if x != nil { + return x.Uuid + } + return nil +} + +func (x *Path) GetIsNexthopInvalid() bool { + if x != nil { + return x.IsNexthopInvalid + } + return false +} + +func (x *Path) GetIdentifier() uint32 { + if x != nil { + return x.Identifier + } + return 0 +} + +func (x *Path) GetLocalIdentifier() uint32 { + if x != nil { + return x.LocalIdentifier + } + return 0 +} + +func (x *Path) GetNlriBinary() []byte { + if x != nil { + return x.NlriBinary + } + return nil +} + +func (x *Path) GetPattrsBinary() [][]byte { + if x != nil { + return x.PattrsBinary + } + return nil +} + +type Destination struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` + Paths []*Path `protobuf:"bytes,2,rep,name=paths,proto3" json:"paths,omitempty"` +} + +func (x *Destination) Reset() { + *x = Destination{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[76] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Destination) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Destination) ProtoMessage() {} + +func (x *Destination) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[76] + 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 Destination.ProtoReflect.Descriptor instead. +func (*Destination) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{76} +} + +func (x *Destination) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *Destination) GetPaths() []*Path { + if x != nil { + return x.Paths + } + return nil +} + +type Peer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApplyPolicy *ApplyPolicy `protobuf:"bytes,1,opt,name=apply_policy,json=applyPolicy,proto3" json:"apply_policy,omitempty"` + Conf *PeerConf `protobuf:"bytes,2,opt,name=conf,proto3" json:"conf,omitempty"` + EbgpMultihop *EbgpMultihop `protobuf:"bytes,3,opt,name=ebgp_multihop,json=ebgpMultihop,proto3" json:"ebgp_multihop,omitempty"` + RouteReflector *RouteReflector `protobuf:"bytes,4,opt,name=route_reflector,json=routeReflector,proto3" json:"route_reflector,omitempty"` + State *PeerState `protobuf:"bytes,5,opt,name=state,proto3" json:"state,omitempty"` + Timers *Timers `protobuf:"bytes,6,opt,name=timers,proto3" json:"timers,omitempty"` + Transport *Transport `protobuf:"bytes,7,opt,name=transport,proto3" json:"transport,omitempty"` + RouteServer *RouteServer `protobuf:"bytes,8,opt,name=route_server,json=routeServer,proto3" json:"route_server,omitempty"` + GracefulRestart *GracefulRestart `protobuf:"bytes,9,opt,name=graceful_restart,json=gracefulRestart,proto3" json:"graceful_restart,omitempty"` + AfiSafis []*AfiSafi `protobuf:"bytes,10,rep,name=afi_safis,json=afiSafis,proto3" json:"afi_safis,omitempty"` + TtlSecurity *TtlSecurity `protobuf:"bytes,11,opt,name=ttl_security,json=ttlSecurity,proto3" json:"ttl_security,omitempty"` +} + +func (x *Peer) Reset() { + *x = Peer{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Peer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Peer) ProtoMessage() {} + +func (x *Peer) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[77] + 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 Peer.ProtoReflect.Descriptor instead. +func (*Peer) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{77} +} + +func (x *Peer) GetApplyPolicy() *ApplyPolicy { + if x != nil { + return x.ApplyPolicy + } + return nil +} + +func (x *Peer) GetConf() *PeerConf { + if x != nil { + return x.Conf + } + return nil +} + +func (x *Peer) GetEbgpMultihop() *EbgpMultihop { + if x != nil { + return x.EbgpMultihop + } + return nil +} + +func (x *Peer) GetRouteReflector() *RouteReflector { + if x != nil { + return x.RouteReflector + } + return nil +} + +func (x *Peer) GetState() *PeerState { + if x != nil { + return x.State + } + return nil +} + +func (x *Peer) GetTimers() *Timers { + if x != nil { + return x.Timers + } + return nil +} + +func (x *Peer) GetTransport() *Transport { + if x != nil { + return x.Transport + } + return nil +} + +func (x *Peer) GetRouteServer() *RouteServer { + if x != nil { + return x.RouteServer + } + return nil +} + +func (x *Peer) GetGracefulRestart() *GracefulRestart { + if x != nil { + return x.GracefulRestart + } + return nil +} + +func (x *Peer) GetAfiSafis() []*AfiSafi { + if x != nil { + return x.AfiSafis + } + return nil +} + +func (x *Peer) GetTtlSecurity() *TtlSecurity { + if x != nil { + return x.TtlSecurity + } + return nil +} + +type PeerGroup struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApplyPolicy *ApplyPolicy `protobuf:"bytes,1,opt,name=apply_policy,json=applyPolicy,proto3" json:"apply_policy,omitempty"` + Conf *PeerGroupConf `protobuf:"bytes,2,opt,name=conf,proto3" json:"conf,omitempty"` + EbgpMultihop *EbgpMultihop `protobuf:"bytes,3,opt,name=ebgp_multihop,json=ebgpMultihop,proto3" json:"ebgp_multihop,omitempty"` + RouteReflector *RouteReflector `protobuf:"bytes,4,opt,name=route_reflector,json=routeReflector,proto3" json:"route_reflector,omitempty"` + Info *PeerGroupState `protobuf:"bytes,5,opt,name=info,proto3" json:"info,omitempty"` + Timers *Timers `protobuf:"bytes,6,opt,name=timers,proto3" json:"timers,omitempty"` + Transport *Transport `protobuf:"bytes,7,opt,name=transport,proto3" json:"transport,omitempty"` + RouteServer *RouteServer `protobuf:"bytes,8,opt,name=route_server,json=routeServer,proto3" json:"route_server,omitempty"` + GracefulRestart *GracefulRestart `protobuf:"bytes,9,opt,name=graceful_restart,json=gracefulRestart,proto3" json:"graceful_restart,omitempty"` + AfiSafis []*AfiSafi `protobuf:"bytes,10,rep,name=afi_safis,json=afiSafis,proto3" json:"afi_safis,omitempty"` + TtlSecurity *TtlSecurity `protobuf:"bytes,11,opt,name=ttl_security,json=ttlSecurity,proto3" json:"ttl_security,omitempty"` +} + +func (x *PeerGroup) Reset() { + *x = PeerGroup{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[78] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerGroup) ProtoMessage() {} + +func (x *PeerGroup) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[78] + 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 PeerGroup.ProtoReflect.Descriptor instead. +func (*PeerGroup) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{78} +} + +func (x *PeerGroup) GetApplyPolicy() *ApplyPolicy { + if x != nil { + return x.ApplyPolicy + } + return nil +} + +func (x *PeerGroup) GetConf() *PeerGroupConf { + if x != nil { + return x.Conf + } + return nil +} + +func (x *PeerGroup) GetEbgpMultihop() *EbgpMultihop { + if x != nil { + return x.EbgpMultihop + } + return nil +} + +func (x *PeerGroup) GetRouteReflector() *RouteReflector { + if x != nil { + return x.RouteReflector + } + return nil +} + +func (x *PeerGroup) GetInfo() *PeerGroupState { + if x != nil { + return x.Info + } + return nil +} + +func (x *PeerGroup) GetTimers() *Timers { + if x != nil { + return x.Timers + } + return nil +} + +func (x *PeerGroup) GetTransport() *Transport { + if x != nil { + return x.Transport + } + return nil +} + +func (x *PeerGroup) GetRouteServer() *RouteServer { + if x != nil { + return x.RouteServer + } + return nil +} + +func (x *PeerGroup) GetGracefulRestart() *GracefulRestart { + if x != nil { + return x.GracefulRestart + } + return nil +} + +func (x *PeerGroup) GetAfiSafis() []*AfiSafi { + if x != nil { + return x.AfiSafis + } + return nil +} + +func (x *PeerGroup) GetTtlSecurity() *TtlSecurity { + if x != nil { + return x.TtlSecurity + } + return nil +} + +type DynamicNeighbor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` + PeerGroup string `protobuf:"bytes,2,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` +} + +func (x *DynamicNeighbor) Reset() { + *x = DynamicNeighbor{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[79] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DynamicNeighbor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DynamicNeighbor) ProtoMessage() {} + +func (x *DynamicNeighbor) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[79] + 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 DynamicNeighbor.ProtoReflect.Descriptor instead. +func (*DynamicNeighbor) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{79} +} + +func (x *DynamicNeighbor) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *DynamicNeighbor) GetPeerGroup() string { + if x != nil { + return x.PeerGroup + } + return "" +} + +type ApplyPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InPolicy *PolicyAssignment `protobuf:"bytes,1,opt,name=in_policy,json=inPolicy,proto3" json:"in_policy,omitempty"` + ExportPolicy *PolicyAssignment `protobuf:"bytes,2,opt,name=export_policy,json=exportPolicy,proto3" json:"export_policy,omitempty"` + ImportPolicy *PolicyAssignment `protobuf:"bytes,3,opt,name=import_policy,json=importPolicy,proto3" json:"import_policy,omitempty"` +} + +func (x *ApplyPolicy) Reset() { + *x = ApplyPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[80] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ApplyPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ApplyPolicy) ProtoMessage() {} + +func (x *ApplyPolicy) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[80] + 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 ApplyPolicy.ProtoReflect.Descriptor instead. +func (*ApplyPolicy) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{80} +} + +func (x *ApplyPolicy) GetInPolicy() *PolicyAssignment { + if x != nil { + return x.InPolicy + } + return nil +} + +func (x *ApplyPolicy) GetExportPolicy() *PolicyAssignment { + if x != nil { + return x.ExportPolicy + } + return nil +} + +func (x *ApplyPolicy) GetImportPolicy() *PolicyAssignment { + if x != nil { + return x.ImportPolicy + } + return nil +} + +type PrefixLimit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + MaxPrefixes uint32 `protobuf:"varint,2,opt,name=max_prefixes,json=maxPrefixes,proto3" json:"max_prefixes,omitempty"` + ShutdownThresholdPct uint32 `protobuf:"varint,3,opt,name=shutdown_threshold_pct,json=shutdownThresholdPct,proto3" json:"shutdown_threshold_pct,omitempty"` +} + +func (x *PrefixLimit) Reset() { + *x = PrefixLimit{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[81] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PrefixLimit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrefixLimit) ProtoMessage() {} + +func (x *PrefixLimit) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[81] + 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 PrefixLimit.ProtoReflect.Descriptor instead. +func (*PrefixLimit) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{81} +} + +func (x *PrefixLimit) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *PrefixLimit) GetMaxPrefixes() uint32 { + if x != nil { + return x.MaxPrefixes + } + return 0 +} + +func (x *PrefixLimit) GetShutdownThresholdPct() uint32 { + if x != nil { + return x.ShutdownThresholdPct + } + return 0 +} + +type PeerConf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword,proto3" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + LocalAsn uint32 `protobuf:"varint,3,opt,name=local_asn,json=localAsn,proto3" json:"local_asn,omitempty"` + NeighborAddress string `protobuf:"bytes,4,opt,name=neighbor_address,json=neighborAddress,proto3" json:"neighbor_address,omitempty"` + PeerAsn uint32 `protobuf:"varint,5,opt,name=peer_asn,json=peerAsn,proto3" json:"peer_asn,omitempty"` + PeerGroup string `protobuf:"bytes,6,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` + Type PeerType `protobuf:"varint,7,opt,name=type,proto3,enum=apipb.PeerType" json:"type,omitempty"` + RemovePrivate RemovePrivate `protobuf:"varint,8,opt,name=remove_private,json=removePrivate,proto3,enum=apipb.RemovePrivate" json:"remove_private,omitempty"` + RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping,proto3" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity,proto3" json:"send_community,omitempty"` + NeighborInterface string `protobuf:"bytes,11,opt,name=neighbor_interface,json=neighborInterface,proto3" json:"neighbor_interface,omitempty"` + Vrf string `protobuf:"bytes,12,opt,name=vrf,proto3" json:"vrf,omitempty"` + AllowOwnAsn uint32 `protobuf:"varint,13,opt,name=allow_own_asn,json=allowOwnAsn,proto3" json:"allow_own_asn,omitempty"` + ReplacePeerAsn bool `protobuf:"varint,14,opt,name=replace_peer_asn,json=replacePeerAsn,proto3" json:"replace_peer_asn,omitempty"` + AdminDown bool `protobuf:"varint,15,opt,name=admin_down,json=adminDown,proto3" json:"admin_down,omitempty"` +} + +func (x *PeerConf) Reset() { + *x = PeerConf{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[82] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerConf) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerConf) ProtoMessage() {} + +func (x *PeerConf) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[82] + 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 PeerConf.ProtoReflect.Descriptor instead. +func (*PeerConf) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{82} +} + +func (x *PeerConf) GetAuthPassword() string { + if x != nil { + return x.AuthPassword + } + return "" +} + +func (x *PeerConf) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *PeerConf) GetLocalAsn() uint32 { + if x != nil { + return x.LocalAsn + } + return 0 +} + +func (x *PeerConf) GetNeighborAddress() string { + if x != nil { + return x.NeighborAddress + } + return "" +} + +func (x *PeerConf) GetPeerAsn() uint32 { + if x != nil { + return x.PeerAsn + } + return 0 +} + +func (x *PeerConf) GetPeerGroup() string { + if x != nil { + return x.PeerGroup + } + return "" +} + +func (x *PeerConf) GetType() PeerType { + if x != nil { + return x.Type + } + return PeerType_INTERNAL +} + +func (x *PeerConf) GetRemovePrivate() RemovePrivate { + if x != nil { + return x.RemovePrivate + } + return RemovePrivate_REMOVE_NONE +} + +func (x *PeerConf) GetRouteFlapDamping() bool { + if x != nil { + return x.RouteFlapDamping + } + return false +} + +func (x *PeerConf) GetSendCommunity() uint32 { + if x != nil { + return x.SendCommunity + } + return 0 +} + +func (x *PeerConf) GetNeighborInterface() string { + if x != nil { + return x.NeighborInterface + } + return "" +} + +func (x *PeerConf) GetVrf() string { + if x != nil { + return x.Vrf + } + return "" +} + +func (x *PeerConf) GetAllowOwnAsn() uint32 { + if x != nil { + return x.AllowOwnAsn + } + return 0 +} + +func (x *PeerConf) GetReplacePeerAsn() bool { + if x != nil { + return x.ReplacePeerAsn + } + return false +} + +func (x *PeerConf) GetAdminDown() bool { + if x != nil { + return x.AdminDown + } + return false +} + +type PeerGroupConf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword,proto3" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + LocalAsn uint32 `protobuf:"varint,3,opt,name=local_asn,json=localAsn,proto3" json:"local_asn,omitempty"` + PeerAsn uint32 `protobuf:"varint,4,opt,name=peer_asn,json=peerAsn,proto3" json:"peer_asn,omitempty"` + PeerGroupName string `protobuf:"bytes,5,opt,name=peer_group_name,json=peerGroupName,proto3" json:"peer_group_name,omitempty"` + Type PeerType `protobuf:"varint,6,opt,name=type,proto3,enum=apipb.PeerType" json:"type,omitempty"` + RemovePrivate RemovePrivate `protobuf:"varint,7,opt,name=remove_private,json=removePrivate,proto3,enum=apipb.RemovePrivate" json:"remove_private,omitempty"` + RouteFlapDamping bool `protobuf:"varint,8,opt,name=route_flap_damping,json=routeFlapDamping,proto3" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,9,opt,name=send_community,json=sendCommunity,proto3" json:"send_community,omitempty"` +} + +func (x *PeerGroupConf) Reset() { + *x = PeerGroupConf{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[83] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerGroupConf) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerGroupConf) ProtoMessage() {} + +func (x *PeerGroupConf) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[83] + 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 PeerGroupConf.ProtoReflect.Descriptor instead. +func (*PeerGroupConf) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{83} +} + +func (x *PeerGroupConf) GetAuthPassword() string { + if x != nil { + return x.AuthPassword + } + return "" +} + +func (x *PeerGroupConf) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *PeerGroupConf) GetLocalAsn() uint32 { + if x != nil { + return x.LocalAsn + } + return 0 +} + +func (x *PeerGroupConf) GetPeerAsn() uint32 { + if x != nil { + return x.PeerAsn + } + return 0 +} + +func (x *PeerGroupConf) GetPeerGroupName() string { + if x != nil { + return x.PeerGroupName + } + return "" +} + +func (x *PeerGroupConf) GetType() PeerType { + if x != nil { + return x.Type + } + return PeerType_INTERNAL +} + +func (x *PeerGroupConf) GetRemovePrivate() RemovePrivate { + if x != nil { + return x.RemovePrivate + } + return RemovePrivate_REMOVE_NONE +} + +func (x *PeerGroupConf) GetRouteFlapDamping() bool { + if x != nil { + return x.RouteFlapDamping + } + return false +} + +func (x *PeerGroupConf) GetSendCommunity() uint32 { + if x != nil { + return x.SendCommunity + } + return 0 +} + +type PeerGroupState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword,proto3" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + LocalAsn uint32 `protobuf:"varint,3,opt,name=local_asn,json=localAsn,proto3" json:"local_asn,omitempty"` + PeerAsn uint32 `protobuf:"varint,4,opt,name=peer_asn,json=peerAsn,proto3" json:"peer_asn,omitempty"` + PeerGroupName string `protobuf:"bytes,5,opt,name=peer_group_name,json=peerGroupName,proto3" json:"peer_group_name,omitempty"` + Type PeerType `protobuf:"varint,6,opt,name=type,proto3,enum=apipb.PeerType" json:"type,omitempty"` + RemovePrivate RemovePrivate `protobuf:"varint,7,opt,name=remove_private,json=removePrivate,proto3,enum=apipb.RemovePrivate" json:"remove_private,omitempty"` + RouteFlapDamping bool `protobuf:"varint,8,opt,name=route_flap_damping,json=routeFlapDamping,proto3" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,9,opt,name=send_community,json=sendCommunity,proto3" json:"send_community,omitempty"` + TotalPaths uint32 `protobuf:"varint,10,opt,name=total_paths,json=totalPaths,proto3" json:"total_paths,omitempty"` + TotalPrefixes uint32 `protobuf:"varint,11,opt,name=total_prefixes,json=totalPrefixes,proto3" json:"total_prefixes,omitempty"` +} + +func (x *PeerGroupState) Reset() { + *x = PeerGroupState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[84] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerGroupState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerGroupState) ProtoMessage() {} + +func (x *PeerGroupState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[84] + 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 PeerGroupState.ProtoReflect.Descriptor instead. +func (*PeerGroupState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{84} +} + +func (x *PeerGroupState) GetAuthPassword() string { + if x != nil { + return x.AuthPassword + } + return "" +} + +func (x *PeerGroupState) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *PeerGroupState) GetLocalAsn() uint32 { + if x != nil { + return x.LocalAsn + } + return 0 +} + +func (x *PeerGroupState) GetPeerAsn() uint32 { + if x != nil { + return x.PeerAsn + } + return 0 +} + +func (x *PeerGroupState) GetPeerGroupName() string { + if x != nil { + return x.PeerGroupName + } + return "" +} + +func (x *PeerGroupState) GetType() PeerType { + if x != nil { + return x.Type + } + return PeerType_INTERNAL +} + +func (x *PeerGroupState) GetRemovePrivate() RemovePrivate { + if x != nil { + return x.RemovePrivate + } + return RemovePrivate_REMOVE_NONE +} + +func (x *PeerGroupState) GetRouteFlapDamping() bool { + if x != nil { + return x.RouteFlapDamping + } + return false +} + +func (x *PeerGroupState) GetSendCommunity() uint32 { + if x != nil { + return x.SendCommunity + } + return 0 +} + +func (x *PeerGroupState) GetTotalPaths() uint32 { + if x != nil { + return x.TotalPaths + } + return 0 +} + +func (x *PeerGroupState) GetTotalPrefixes() uint32 { + if x != nil { + return x.TotalPrefixes + } + return 0 +} + +type TtlSecurity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + TtlMin uint32 `protobuf:"varint,2,opt,name=ttl_min,json=ttlMin,proto3" json:"ttl_min,omitempty"` +} + +func (x *TtlSecurity) Reset() { + *x = TtlSecurity{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[85] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TtlSecurity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TtlSecurity) ProtoMessage() {} + +func (x *TtlSecurity) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[85] + 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 TtlSecurity.ProtoReflect.Descriptor instead. +func (*TtlSecurity) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{85} +} + +func (x *TtlSecurity) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *TtlSecurity) GetTtlMin() uint32 { + if x != nil { + return x.TtlMin + } + return 0 +} + +type EbgpMultihop struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + MultihopTtl uint32 `protobuf:"varint,2,opt,name=multihop_ttl,json=multihopTtl,proto3" json:"multihop_ttl,omitempty"` +} + +func (x *EbgpMultihop) Reset() { + *x = EbgpMultihop{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[86] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EbgpMultihop) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EbgpMultihop) ProtoMessage() {} + +func (x *EbgpMultihop) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[86] + 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 EbgpMultihop.ProtoReflect.Descriptor instead. +func (*EbgpMultihop) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{86} +} + +func (x *EbgpMultihop) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *EbgpMultihop) GetMultihopTtl() uint32 { + if x != nil { + return x.MultihopTtl + } + return 0 +} + +type RouteReflector struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RouteReflectorClient bool `protobuf:"varint,1,opt,name=route_reflector_client,json=routeReflectorClient,proto3" json:"route_reflector_client,omitempty"` + RouteReflectorClusterId string `protobuf:"bytes,2,opt,name=route_reflector_cluster_id,json=routeReflectorClusterId,proto3" json:"route_reflector_cluster_id,omitempty"` +} + +func (x *RouteReflector) Reset() { + *x = RouteReflector{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[87] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteReflector) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteReflector) ProtoMessage() {} + +func (x *RouteReflector) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[87] + 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 RouteReflector.ProtoReflect.Descriptor instead. +func (*RouteReflector) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{87} +} + +func (x *RouteReflector) GetRouteReflectorClient() bool { + if x != nil { + return x.RouteReflectorClient + } + return false +} + +func (x *RouteReflector) GetRouteReflectorClusterId() string { + if x != nil { + return x.RouteReflectorClusterId + } + return "" +} + +type PeerState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword,proto3" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + LocalAsn uint32 `protobuf:"varint,3,opt,name=local_asn,json=localAsn,proto3" json:"local_asn,omitempty"` + Messages *Messages `protobuf:"bytes,4,opt,name=messages,proto3" json:"messages,omitempty"` + NeighborAddress string `protobuf:"bytes,5,opt,name=neighbor_address,json=neighborAddress,proto3" json:"neighbor_address,omitempty"` + PeerAsn uint32 `protobuf:"varint,6,opt,name=peer_asn,json=peerAsn,proto3" json:"peer_asn,omitempty"` + PeerGroup string `protobuf:"bytes,7,opt,name=peer_group,json=peerGroup,proto3" json:"peer_group,omitempty"` + Type PeerType `protobuf:"varint,8,opt,name=type,proto3,enum=apipb.PeerType" json:"type,omitempty"` + Queues *Queues `protobuf:"bytes,9,opt,name=queues,proto3" json:"queues,omitempty"` + RemovePrivate RemovePrivate `protobuf:"varint,10,opt,name=remove_private,json=removePrivate,proto3,enum=apipb.RemovePrivate" json:"remove_private,omitempty"` + RouteFlapDamping bool `protobuf:"varint,11,opt,name=route_flap_damping,json=routeFlapDamping,proto3" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,12,opt,name=send_community,json=sendCommunity,proto3" json:"send_community,omitempty"` + SessionState PeerState_SessionState `protobuf:"varint,13,opt,name=session_state,json=sessionState,proto3,enum=apipb.PeerState_SessionState" json:"session_state,omitempty"` + AdminState PeerState_AdminState `protobuf:"varint,15,opt,name=admin_state,json=adminState,proto3,enum=apipb.PeerState_AdminState" json:"admin_state,omitempty"` + OutQ uint32 `protobuf:"varint,16,opt,name=out_q,json=outQ,proto3" json:"out_q,omitempty"` + Flops uint32 `protobuf:"varint,17,opt,name=flops,proto3" json:"flops,omitempty"` + // Each attribute must be one of *Capability defined in + // "api/capability.proto". + RemoteCap []*anypb.Any `protobuf:"bytes,18,rep,name=remote_cap,json=remoteCap,proto3" json:"remote_cap,omitempty"` + LocalCap []*anypb.Any `protobuf:"bytes,19,rep,name=local_cap,json=localCap,proto3" json:"local_cap,omitempty"` + RouterId string `protobuf:"bytes,20,opt,name=router_id,json=routerId,proto3" json:"router_id,omitempty"` +} + +func (x *PeerState) Reset() { + *x = PeerState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[88] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerState) ProtoMessage() {} + +func (x *PeerState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[88] + 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 PeerState.ProtoReflect.Descriptor instead. +func (*PeerState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{88} +} + +func (x *PeerState) GetAuthPassword() string { + if x != nil { + return x.AuthPassword + } + return "" +} + +func (x *PeerState) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *PeerState) GetLocalAsn() uint32 { + if x != nil { + return x.LocalAsn + } + return 0 +} + +func (x *PeerState) GetMessages() *Messages { + if x != nil { + return x.Messages + } + return nil +} + +func (x *PeerState) GetNeighborAddress() string { + if x != nil { + return x.NeighborAddress + } + return "" +} + +func (x *PeerState) GetPeerAsn() uint32 { + if x != nil { + return x.PeerAsn + } + return 0 +} + +func (x *PeerState) GetPeerGroup() string { + if x != nil { + return x.PeerGroup + } + return "" +} + +func (x *PeerState) GetType() PeerType { + if x != nil { + return x.Type + } + return PeerType_INTERNAL +} + +func (x *PeerState) GetQueues() *Queues { + if x != nil { + return x.Queues + } + return nil +} + +func (x *PeerState) GetRemovePrivate() RemovePrivate { + if x != nil { + return x.RemovePrivate + } + return RemovePrivate_REMOVE_NONE +} + +func (x *PeerState) GetRouteFlapDamping() bool { + if x != nil { + return x.RouteFlapDamping + } + return false +} + +func (x *PeerState) GetSendCommunity() uint32 { + if x != nil { + return x.SendCommunity + } + return 0 +} + +func (x *PeerState) GetSessionState() PeerState_SessionState { + if x != nil { + return x.SessionState + } + return PeerState_UNKNOWN +} + +func (x *PeerState) GetAdminState() PeerState_AdminState { + if x != nil { + return x.AdminState + } + return PeerState_UP +} + +func (x *PeerState) GetOutQ() uint32 { + if x != nil { + return x.OutQ + } + return 0 +} + +func (x *PeerState) GetFlops() uint32 { + if x != nil { + return x.Flops + } + return 0 +} + +func (x *PeerState) GetRemoteCap() []*anypb.Any { + if x != nil { + return x.RemoteCap + } + return nil +} + +func (x *PeerState) GetLocalCap() []*anypb.Any { + if x != nil { + return x.LocalCap + } + return nil +} + +func (x *PeerState) GetRouterId() string { + if x != nil { + return x.RouterId + } + return "" +} + +type Messages struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Received *Message `protobuf:"bytes,1,opt,name=received,proto3" json:"received,omitempty"` + Sent *Message `protobuf:"bytes,2,opt,name=sent,proto3" json:"sent,omitempty"` +} + +func (x *Messages) Reset() { + *x = Messages{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[89] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Messages) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Messages) ProtoMessage() {} + +func (x *Messages) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[89] + 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 Messages.ProtoReflect.Descriptor instead. +func (*Messages) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{89} +} + +func (x *Messages) GetReceived() *Message { + if x != nil { + return x.Received + } + return nil +} + +func (x *Messages) GetSent() *Message { + if x != nil { + return x.Sent + } + return nil +} + +type Message struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Notification uint64 `protobuf:"varint,1,opt,name=notification,proto3" json:"notification,omitempty"` + Update uint64 `protobuf:"varint,2,opt,name=update,proto3" json:"update,omitempty"` + Open uint64 `protobuf:"varint,3,opt,name=open,proto3" json:"open,omitempty"` + Keepalive uint64 `protobuf:"varint,4,opt,name=keepalive,proto3" json:"keepalive,omitempty"` + Refresh uint64 `protobuf:"varint,5,opt,name=refresh,proto3" json:"refresh,omitempty"` + Discarded uint64 `protobuf:"varint,6,opt,name=discarded,proto3" json:"discarded,omitempty"` + Total uint64 `protobuf:"varint,7,opt,name=total,proto3" json:"total,omitempty"` + WithdrawUpdate uint64 `protobuf:"varint,8,opt,name=withdraw_update,json=withdrawUpdate,proto3" json:"withdraw_update,omitempty"` + WithdrawPrefix uint64 `protobuf:"varint,9,opt,name=withdraw_prefix,json=withdrawPrefix,proto3" json:"withdraw_prefix,omitempty"` +} + +func (x *Message) Reset() { + *x = Message{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[90] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Message) ProtoMessage() {} + +func (x *Message) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[90] + 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 Message.ProtoReflect.Descriptor instead. +func (*Message) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{90} +} + +func (x *Message) GetNotification() uint64 { + if x != nil { + return x.Notification + } + return 0 +} + +func (x *Message) GetUpdate() uint64 { + if x != nil { + return x.Update + } + return 0 +} + +func (x *Message) GetOpen() uint64 { + if x != nil { + return x.Open + } + return 0 +} + +func (x *Message) GetKeepalive() uint64 { + if x != nil { + return x.Keepalive + } + return 0 +} + +func (x *Message) GetRefresh() uint64 { + if x != nil { + return x.Refresh + } + return 0 +} + +func (x *Message) GetDiscarded() uint64 { + if x != nil { + return x.Discarded + } + return 0 +} + +func (x *Message) GetTotal() uint64 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *Message) GetWithdrawUpdate() uint64 { + if x != nil { + return x.WithdrawUpdate + } + return 0 +} + +func (x *Message) GetWithdrawPrefix() uint64 { + if x != nil { + return x.WithdrawPrefix + } + return 0 +} + +type Queues struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Input uint32 `protobuf:"varint,1,opt,name=input,proto3" json:"input,omitempty"` + Output uint32 `protobuf:"varint,2,opt,name=output,proto3" json:"output,omitempty"` +} + +func (x *Queues) Reset() { + *x = Queues{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[91] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Queues) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Queues) ProtoMessage() {} + +func (x *Queues) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[91] + 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 Queues.ProtoReflect.Descriptor instead. +func (*Queues) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{91} +} + +func (x *Queues) GetInput() uint32 { + if x != nil { + return x.Input + } + return 0 +} + +func (x *Queues) GetOutput() uint32 { + if x != nil { + return x.Output + } + return 0 +} + +type Timers struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *TimersConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *TimersState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *Timers) Reset() { + *x = Timers{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[92] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Timers) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Timers) ProtoMessage() {} + +func (x *Timers) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[92] + 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 Timers.ProtoReflect.Descriptor instead. +func (*Timers) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{92} +} + +func (x *Timers) GetConfig() *TimersConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *Timers) GetState() *TimersState { + if x != nil { + return x.State + } + return nil +} + +type TimersConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConnectRetry uint64 `protobuf:"varint,1,opt,name=connect_retry,json=connectRetry,proto3" json:"connect_retry,omitempty"` + HoldTime uint64 `protobuf:"varint,2,opt,name=hold_time,json=holdTime,proto3" json:"hold_time,omitempty"` + KeepaliveInterval uint64 `protobuf:"varint,3,opt,name=keepalive_interval,json=keepaliveInterval,proto3" json:"keepalive_interval,omitempty"` + MinimumAdvertisementInterval uint64 `protobuf:"varint,4,opt,name=minimum_advertisement_interval,json=minimumAdvertisementInterval,proto3" json:"minimum_advertisement_interval,omitempty"` + IdleHoldTimeAfterReset uint64 `protobuf:"varint,5,opt,name=idle_hold_time_after_reset,json=idleHoldTimeAfterReset,proto3" json:"idle_hold_time_after_reset,omitempty"` +} + +func (x *TimersConfig) Reset() { + *x = TimersConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[93] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TimersConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TimersConfig) ProtoMessage() {} + +func (x *TimersConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[93] + 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 TimersConfig.ProtoReflect.Descriptor instead. +func (*TimersConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{93} +} + +func (x *TimersConfig) GetConnectRetry() uint64 { + if x != nil { + return x.ConnectRetry + } + return 0 +} + +func (x *TimersConfig) GetHoldTime() uint64 { + if x != nil { + return x.HoldTime + } + return 0 +} + +func (x *TimersConfig) GetKeepaliveInterval() uint64 { + if x != nil { + return x.KeepaliveInterval + } + return 0 +} + +func (x *TimersConfig) GetMinimumAdvertisementInterval() uint64 { + if x != nil { + return x.MinimumAdvertisementInterval + } + return 0 +} + +func (x *TimersConfig) GetIdleHoldTimeAfterReset() uint64 { + if x != nil { + return x.IdleHoldTimeAfterReset + } + return 0 +} + +type TimersState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConnectRetry uint64 `protobuf:"varint,1,opt,name=connect_retry,json=connectRetry,proto3" json:"connect_retry,omitempty"` + HoldTime uint64 `protobuf:"varint,2,opt,name=hold_time,json=holdTime,proto3" json:"hold_time,omitempty"` + KeepaliveInterval uint64 `protobuf:"varint,3,opt,name=keepalive_interval,json=keepaliveInterval,proto3" json:"keepalive_interval,omitempty"` + MinimumAdvertisementInterval uint64 `protobuf:"varint,4,opt,name=minimum_advertisement_interval,json=minimumAdvertisementInterval,proto3" json:"minimum_advertisement_interval,omitempty"` + NegotiatedHoldTime uint64 `protobuf:"varint,5,opt,name=negotiated_hold_time,json=negotiatedHoldTime,proto3" json:"negotiated_hold_time,omitempty"` + Uptime *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=uptime,proto3" json:"uptime,omitempty"` + Downtime *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=downtime,proto3" json:"downtime,omitempty"` +} + +func (x *TimersState) Reset() { + *x = TimersState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[94] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TimersState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TimersState) ProtoMessage() {} + +func (x *TimersState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[94] + 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 TimersState.ProtoReflect.Descriptor instead. +func (*TimersState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{94} +} + +func (x *TimersState) GetConnectRetry() uint64 { + if x != nil { + return x.ConnectRetry + } + return 0 +} + +func (x *TimersState) GetHoldTime() uint64 { + if x != nil { + return x.HoldTime + } + return 0 +} + +func (x *TimersState) GetKeepaliveInterval() uint64 { + if x != nil { + return x.KeepaliveInterval + } + return 0 +} + +func (x *TimersState) GetMinimumAdvertisementInterval() uint64 { + if x != nil { + return x.MinimumAdvertisementInterval + } + return 0 +} + +func (x *TimersState) GetNegotiatedHoldTime() uint64 { + if x != nil { + return x.NegotiatedHoldTime + } + return 0 +} + +func (x *TimersState) GetUptime() *timestamppb.Timestamp { + if x != nil { + return x.Uptime + } + return nil +} + +func (x *TimersState) GetDowntime() *timestamppb.Timestamp { + if x != nil { + return x.Downtime + } + return nil +} + +type Transport struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LocalAddress string `protobuf:"bytes,1,opt,name=local_address,json=localAddress,proto3" json:"local_address,omitempty"` + LocalPort uint32 `protobuf:"varint,2,opt,name=local_port,json=localPort,proto3" json:"local_port,omitempty"` + MtuDiscovery bool `protobuf:"varint,3,opt,name=mtu_discovery,json=mtuDiscovery,proto3" json:"mtu_discovery,omitempty"` + PassiveMode bool `protobuf:"varint,4,opt,name=passive_mode,json=passiveMode,proto3" json:"passive_mode,omitempty"` + RemoteAddress string `protobuf:"bytes,5,opt,name=remote_address,json=remoteAddress,proto3" json:"remote_address,omitempty"` + RemotePort uint32 `protobuf:"varint,6,opt,name=remote_port,json=remotePort,proto3" json:"remote_port,omitempty"` + TcpMss uint32 `protobuf:"varint,7,opt,name=tcp_mss,json=tcpMss,proto3" json:"tcp_mss,omitempty"` + BindInterface string `protobuf:"bytes,8,opt,name=bind_interface,json=bindInterface,proto3" json:"bind_interface,omitempty"` +} + +func (x *Transport) Reset() { + *x = Transport{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[95] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Transport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Transport) ProtoMessage() {} + +func (x *Transport) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[95] + 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 Transport.ProtoReflect.Descriptor instead. +func (*Transport) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{95} +} + +func (x *Transport) GetLocalAddress() string { + if x != nil { + return x.LocalAddress + } + return "" +} + +func (x *Transport) GetLocalPort() uint32 { + if x != nil { + return x.LocalPort + } + return 0 +} + +func (x *Transport) GetMtuDiscovery() bool { + if x != nil { + return x.MtuDiscovery + } + return false +} + +func (x *Transport) GetPassiveMode() bool { + if x != nil { + return x.PassiveMode + } + return false +} + +func (x *Transport) GetRemoteAddress() string { + if x != nil { + return x.RemoteAddress + } + return "" +} + +func (x *Transport) GetRemotePort() uint32 { + if x != nil { + return x.RemotePort + } + return 0 +} + +func (x *Transport) GetTcpMss() uint32 { + if x != nil { + return x.TcpMss + } + return 0 +} + +func (x *Transport) GetBindInterface() string { + if x != nil { + return x.BindInterface + } + return "" +} + +type RouteServer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RouteServerClient bool `protobuf:"varint,1,opt,name=route_server_client,json=routeServerClient,proto3" json:"route_server_client,omitempty"` + SecondaryRoute bool `protobuf:"varint,2,opt,name=secondary_route,json=secondaryRoute,proto3" json:"secondary_route,omitempty"` +} + +func (x *RouteServer) Reset() { + *x = RouteServer{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[96] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteServer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteServer) ProtoMessage() {} + +func (x *RouteServer) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[96] + 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 RouteServer.ProtoReflect.Descriptor instead. +func (*RouteServer) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{96} +} + +func (x *RouteServer) GetRouteServerClient() bool { + if x != nil { + return x.RouteServerClient + } + return false +} + +func (x *RouteServer) GetSecondaryRoute() bool { + if x != nil { + return x.SecondaryRoute + } + return false +} + +type GracefulRestart struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + RestartTime uint32 `protobuf:"varint,2,opt,name=restart_time,json=restartTime,proto3" json:"restart_time,omitempty"` + HelperOnly bool `protobuf:"varint,3,opt,name=helper_only,json=helperOnly,proto3" json:"helper_only,omitempty"` + DeferralTime uint32 `protobuf:"varint,4,opt,name=deferral_time,json=deferralTime,proto3" json:"deferral_time,omitempty"` + NotificationEnabled bool `protobuf:"varint,5,opt,name=notification_enabled,json=notificationEnabled,proto3" json:"notification_enabled,omitempty"` + LonglivedEnabled bool `protobuf:"varint,6,opt,name=longlived_enabled,json=longlivedEnabled,proto3" json:"longlived_enabled,omitempty"` + StaleRoutesTime uint32 `protobuf:"varint,7,opt,name=stale_routes_time,json=staleRoutesTime,proto3" json:"stale_routes_time,omitempty"` + PeerRestartTime uint32 `protobuf:"varint,8,opt,name=peer_restart_time,json=peerRestartTime,proto3" json:"peer_restart_time,omitempty"` + PeerRestarting bool `protobuf:"varint,9,opt,name=peer_restarting,json=peerRestarting,proto3" json:"peer_restarting,omitempty"` + LocalRestarting bool `protobuf:"varint,10,opt,name=local_restarting,json=localRestarting,proto3" json:"local_restarting,omitempty"` + Mode string `protobuf:"bytes,11,opt,name=mode,proto3" json:"mode,omitempty"` +} + +func (x *GracefulRestart) Reset() { + *x = GracefulRestart{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[97] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GracefulRestart) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GracefulRestart) ProtoMessage() {} + +func (x *GracefulRestart) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[97] + 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 GracefulRestart.ProtoReflect.Descriptor instead. +func (*GracefulRestart) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{97} +} + +func (x *GracefulRestart) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *GracefulRestart) GetRestartTime() uint32 { + if x != nil { + return x.RestartTime + } + return 0 +} + +func (x *GracefulRestart) GetHelperOnly() bool { + if x != nil { + return x.HelperOnly + } + return false +} + +func (x *GracefulRestart) GetDeferralTime() uint32 { + if x != nil { + return x.DeferralTime + } + return 0 +} + +func (x *GracefulRestart) GetNotificationEnabled() bool { + if x != nil { + return x.NotificationEnabled + } + return false +} + +func (x *GracefulRestart) GetLonglivedEnabled() bool { + if x != nil { + return x.LonglivedEnabled + } + return false +} + +func (x *GracefulRestart) GetStaleRoutesTime() uint32 { + if x != nil { + return x.StaleRoutesTime + } + return 0 +} + +func (x *GracefulRestart) GetPeerRestartTime() uint32 { + if x != nil { + return x.PeerRestartTime + } + return 0 +} + +func (x *GracefulRestart) GetPeerRestarting() bool { + if x != nil { + return x.PeerRestarting + } + return false +} + +func (x *GracefulRestart) GetLocalRestarting() bool { + if x != nil { + return x.LocalRestarting + } + return false +} + +func (x *GracefulRestart) GetMode() string { + if x != nil { + return x.Mode + } + return "" +} + +type MpGracefulRestartConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *MpGracefulRestartConfig) Reset() { + *x = MpGracefulRestartConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[98] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MpGracefulRestartConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MpGracefulRestartConfig) ProtoMessage() {} + +func (x *MpGracefulRestartConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[98] + 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 MpGracefulRestartConfig.ProtoReflect.Descriptor instead. +func (*MpGracefulRestartConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{98} +} + +func (x *MpGracefulRestartConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type MpGracefulRestartState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Received bool `protobuf:"varint,2,opt,name=received,proto3" json:"received,omitempty"` + Advertised bool `protobuf:"varint,3,opt,name=advertised,proto3" json:"advertised,omitempty"` + EndOfRibReceived bool `protobuf:"varint,4,opt,name=end_of_rib_received,json=endOfRibReceived,proto3" json:"end_of_rib_received,omitempty"` + EndOfRibSent bool `protobuf:"varint,5,opt,name=end_of_rib_sent,json=endOfRibSent,proto3" json:"end_of_rib_sent,omitempty"` +} + +func (x *MpGracefulRestartState) Reset() { + *x = MpGracefulRestartState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[99] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MpGracefulRestartState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MpGracefulRestartState) ProtoMessage() {} + +func (x *MpGracefulRestartState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[99] + 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 MpGracefulRestartState.ProtoReflect.Descriptor instead. +func (*MpGracefulRestartState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{99} +} + +func (x *MpGracefulRestartState) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *MpGracefulRestartState) GetReceived() bool { + if x != nil { + return x.Received + } + return false +} + +func (x *MpGracefulRestartState) GetAdvertised() bool { + if x != nil { + return x.Advertised + } + return false +} + +func (x *MpGracefulRestartState) GetEndOfRibReceived() bool { + if x != nil { + return x.EndOfRibReceived + } + return false +} + +func (x *MpGracefulRestartState) GetEndOfRibSent() bool { + if x != nil { + return x.EndOfRibSent + } + return false +} + +type MpGracefulRestart struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *MpGracefulRestartConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *MpGracefulRestartState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *MpGracefulRestart) Reset() { + *x = MpGracefulRestart{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[100] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MpGracefulRestart) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MpGracefulRestart) ProtoMessage() {} + +func (x *MpGracefulRestart) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[100] + 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 MpGracefulRestart.ProtoReflect.Descriptor instead. +func (*MpGracefulRestart) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{100} +} + +func (x *MpGracefulRestart) GetConfig() *MpGracefulRestartConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *MpGracefulRestart) GetState() *MpGracefulRestartState { + if x != nil { + return x.State + } + return nil +} + +type AfiSafiConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *AfiSafiConfig) Reset() { + *x = AfiSafiConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[101] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AfiSafiConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AfiSafiConfig) ProtoMessage() {} + +func (x *AfiSafiConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[101] + 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 AfiSafiConfig.ProtoReflect.Descriptor instead. +func (*AfiSafiConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{101} +} + +func (x *AfiSafiConfig) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *AfiSafiConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type AfiSafiState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Family *Family `protobuf:"bytes,1,opt,name=family,proto3" json:"family,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + Received uint64 `protobuf:"varint,3,opt,name=received,proto3" json:"received,omitempty"` + Accepted uint64 `protobuf:"varint,4,opt,name=accepted,proto3" json:"accepted,omitempty"` + Advertised uint64 `protobuf:"varint,5,opt,name=advertised,proto3" json:"advertised,omitempty"` +} + +func (x *AfiSafiState) Reset() { + *x = AfiSafiState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[102] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AfiSafiState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AfiSafiState) ProtoMessage() {} + +func (x *AfiSafiState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[102] + 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 AfiSafiState.ProtoReflect.Descriptor instead. +func (*AfiSafiState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{102} +} + +func (x *AfiSafiState) GetFamily() *Family { + if x != nil { + return x.Family + } + return nil +} + +func (x *AfiSafiState) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *AfiSafiState) GetReceived() uint64 { + if x != nil { + return x.Received + } + return 0 +} + +func (x *AfiSafiState) GetAccepted() uint64 { + if x != nil { + return x.Accepted + } + return 0 +} + +func (x *AfiSafiState) GetAdvertised() uint64 { + if x != nil { + return x.Advertised + } + return 0 +} + +type RouteSelectionOptionsConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed,proto3" json:"always_compare_med,omitempty"` + IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength,proto3" json:"ignore_as_path_length,omitempty"` + ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId,proto3" json:"external_compare_router_id,omitempty"` + AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes,proto3" json:"advertise_inactive_routes,omitempty"` + EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp,proto3" json:"enable_aigp,omitempty"` + IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric,proto3" json:"ignore_next_hop_igp_metric,omitempty"` + DisableBestPathSelection bool `protobuf:"varint,7,opt,name=disable_best_path_selection,json=disableBestPathSelection,proto3" json:"disable_best_path_selection,omitempty"` +} + +func (x *RouteSelectionOptionsConfig) Reset() { + *x = RouteSelectionOptionsConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[103] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteSelectionOptionsConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteSelectionOptionsConfig) ProtoMessage() {} + +func (x *RouteSelectionOptionsConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[103] + 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 RouteSelectionOptionsConfig.ProtoReflect.Descriptor instead. +func (*RouteSelectionOptionsConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{103} +} + +func (x *RouteSelectionOptionsConfig) GetAlwaysCompareMed() bool { + if x != nil { + return x.AlwaysCompareMed + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetIgnoreAsPathLength() bool { + if x != nil { + return x.IgnoreAsPathLength + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetExternalCompareRouterId() bool { + if x != nil { + return x.ExternalCompareRouterId + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetAdvertiseInactiveRoutes() bool { + if x != nil { + return x.AdvertiseInactiveRoutes + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetEnableAigp() bool { + if x != nil { + return x.EnableAigp + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetIgnoreNextHopIgpMetric() bool { + if x != nil { + return x.IgnoreNextHopIgpMetric + } + return false +} + +func (x *RouteSelectionOptionsConfig) GetDisableBestPathSelection() bool { + if x != nil { + return x.DisableBestPathSelection + } + return false +} + +type RouteSelectionOptionsState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed,proto3" json:"always_compare_med,omitempty"` + IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength,proto3" json:"ignore_as_path_length,omitempty"` + ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId,proto3" json:"external_compare_router_id,omitempty"` + AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes,proto3" json:"advertise_inactive_routes,omitempty"` + EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp,proto3" json:"enable_aigp,omitempty"` + IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric,proto3" json:"ignore_next_hop_igp_metric,omitempty"` + DisableBestPathSelection bool `protobuf:"varint,7,opt,name=disable_best_path_selection,json=disableBestPathSelection,proto3" json:"disable_best_path_selection,omitempty"` +} + +func (x *RouteSelectionOptionsState) Reset() { + *x = RouteSelectionOptionsState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[104] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteSelectionOptionsState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteSelectionOptionsState) ProtoMessage() {} + +func (x *RouteSelectionOptionsState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[104] + 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 RouteSelectionOptionsState.ProtoReflect.Descriptor instead. +func (*RouteSelectionOptionsState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{104} +} + +func (x *RouteSelectionOptionsState) GetAlwaysCompareMed() bool { + if x != nil { + return x.AlwaysCompareMed + } + return false +} + +func (x *RouteSelectionOptionsState) GetIgnoreAsPathLength() bool { + if x != nil { + return x.IgnoreAsPathLength + } + return false +} + +func (x *RouteSelectionOptionsState) GetExternalCompareRouterId() bool { + if x != nil { + return x.ExternalCompareRouterId + } + return false +} + +func (x *RouteSelectionOptionsState) GetAdvertiseInactiveRoutes() bool { + if x != nil { + return x.AdvertiseInactiveRoutes + } + return false +} + +func (x *RouteSelectionOptionsState) GetEnableAigp() bool { + if x != nil { + return x.EnableAigp + } + return false +} + +func (x *RouteSelectionOptionsState) GetIgnoreNextHopIgpMetric() bool { + if x != nil { + return x.IgnoreNextHopIgpMetric + } + return false +} + +func (x *RouteSelectionOptionsState) GetDisableBestPathSelection() bool { + if x != nil { + return x.DisableBestPathSelection + } + return false +} + +type RouteSelectionOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *RouteSelectionOptionsConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *RouteSelectionOptionsState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *RouteSelectionOptions) Reset() { + *x = RouteSelectionOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[105] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteSelectionOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteSelectionOptions) ProtoMessage() {} + +func (x *RouteSelectionOptions) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[105] + 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 RouteSelectionOptions.ProtoReflect.Descriptor instead. +func (*RouteSelectionOptions) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{105} +} + +func (x *RouteSelectionOptions) GetConfig() *RouteSelectionOptionsConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *RouteSelectionOptions) GetState() *RouteSelectionOptionsState { + if x != nil { + return x.State + } + return nil +} + +type UseMultiplePathsConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *UseMultiplePathsConfig) Reset() { + *x = UseMultiplePathsConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[106] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UseMultiplePathsConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UseMultiplePathsConfig) ProtoMessage() {} + +func (x *UseMultiplePathsConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[106] + 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 UseMultiplePathsConfig.ProtoReflect.Descriptor instead. +func (*UseMultiplePathsConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{106} +} + +func (x *UseMultiplePathsConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type UseMultiplePathsState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *UseMultiplePathsState) Reset() { + *x = UseMultiplePathsState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[107] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UseMultiplePathsState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UseMultiplePathsState) ProtoMessage() {} + +func (x *UseMultiplePathsState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[107] + 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 UseMultiplePathsState.ProtoReflect.Descriptor instead. +func (*UseMultiplePathsState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{107} +} + +func (x *UseMultiplePathsState) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type EbgpConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AllowMultipleAsn bool `protobuf:"varint,1,opt,name=allow_multiple_asn,json=allowMultipleAsn,proto3" json:"allow_multiple_asn,omitempty"` + MaximumPaths uint32 `protobuf:"varint,2,opt,name=maximum_paths,json=maximumPaths,proto3" json:"maximum_paths,omitempty"` +} + +func (x *EbgpConfig) Reset() { + *x = EbgpConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[108] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EbgpConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EbgpConfig) ProtoMessage() {} + +func (x *EbgpConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[108] + 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 EbgpConfig.ProtoReflect.Descriptor instead. +func (*EbgpConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{108} +} + +func (x *EbgpConfig) GetAllowMultipleAsn() bool { + if x != nil { + return x.AllowMultipleAsn + } + return false +} + +func (x *EbgpConfig) GetMaximumPaths() uint32 { + if x != nil { + return x.MaximumPaths + } + return 0 +} + +type EbgpState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AllowMultipleAsn bool `protobuf:"varint,1,opt,name=allow_multiple_asn,json=allowMultipleAsn,proto3" json:"allow_multiple_asn,omitempty"` + MaximumPaths uint32 `protobuf:"varint,2,opt,name=maximum_paths,json=maximumPaths,proto3" json:"maximum_paths,omitempty"` +} + +func (x *EbgpState) Reset() { + *x = EbgpState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[109] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EbgpState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EbgpState) ProtoMessage() {} + +func (x *EbgpState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[109] + 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 EbgpState.ProtoReflect.Descriptor instead. +func (*EbgpState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{109} +} + +func (x *EbgpState) GetAllowMultipleAsn() bool { + if x != nil { + return x.AllowMultipleAsn + } + return false +} + +func (x *EbgpState) GetMaximumPaths() uint32 { + if x != nil { + return x.MaximumPaths + } + return 0 +} + +type Ebgp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *EbgpConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *EbgpState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *Ebgp) Reset() { + *x = Ebgp{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[110] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ebgp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ebgp) ProtoMessage() {} + +func (x *Ebgp) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[110] + 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 Ebgp.ProtoReflect.Descriptor instead. +func (*Ebgp) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{110} +} + +func (x *Ebgp) GetConfig() *EbgpConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *Ebgp) GetState() *EbgpState { + if x != nil { + return x.State + } + return nil +} + +type IbgpConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MaximumPaths uint32 `protobuf:"varint,1,opt,name=maximum_paths,json=maximumPaths,proto3" json:"maximum_paths,omitempty"` +} + +func (x *IbgpConfig) Reset() { + *x = IbgpConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[111] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IbgpConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IbgpConfig) ProtoMessage() {} + +func (x *IbgpConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[111] + 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 IbgpConfig.ProtoReflect.Descriptor instead. +func (*IbgpConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{111} +} + +func (x *IbgpConfig) GetMaximumPaths() uint32 { + if x != nil { + return x.MaximumPaths + } + return 0 +} + +type IbgpState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MaximumPaths uint32 `protobuf:"varint,1,opt,name=maximum_paths,json=maximumPaths,proto3" json:"maximum_paths,omitempty"` +} + +func (x *IbgpState) Reset() { + *x = IbgpState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[112] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IbgpState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IbgpState) ProtoMessage() {} + +func (x *IbgpState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[112] + 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 IbgpState.ProtoReflect.Descriptor instead. +func (*IbgpState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{112} +} + +func (x *IbgpState) GetMaximumPaths() uint32 { + if x != nil { + return x.MaximumPaths + } + return 0 +} + +type Ibgp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *IbgpConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *IbgpState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *Ibgp) Reset() { + *x = Ibgp{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[113] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ibgp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ibgp) ProtoMessage() {} + +func (x *Ibgp) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[113] + 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 Ibgp.ProtoReflect.Descriptor instead. +func (*Ibgp) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{113} +} + +func (x *Ibgp) GetConfig() *IbgpConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *Ibgp) GetState() *IbgpState { + if x != nil { + return x.State + } + return nil +} + +type UseMultiplePaths struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *UseMultiplePathsConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *UseMultiplePathsState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + Ebgp *Ebgp `protobuf:"bytes,3,opt,name=ebgp,proto3" json:"ebgp,omitempty"` + Ibgp *Ibgp `protobuf:"bytes,4,opt,name=ibgp,proto3" json:"ibgp,omitempty"` +} + +func (x *UseMultiplePaths) Reset() { + *x = UseMultiplePaths{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[114] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UseMultiplePaths) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UseMultiplePaths) ProtoMessage() {} + +func (x *UseMultiplePaths) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[114] + 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 UseMultiplePaths.ProtoReflect.Descriptor instead. +func (*UseMultiplePaths) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{114} +} + +func (x *UseMultiplePaths) GetConfig() *UseMultiplePathsConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *UseMultiplePaths) GetState() *UseMultiplePathsState { + if x != nil { + return x.State + } + return nil +} + +func (x *UseMultiplePaths) GetEbgp() *Ebgp { + if x != nil { + return x.Ebgp + } + return nil +} + +func (x *UseMultiplePaths) GetIbgp() *Ibgp { + if x != nil { + return x.Ibgp + } + return nil +} + +type RouteTargetMembershipConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeferralTime uint32 `protobuf:"varint,1,opt,name=deferral_time,json=deferralTime,proto3" json:"deferral_time,omitempty"` +} + +func (x *RouteTargetMembershipConfig) Reset() { + *x = RouteTargetMembershipConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[115] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteTargetMembershipConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteTargetMembershipConfig) ProtoMessage() {} + +func (x *RouteTargetMembershipConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[115] + 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 RouteTargetMembershipConfig.ProtoReflect.Descriptor instead. +func (*RouteTargetMembershipConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{115} +} + +func (x *RouteTargetMembershipConfig) GetDeferralTime() uint32 { + if x != nil { + return x.DeferralTime + } + return 0 +} + +type RouteTargetMembershipState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeferralTime uint32 `protobuf:"varint,1,opt,name=deferral_time,json=deferralTime,proto3" json:"deferral_time,omitempty"` +} + +func (x *RouteTargetMembershipState) Reset() { + *x = RouteTargetMembershipState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[116] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteTargetMembershipState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteTargetMembershipState) ProtoMessage() {} + +func (x *RouteTargetMembershipState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[116] + 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 RouteTargetMembershipState.ProtoReflect.Descriptor instead. +func (*RouteTargetMembershipState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{116} +} + +func (x *RouteTargetMembershipState) GetDeferralTime() uint32 { + if x != nil { + return x.DeferralTime + } + return 0 +} + +type RouteTargetMembership struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *RouteTargetMembershipConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *RouteTargetMembershipState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *RouteTargetMembership) Reset() { + *x = RouteTargetMembership{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[117] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RouteTargetMembership) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RouteTargetMembership) ProtoMessage() {} + +func (x *RouteTargetMembership) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[117] + 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 RouteTargetMembership.ProtoReflect.Descriptor instead. +func (*RouteTargetMembership) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{117} +} + +func (x *RouteTargetMembership) GetConfig() *RouteTargetMembershipConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *RouteTargetMembership) GetState() *RouteTargetMembershipState { + if x != nil { + return x.State + } + return nil +} + +type LongLivedGracefulRestartConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + RestartTime uint32 `protobuf:"varint,2,opt,name=restart_time,json=restartTime,proto3" json:"restart_time,omitempty"` +} + +func (x *LongLivedGracefulRestartConfig) Reset() { + *x = LongLivedGracefulRestartConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[118] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LongLivedGracefulRestartConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LongLivedGracefulRestartConfig) ProtoMessage() {} + +func (x *LongLivedGracefulRestartConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[118] + 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 LongLivedGracefulRestartConfig.ProtoReflect.Descriptor instead. +func (*LongLivedGracefulRestartConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{118} +} + +func (x *LongLivedGracefulRestartConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *LongLivedGracefulRestartConfig) GetRestartTime() uint32 { + if x != nil { + return x.RestartTime + } + return 0 +} + +type LongLivedGracefulRestartState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Received bool `protobuf:"varint,2,opt,name=received,proto3" json:"received,omitempty"` + Advertised bool `protobuf:"varint,3,opt,name=advertised,proto3" json:"advertised,omitempty"` + PeerRestartTime uint32 `protobuf:"varint,4,opt,name=peer_restart_time,json=peerRestartTime,proto3" json:"peer_restart_time,omitempty"` + PeerRestartTimerExpired bool `protobuf:"varint,5,opt,name=peer_restart_timer_expired,json=peerRestartTimerExpired,proto3" json:"peer_restart_timer_expired,omitempty"` +} + +func (x *LongLivedGracefulRestartState) Reset() { + *x = LongLivedGracefulRestartState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[119] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LongLivedGracefulRestartState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LongLivedGracefulRestartState) ProtoMessage() {} + +func (x *LongLivedGracefulRestartState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[119] + 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 LongLivedGracefulRestartState.ProtoReflect.Descriptor instead. +func (*LongLivedGracefulRestartState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{119} +} + +func (x *LongLivedGracefulRestartState) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *LongLivedGracefulRestartState) GetReceived() bool { + if x != nil { + return x.Received + } + return false +} + +func (x *LongLivedGracefulRestartState) GetAdvertised() bool { + if x != nil { + return x.Advertised + } + return false +} + +func (x *LongLivedGracefulRestartState) GetPeerRestartTime() uint32 { + if x != nil { + return x.PeerRestartTime + } + return 0 +} + +func (x *LongLivedGracefulRestartState) GetPeerRestartTimerExpired() bool { + if x != nil { + return x.PeerRestartTimerExpired + } + return false +} + +type LongLivedGracefulRestart struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *LongLivedGracefulRestartConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *LongLivedGracefulRestartState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *LongLivedGracefulRestart) Reset() { + *x = LongLivedGracefulRestart{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[120] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LongLivedGracefulRestart) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LongLivedGracefulRestart) ProtoMessage() {} + +func (x *LongLivedGracefulRestart) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[120] + 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 LongLivedGracefulRestart.ProtoReflect.Descriptor instead. +func (*LongLivedGracefulRestart) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{120} +} + +func (x *LongLivedGracefulRestart) GetConfig() *LongLivedGracefulRestartConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *LongLivedGracefulRestart) GetState() *LongLivedGracefulRestartState { + if x != nil { + return x.State + } + return nil +} + +type AfiSafi struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MpGracefulRestart *MpGracefulRestart `protobuf:"bytes,1,opt,name=mp_graceful_restart,json=mpGracefulRestart,proto3" json:"mp_graceful_restart,omitempty"` + Config *AfiSafiConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + State *AfiSafiState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + ApplyPolicy *ApplyPolicy `protobuf:"bytes,4,opt,name=apply_policy,json=applyPolicy,proto3" json:"apply_policy,omitempty"` + // TODO: + // Support the following structures: + // - Ipv4Unicast + // - Ipv6Unicast + // - Ipv4LabelledUnicast + // - Ipv6LabelledUnicast + // - L3vpnIpv4Unicast + // - L3vpnIpv6Unicast + // - L3vpnIpv4Multicast + // - L3vpnIpv6Multicast + // - L2vpnVpls + // - L2vpnEvpn + RouteSelectionOptions *RouteSelectionOptions `protobuf:"bytes,5,opt,name=route_selection_options,json=routeSelectionOptions,proto3" json:"route_selection_options,omitempty"` + UseMultiplePaths *UseMultiplePaths `protobuf:"bytes,6,opt,name=use_multiple_paths,json=useMultiplePaths,proto3" json:"use_multiple_paths,omitempty"` + PrefixLimits *PrefixLimit `protobuf:"bytes,7,opt,name=prefix_limits,json=prefixLimits,proto3" json:"prefix_limits,omitempty"` + RouteTargetMembership *RouteTargetMembership `protobuf:"bytes,8,opt,name=route_target_membership,json=routeTargetMembership,proto3" json:"route_target_membership,omitempty"` + LongLivedGracefulRestart *LongLivedGracefulRestart `protobuf:"bytes,9,opt,name=long_lived_graceful_restart,json=longLivedGracefulRestart,proto3" json:"long_lived_graceful_restart,omitempty"` + AddPaths *AddPaths `protobuf:"bytes,10,opt,name=add_paths,json=addPaths,proto3" json:"add_paths,omitempty"` +} + +func (x *AfiSafi) Reset() { + *x = AfiSafi{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[121] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AfiSafi) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AfiSafi) ProtoMessage() {} + +func (x *AfiSafi) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[121] + 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 AfiSafi.ProtoReflect.Descriptor instead. +func (*AfiSafi) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{121} +} + +func (x *AfiSafi) GetMpGracefulRestart() *MpGracefulRestart { + if x != nil { + return x.MpGracefulRestart + } + return nil +} + +func (x *AfiSafi) GetConfig() *AfiSafiConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *AfiSafi) GetState() *AfiSafiState { + if x != nil { + return x.State + } + return nil +} + +func (x *AfiSafi) GetApplyPolicy() *ApplyPolicy { + if x != nil { + return x.ApplyPolicy + } + return nil +} + +func (x *AfiSafi) GetRouteSelectionOptions() *RouteSelectionOptions { + if x != nil { + return x.RouteSelectionOptions + } + return nil +} + +func (x *AfiSafi) GetUseMultiplePaths() *UseMultiplePaths { + if x != nil { + return x.UseMultiplePaths + } + return nil +} + +func (x *AfiSafi) GetPrefixLimits() *PrefixLimit { + if x != nil { + return x.PrefixLimits + } + return nil +} + +func (x *AfiSafi) GetRouteTargetMembership() *RouteTargetMembership { + if x != nil { + return x.RouteTargetMembership + } + return nil +} + +func (x *AfiSafi) GetLongLivedGracefulRestart() *LongLivedGracefulRestart { + if x != nil { + return x.LongLivedGracefulRestart + } + return nil +} + +func (x *AfiSafi) GetAddPaths() *AddPaths { + if x != nil { + return x.AddPaths + } + return nil +} + +type AddPathsConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Receive bool `protobuf:"varint,1,opt,name=receive,proto3" json:"receive,omitempty"` + SendMax uint32 `protobuf:"varint,2,opt,name=send_max,json=sendMax,proto3" json:"send_max,omitempty"` +} + +func (x *AddPathsConfig) Reset() { + *x = AddPathsConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[122] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathsConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathsConfig) ProtoMessage() {} + +func (x *AddPathsConfig) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[122] + 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 AddPathsConfig.ProtoReflect.Descriptor instead. +func (*AddPathsConfig) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{122} +} + +func (x *AddPathsConfig) GetReceive() bool { + if x != nil { + return x.Receive + } + return false +} + +func (x *AddPathsConfig) GetSendMax() uint32 { + if x != nil { + return x.SendMax + } + return 0 +} + +type AddPathsState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Receive bool `protobuf:"varint,1,opt,name=receive,proto3" json:"receive,omitempty"` + SendMax uint32 `protobuf:"varint,2,opt,name=send_max,json=sendMax,proto3" json:"send_max,omitempty"` +} + +func (x *AddPathsState) Reset() { + *x = AddPathsState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[123] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPathsState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPathsState) ProtoMessage() {} + +func (x *AddPathsState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[123] + 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 AddPathsState.ProtoReflect.Descriptor instead. +func (*AddPathsState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{123} +} + +func (x *AddPathsState) GetReceive() bool { + if x != nil { + return x.Receive + } + return false +} + +func (x *AddPathsState) GetSendMax() uint32 { + if x != nil { + return x.SendMax + } + return 0 +} + +type AddPaths struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *AddPathsConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + State *AddPathsState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *AddPaths) Reset() { + *x = AddPaths{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[124] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPaths) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPaths) ProtoMessage() {} + +func (x *AddPaths) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[124] + 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 AddPaths.ProtoReflect.Descriptor instead. +func (*AddPaths) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{124} +} + +func (x *AddPaths) GetConfig() *AddPathsConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *AddPaths) GetState() *AddPathsState { + if x != nil { + return x.State + } + return nil +} + +type Prefix struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IpPrefix string `protobuf:"bytes,1,opt,name=ip_prefix,json=ipPrefix,proto3" json:"ip_prefix,omitempty"` + MaskLengthMin uint32 `protobuf:"varint,2,opt,name=mask_length_min,json=maskLengthMin,proto3" json:"mask_length_min,omitempty"` + MaskLengthMax uint32 `protobuf:"varint,3,opt,name=mask_length_max,json=maskLengthMax,proto3" json:"mask_length_max,omitempty"` +} + +func (x *Prefix) Reset() { + *x = Prefix{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[125] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Prefix) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Prefix) ProtoMessage() {} + +func (x *Prefix) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[125] + 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 Prefix.ProtoReflect.Descriptor instead. +func (*Prefix) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{125} +} + +func (x *Prefix) GetIpPrefix() string { + if x != nil { + return x.IpPrefix + } + return "" +} + +func (x *Prefix) GetMaskLengthMin() uint32 { + if x != nil { + return x.MaskLengthMin + } + return 0 +} + +func (x *Prefix) GetMaskLengthMax() uint32 { + if x != nil { + return x.MaskLengthMax + } + return 0 +} + +type DefinedSet struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedType DefinedType `protobuf:"varint,1,opt,name=defined_type,json=definedType,proto3,enum=apipb.DefinedType" json:"defined_type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + List []string `protobuf:"bytes,3,rep,name=list,proto3" json:"list,omitempty"` + Prefixes []*Prefix `protobuf:"bytes,4,rep,name=prefixes,proto3" json:"prefixes,omitempty"` +} + +func (x *DefinedSet) Reset() { + *x = DefinedSet{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[126] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DefinedSet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DefinedSet) ProtoMessage() {} + +func (x *DefinedSet) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[126] + 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 DefinedSet.ProtoReflect.Descriptor instead. +func (*DefinedSet) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{126} +} + +func (x *DefinedSet) GetDefinedType() DefinedType { + if x != nil { + return x.DefinedType + } + return DefinedType_PREFIX +} + +func (x *DefinedSet) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DefinedSet) GetList() []string { + if x != nil { + return x.List + } + return nil +} + +func (x *DefinedSet) GetPrefixes() []*Prefix { + if x != nil { + return x.Prefixes + } + return nil +} + +type MatchSet struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type MatchSet_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.MatchSet_Type" json:"type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *MatchSet) Reset() { + *x = MatchSet{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[127] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MatchSet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MatchSet) ProtoMessage() {} + +func (x *MatchSet) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[127] + 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 MatchSet.ProtoReflect.Descriptor instead. +func (*MatchSet) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{127} +} + +func (x *MatchSet) GetType() MatchSet_Type { + if x != nil { + return x.Type + } + return MatchSet_ANY +} + +func (x *MatchSet) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type AsPathLength struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type AsPathLength_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.AsPathLength_Type" json:"type,omitempty"` + Length uint32 `protobuf:"varint,2,opt,name=length,proto3" json:"length,omitempty"` +} + +func (x *AsPathLength) Reset() { + *x = AsPathLength{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[128] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AsPathLength) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AsPathLength) ProtoMessage() {} + +func (x *AsPathLength) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[128] + 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 AsPathLength.ProtoReflect.Descriptor instead. +func (*AsPathLength) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{128} +} + +func (x *AsPathLength) GetType() AsPathLength_Type { + if x != nil { + return x.Type + } + return AsPathLength_EQ +} + +func (x *AsPathLength) GetLength() uint32 { + if x != nil { + return x.Length + } + return 0 +} + +type Conditions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PrefixSet *MatchSet `protobuf:"bytes,1,opt,name=prefix_set,json=prefixSet,proto3" json:"prefix_set,omitempty"` + NeighborSet *MatchSet `protobuf:"bytes,2,opt,name=neighbor_set,json=neighborSet,proto3" json:"neighbor_set,omitempty"` + AsPathLength *AsPathLength `protobuf:"bytes,3,opt,name=as_path_length,json=asPathLength,proto3" json:"as_path_length,omitempty"` + AsPathSet *MatchSet `protobuf:"bytes,4,opt,name=as_path_set,json=asPathSet,proto3" json:"as_path_set,omitempty"` + CommunitySet *MatchSet `protobuf:"bytes,5,opt,name=community_set,json=communitySet,proto3" json:"community_set,omitempty"` + ExtCommunitySet *MatchSet `protobuf:"bytes,6,opt,name=ext_community_set,json=extCommunitySet,proto3" json:"ext_community_set,omitempty"` + RpkiResult int32 `protobuf:"varint,7,opt,name=rpki_result,json=rpkiResult,proto3" json:"rpki_result,omitempty"` + RouteType Conditions_RouteType `protobuf:"varint,8,opt,name=route_type,json=routeType,proto3,enum=apipb.Conditions_RouteType" json:"route_type,omitempty"` + LargeCommunitySet *MatchSet `protobuf:"bytes,9,opt,name=large_community_set,json=largeCommunitySet,proto3" json:"large_community_set,omitempty"` + NextHopInList []string `protobuf:"bytes,10,rep,name=next_hop_in_list,json=nextHopInList,proto3" json:"next_hop_in_list,omitempty"` + AfiSafiIn []*Family `protobuf:"bytes,11,rep,name=afi_safi_in,json=afiSafiIn,proto3" json:"afi_safi_in,omitempty"` +} + +func (x *Conditions) Reset() { + *x = Conditions{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[129] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Conditions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Conditions) ProtoMessage() {} + +func (x *Conditions) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[129] + 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 Conditions.ProtoReflect.Descriptor instead. +func (*Conditions) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{129} +} + +func (x *Conditions) GetPrefixSet() *MatchSet { + if x != nil { + return x.PrefixSet + } + return nil +} + +func (x *Conditions) GetNeighborSet() *MatchSet { + if x != nil { + return x.NeighborSet + } + return nil +} + +func (x *Conditions) GetAsPathLength() *AsPathLength { + if x != nil { + return x.AsPathLength + } + return nil +} + +func (x *Conditions) GetAsPathSet() *MatchSet { + if x != nil { + return x.AsPathSet + } + return nil +} + +func (x *Conditions) GetCommunitySet() *MatchSet { + if x != nil { + return x.CommunitySet + } + return nil +} + +func (x *Conditions) GetExtCommunitySet() *MatchSet { + if x != nil { + return x.ExtCommunitySet + } + return nil +} + +func (x *Conditions) GetRpkiResult() int32 { + if x != nil { + return x.RpkiResult + } + return 0 +} + +func (x *Conditions) GetRouteType() Conditions_RouteType { + if x != nil { + return x.RouteType + } + return Conditions_ROUTE_TYPE_NONE +} + +func (x *Conditions) GetLargeCommunitySet() *MatchSet { + if x != nil { + return x.LargeCommunitySet + } + return nil +} + +func (x *Conditions) GetNextHopInList() []string { + if x != nil { + return x.NextHopInList + } + return nil +} + +func (x *Conditions) GetAfiSafiIn() []*Family { + if x != nil { + return x.AfiSafiIn + } + return nil +} + +type CommunityAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type CommunityAction_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.CommunityAction_Type" json:"type,omitempty"` + Communities []string `protobuf:"bytes,2,rep,name=communities,proto3" json:"communities,omitempty"` +} + +func (x *CommunityAction) Reset() { + *x = CommunityAction{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[130] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommunityAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommunityAction) ProtoMessage() {} + +func (x *CommunityAction) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[130] + 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 CommunityAction.ProtoReflect.Descriptor instead. +func (*CommunityAction) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{130} +} + +func (x *CommunityAction) GetType() CommunityAction_Type { + if x != nil { + return x.Type + } + return CommunityAction_ADD +} + +func (x *CommunityAction) GetCommunities() []string { + if x != nil { + return x.Communities + } + return nil +} + +type MedAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type MedAction_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.MedAction_Type" json:"type,omitempty"` + Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *MedAction) Reset() { + *x = MedAction{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[131] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MedAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MedAction) ProtoMessage() {} + +func (x *MedAction) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[131] + 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 MedAction.ProtoReflect.Descriptor instead. +func (*MedAction) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{131} +} + +func (x *MedAction) GetType() MedAction_Type { + if x != nil { + return x.Type + } + return MedAction_MOD +} + +func (x *MedAction) GetValue() int64 { + if x != nil { + return x.Value + } + return 0 +} + +type AsPrependAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + Repeat uint32 `protobuf:"varint,2,opt,name=repeat,proto3" json:"repeat,omitempty"` + UseLeftMost bool `protobuf:"varint,3,opt,name=use_left_most,json=useLeftMost,proto3" json:"use_left_most,omitempty"` +} + +func (x *AsPrependAction) Reset() { + *x = AsPrependAction{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[132] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AsPrependAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AsPrependAction) ProtoMessage() {} + +func (x *AsPrependAction) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[132] + 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 AsPrependAction.ProtoReflect.Descriptor instead. +func (*AsPrependAction) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{132} +} + +func (x *AsPrependAction) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *AsPrependAction) GetRepeat() uint32 { + if x != nil { + return x.Repeat + } + return 0 +} + +func (x *AsPrependAction) GetUseLeftMost() bool { + if x != nil { + return x.UseLeftMost + } + return false +} + +type NexthopAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Self bool `protobuf:"varint,2,opt,name=self,proto3" json:"self,omitempty"` + Unchanged bool `protobuf:"varint,3,opt,name=unchanged,proto3" json:"unchanged,omitempty"` +} + +func (x *NexthopAction) Reset() { + *x = NexthopAction{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[133] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NexthopAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NexthopAction) ProtoMessage() {} + +func (x *NexthopAction) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[133] + 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 NexthopAction.ProtoReflect.Descriptor instead. +func (*NexthopAction) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{133} +} + +func (x *NexthopAction) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *NexthopAction) GetSelf() bool { + if x != nil { + return x.Self + } + return false +} + +func (x *NexthopAction) GetUnchanged() bool { + if x != nil { + return x.Unchanged + } + return false +} + +type LocalPrefAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *LocalPrefAction) Reset() { + *x = LocalPrefAction{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[134] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LocalPrefAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocalPrefAction) ProtoMessage() {} + +func (x *LocalPrefAction) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[134] + 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 LocalPrefAction.ProtoReflect.Descriptor instead. +func (*LocalPrefAction) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{134} +} + +func (x *LocalPrefAction) GetValue() uint32 { + if x != nil { + return x.Value + } + return 0 +} + +type Actions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RouteAction RouteAction `protobuf:"varint,1,opt,name=route_action,json=routeAction,proto3,enum=apipb.RouteAction" json:"route_action,omitempty"` + Community *CommunityAction `protobuf:"bytes,2,opt,name=community,proto3" json:"community,omitempty"` + Med *MedAction `protobuf:"bytes,3,opt,name=med,proto3" json:"med,omitempty"` + AsPrepend *AsPrependAction `protobuf:"bytes,4,opt,name=as_prepend,json=asPrepend,proto3" json:"as_prepend,omitempty"` + ExtCommunity *CommunityAction `protobuf:"bytes,5,opt,name=ext_community,json=extCommunity,proto3" json:"ext_community,omitempty"` + Nexthop *NexthopAction `protobuf:"bytes,6,opt,name=nexthop,proto3" json:"nexthop,omitempty"` + LocalPref *LocalPrefAction `protobuf:"bytes,7,opt,name=local_pref,json=localPref,proto3" json:"local_pref,omitempty"` + LargeCommunity *CommunityAction `protobuf:"bytes,8,opt,name=large_community,json=largeCommunity,proto3" json:"large_community,omitempty"` +} + +func (x *Actions) Reset() { + *x = Actions{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[135] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Actions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Actions) ProtoMessage() {} + +func (x *Actions) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[135] + 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 Actions.ProtoReflect.Descriptor instead. +func (*Actions) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{135} +} + +func (x *Actions) GetRouteAction() RouteAction { + if x != nil { + return x.RouteAction + } + return RouteAction_NONE +} + +func (x *Actions) GetCommunity() *CommunityAction { + if x != nil { + return x.Community + } + return nil +} + +func (x *Actions) GetMed() *MedAction { + if x != nil { + return x.Med + } + return nil +} + +func (x *Actions) GetAsPrepend() *AsPrependAction { + if x != nil { + return x.AsPrepend + } + return nil +} + +func (x *Actions) GetExtCommunity() *CommunityAction { + if x != nil { + return x.ExtCommunity + } + return nil +} + +func (x *Actions) GetNexthop() *NexthopAction { + if x != nil { + return x.Nexthop + } + return nil +} + +func (x *Actions) GetLocalPref() *LocalPrefAction { + if x != nil { + return x.LocalPref + } + return nil +} + +func (x *Actions) GetLargeCommunity() *CommunityAction { + if x != nil { + return x.LargeCommunity + } + return nil +} + +type Statement struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Conditions *Conditions `protobuf:"bytes,2,opt,name=conditions,proto3" json:"conditions,omitempty"` + Actions *Actions `protobuf:"bytes,3,opt,name=actions,proto3" json:"actions,omitempty"` +} + +func (x *Statement) Reset() { + *x = Statement{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[136] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Statement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Statement) ProtoMessage() {} + +func (x *Statement) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[136] + 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 Statement.ProtoReflect.Descriptor instead. +func (*Statement) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{136} +} + +func (x *Statement) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Statement) GetConditions() *Conditions { + if x != nil { + return x.Conditions + } + return nil +} + +func (x *Statement) GetActions() *Actions { + if x != nil { + return x.Actions + } + return nil +} + +type Policy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Statements []*Statement `protobuf:"bytes,2,rep,name=statements,proto3" json:"statements,omitempty"` +} + +func (x *Policy) Reset() { + *x = Policy{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[137] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy) ProtoMessage() {} + +func (x *Policy) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[137] + 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 Policy.ProtoReflect.Descriptor instead. +func (*Policy) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{137} +} + +func (x *Policy) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Policy) GetStatements() []*Statement { + if x != nil { + return x.Statements + } + return nil +} + +type PolicyAssignment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Direction PolicyDirection `protobuf:"varint,2,opt,name=direction,proto3,enum=apipb.PolicyDirection" json:"direction,omitempty"` + Policies []*Policy `protobuf:"bytes,4,rep,name=policies,proto3" json:"policies,omitempty"` + DefaultAction RouteAction `protobuf:"varint,5,opt,name=default_action,json=defaultAction,proto3,enum=apipb.RouteAction" json:"default_action,omitempty"` +} + +func (x *PolicyAssignment) Reset() { + *x = PolicyAssignment{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[138] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyAssignment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyAssignment) ProtoMessage() {} + +func (x *PolicyAssignment) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[138] + 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 PolicyAssignment.ProtoReflect.Descriptor instead. +func (*PolicyAssignment) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{138} +} + +func (x *PolicyAssignment) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *PolicyAssignment) GetDirection() PolicyDirection { + if x != nil { + return x.Direction + } + return PolicyDirection_UNKNOWN +} + +func (x *PolicyAssignment) GetPolicies() []*Policy { + if x != nil { + return x.Policies + } + return nil +} + +func (x *PolicyAssignment) GetDefaultAction() RouteAction { + if x != nil { + return x.DefaultAction + } + return RouteAction_NONE +} + +type RoutingPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DefinedSets []*DefinedSet `protobuf:"bytes,1,rep,name=defined_sets,json=definedSets,proto3" json:"defined_sets,omitempty"` + Policies []*Policy `protobuf:"bytes,2,rep,name=policies,proto3" json:"policies,omitempty"` +} + +func (x *RoutingPolicy) Reset() { + *x = RoutingPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[139] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RoutingPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoutingPolicy) ProtoMessage() {} + +func (x *RoutingPolicy) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[139] + 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 RoutingPolicy.ProtoReflect.Descriptor instead. +func (*RoutingPolicy) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{139} +} + +func (x *RoutingPolicy) GetDefinedSets() []*DefinedSet { + if x != nil { + return x.DefinedSets + } + return nil +} + +func (x *RoutingPolicy) GetPolicies() []*Policy { + if x != nil { + return x.Policies + } + return nil +} + +type Roa struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + Prefixlen uint32 `protobuf:"varint,2,opt,name=prefixlen,proto3" json:"prefixlen,omitempty"` + Maxlen uint32 `protobuf:"varint,3,opt,name=maxlen,proto3" json:"maxlen,omitempty"` + Prefix string `protobuf:"bytes,4,opt,name=prefix,proto3" json:"prefix,omitempty"` + Conf *RPKIConf `protobuf:"bytes,5,opt,name=conf,proto3" json:"conf,omitempty"` +} + +func (x *Roa) Reset() { + *x = Roa{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[140] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Roa) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Roa) ProtoMessage() {} + +func (x *Roa) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[140] + 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 Roa.ProtoReflect.Descriptor instead. +func (*Roa) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{140} +} + +func (x *Roa) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *Roa) GetPrefixlen() uint32 { + if x != nil { + return x.Prefixlen + } + return 0 +} + +func (x *Roa) GetMaxlen() uint32 { + if x != nil { + return x.Maxlen + } + return 0 +} + +func (x *Roa) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +func (x *Roa) GetConf() *RPKIConf { + if x != nil { + return x.Conf + } + return nil +} + +type Vrf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Route Distinguisher must be one of + // RouteDistinguisherTwoOctetAS, + // RouteDistinguisherIPAddressAS, + // or RouteDistinguisherFourOctetAS. + Rd *anypb.Any `protobuf:"bytes,2,opt,name=rd,proto3" json:"rd,omitempty"` + // List of the Import Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + ImportRt []*anypb.Any `protobuf:"bytes,3,rep,name=import_rt,json=importRt,proto3" json:"import_rt,omitempty"` + // List of the Export Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + ExportRt []*anypb.Any `protobuf:"bytes,4,rep,name=export_rt,json=exportRt,proto3" json:"export_rt,omitempty"` + Id uint32 `protobuf:"varint,5,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *Vrf) Reset() { + *x = Vrf{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[141] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Vrf) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Vrf) ProtoMessage() {} + +func (x *Vrf) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[141] + 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 Vrf.ProtoReflect.Descriptor instead. +func (*Vrf) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{141} +} + +func (x *Vrf) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Vrf) GetRd() *anypb.Any { + if x != nil { + return x.Rd + } + return nil +} + +func (x *Vrf) GetImportRt() []*anypb.Any { + if x != nil { + return x.ImportRt + } + return nil +} + +func (x *Vrf) GetExportRt() []*anypb.Any { + if x != nil { + return x.ExportRt + } + return nil +} + +func (x *Vrf) GetId() uint32 { + if x != nil { + return x.Id + } + return 0 +} + +type DefaultRouteDistance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExternalRouteDistance uint32 `protobuf:"varint,1,opt,name=external_route_distance,json=externalRouteDistance,proto3" json:"external_route_distance,omitempty"` + InternalRouteDistance uint32 `protobuf:"varint,2,opt,name=internal_route_distance,json=internalRouteDistance,proto3" json:"internal_route_distance,omitempty"` +} + +func (x *DefaultRouteDistance) Reset() { + *x = DefaultRouteDistance{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[142] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DefaultRouteDistance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DefaultRouteDistance) ProtoMessage() {} + +func (x *DefaultRouteDistance) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[142] + 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 DefaultRouteDistance.ProtoReflect.Descriptor instead. +func (*DefaultRouteDistance) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{142} +} + +func (x *DefaultRouteDistance) GetExternalRouteDistance() uint32 { + if x != nil { + return x.ExternalRouteDistance + } + return 0 +} + +func (x *DefaultRouteDistance) GetInternalRouteDistance() uint32 { + if x != nil { + return x.InternalRouteDistance + } + return 0 +} + +type Global struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asn uint32 `protobuf:"varint,1,opt,name=asn,proto3" json:"asn,omitempty"` + RouterId string `protobuf:"bytes,2,opt,name=router_id,json=routerId,proto3" json:"router_id,omitempty"` + ListenPort int32 `protobuf:"varint,3,opt,name=listen_port,json=listenPort,proto3" json:"listen_port,omitempty"` + ListenAddresses []string `protobuf:"bytes,4,rep,name=listen_addresses,json=listenAddresses,proto3" json:"listen_addresses,omitempty"` + Families []uint32 `protobuf:"varint,5,rep,packed,name=families,proto3" json:"families,omitempty"` + UseMultiplePaths bool `protobuf:"varint,6,opt,name=use_multiple_paths,json=useMultiplePaths,proto3" json:"use_multiple_paths,omitempty"` + RouteSelectionOptions *RouteSelectionOptionsConfig `protobuf:"bytes,7,opt,name=route_selection_options,json=routeSelectionOptions,proto3" json:"route_selection_options,omitempty"` + DefaultRouteDistance *DefaultRouteDistance `protobuf:"bytes,8,opt,name=default_route_distance,json=defaultRouteDistance,proto3" json:"default_route_distance,omitempty"` + Confederation *Confederation `protobuf:"bytes,9,opt,name=confederation,proto3" json:"confederation,omitempty"` + GracefulRestart *GracefulRestart `protobuf:"bytes,10,opt,name=graceful_restart,json=gracefulRestart,proto3" json:"graceful_restart,omitempty"` + ApplyPolicy *ApplyPolicy `protobuf:"bytes,11,opt,name=apply_policy,json=applyPolicy,proto3" json:"apply_policy,omitempty"` + BindToDevice string `protobuf:"bytes,12,opt,name=bind_to_device,json=bindToDevice,proto3" json:"bind_to_device,omitempty"` +} + +func (x *Global) Reset() { + *x = Global{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[143] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Global) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Global) ProtoMessage() {} + +func (x *Global) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[143] + 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 Global.ProtoReflect.Descriptor instead. +func (*Global) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{143} +} + +func (x *Global) GetAsn() uint32 { + if x != nil { + return x.Asn + } + return 0 +} + +func (x *Global) GetRouterId() string { + if x != nil { + return x.RouterId + } + return "" +} + +func (x *Global) GetListenPort() int32 { + if x != nil { + return x.ListenPort + } + return 0 +} + +func (x *Global) GetListenAddresses() []string { + if x != nil { + return x.ListenAddresses + } + return nil +} + +func (x *Global) GetFamilies() []uint32 { + if x != nil { + return x.Families + } + return nil +} + +func (x *Global) GetUseMultiplePaths() bool { + if x != nil { + return x.UseMultiplePaths + } + return false +} + +func (x *Global) GetRouteSelectionOptions() *RouteSelectionOptionsConfig { + if x != nil { + return x.RouteSelectionOptions + } + return nil +} + +func (x *Global) GetDefaultRouteDistance() *DefaultRouteDistance { + if x != nil { + return x.DefaultRouteDistance + } + return nil +} + +func (x *Global) GetConfederation() *Confederation { + if x != nil { + return x.Confederation + } + return nil +} + +func (x *Global) GetGracefulRestart() *GracefulRestart { + if x != nil { + return x.GracefulRestart + } + return nil +} + +func (x *Global) GetApplyPolicy() *ApplyPolicy { + if x != nil { + return x.ApplyPolicy + } + return nil +} + +func (x *Global) GetBindToDevice() string { + if x != nil { + return x.BindToDevice + } + return "" +} + +type Confederation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Identifier uint32 `protobuf:"varint,2,opt,name=identifier,proto3" json:"identifier,omitempty"` + MemberAsList []uint32 `protobuf:"varint,3,rep,packed,name=member_as_list,json=memberAsList,proto3" json:"member_as_list,omitempty"` +} + +func (x *Confederation) Reset() { + *x = Confederation{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[144] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Confederation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Confederation) ProtoMessage() {} + +func (x *Confederation) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[144] + 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 Confederation.ProtoReflect.Descriptor instead. +func (*Confederation) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{144} +} + +func (x *Confederation) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *Confederation) GetIdentifier() uint32 { + if x != nil { + return x.Identifier + } + return 0 +} + +func (x *Confederation) GetMemberAsList() []uint32 { + if x != nil { + return x.MemberAsList + } + return nil +} + +type RPKIConf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + RemotePort uint32 `protobuf:"varint,2,opt,name=remote_port,json=remotePort,proto3" json:"remote_port,omitempty"` +} + +func (x *RPKIConf) Reset() { + *x = RPKIConf{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[145] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPKIConf) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPKIConf) ProtoMessage() {} + +func (x *RPKIConf) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[145] + 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 RPKIConf.ProtoReflect.Descriptor instead. +func (*RPKIConf) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{145} +} + +func (x *RPKIConf) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *RPKIConf) GetRemotePort() uint32 { + if x != nil { + return x.RemotePort + } + return 0 +} + +type RPKIState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uptime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=uptime,proto3" json:"uptime,omitempty"` + Downtime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=downtime,proto3" json:"downtime,omitempty"` + Up bool `protobuf:"varint,3,opt,name=up,proto3" json:"up,omitempty"` + RecordIpv4 uint32 `protobuf:"varint,4,opt,name=record_ipv4,json=recordIpv4,proto3" json:"record_ipv4,omitempty"` + RecordIpv6 uint32 `protobuf:"varint,5,opt,name=record_ipv6,json=recordIpv6,proto3" json:"record_ipv6,omitempty"` + PrefixIpv4 uint32 `protobuf:"varint,6,opt,name=prefix_ipv4,json=prefixIpv4,proto3" json:"prefix_ipv4,omitempty"` + PrefixIpv6 uint32 `protobuf:"varint,7,opt,name=prefix_ipv6,json=prefixIpv6,proto3" json:"prefix_ipv6,omitempty"` + Serial uint32 `protobuf:"varint,8,opt,name=serial,proto3" json:"serial,omitempty"` + ReceivedIpv4 int64 `protobuf:"varint,9,opt,name=received_ipv4,json=receivedIpv4,proto3" json:"received_ipv4,omitempty"` + ReceivedIpv6 int64 `protobuf:"varint,10,opt,name=received_ipv6,json=receivedIpv6,proto3" json:"received_ipv6,omitempty"` + SerialNotify int64 `protobuf:"varint,11,opt,name=serial_notify,json=serialNotify,proto3" json:"serial_notify,omitempty"` + CacheReset int64 `protobuf:"varint,12,opt,name=cache_reset,json=cacheReset,proto3" json:"cache_reset,omitempty"` + CacheResponse int64 `protobuf:"varint,13,opt,name=cache_response,json=cacheResponse,proto3" json:"cache_response,omitempty"` + EndOfData int64 `protobuf:"varint,14,opt,name=end_of_data,json=endOfData,proto3" json:"end_of_data,omitempty"` + Error int64 `protobuf:"varint,15,opt,name=error,proto3" json:"error,omitempty"` + SerialQuery int64 `protobuf:"varint,16,opt,name=serial_query,json=serialQuery,proto3" json:"serial_query,omitempty"` + ResetQuery int64 `protobuf:"varint,17,opt,name=reset_query,json=resetQuery,proto3" json:"reset_query,omitempty"` +} + +func (x *RPKIState) Reset() { + *x = RPKIState{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[146] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPKIState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPKIState) ProtoMessage() {} + +func (x *RPKIState) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[146] + 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 RPKIState.ProtoReflect.Descriptor instead. +func (*RPKIState) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{146} +} + +func (x *RPKIState) GetUptime() *timestamppb.Timestamp { + if x != nil { + return x.Uptime + } + return nil +} + +func (x *RPKIState) GetDowntime() *timestamppb.Timestamp { + if x != nil { + return x.Downtime + } + return nil +} + +func (x *RPKIState) GetUp() bool { + if x != nil { + return x.Up + } + return false +} + +func (x *RPKIState) GetRecordIpv4() uint32 { + if x != nil { + return x.RecordIpv4 + } + return 0 +} + +func (x *RPKIState) GetRecordIpv6() uint32 { + if x != nil { + return x.RecordIpv6 + } + return 0 +} + +func (x *RPKIState) GetPrefixIpv4() uint32 { + if x != nil { + return x.PrefixIpv4 + } + return 0 +} + +func (x *RPKIState) GetPrefixIpv6() uint32 { + if x != nil { + return x.PrefixIpv6 + } + return 0 +} + +func (x *RPKIState) GetSerial() uint32 { + if x != nil { + return x.Serial + } + return 0 +} + +func (x *RPKIState) GetReceivedIpv4() int64 { + if x != nil { + return x.ReceivedIpv4 + } + return 0 +} + +func (x *RPKIState) GetReceivedIpv6() int64 { + if x != nil { + return x.ReceivedIpv6 + } + return 0 +} + +func (x *RPKIState) GetSerialNotify() int64 { + if x != nil { + return x.SerialNotify + } + return 0 +} + +func (x *RPKIState) GetCacheReset() int64 { + if x != nil { + return x.CacheReset + } + return 0 +} + +func (x *RPKIState) GetCacheResponse() int64 { + if x != nil { + return x.CacheResponse + } + return 0 +} + +func (x *RPKIState) GetEndOfData() int64 { + if x != nil { + return x.EndOfData + } + return 0 +} + +func (x *RPKIState) GetError() int64 { + if x != nil { + return x.Error + } + return 0 +} + +func (x *RPKIState) GetSerialQuery() int64 { + if x != nil { + return x.SerialQuery + } + return 0 +} + +func (x *RPKIState) GetResetQuery() int64 { + if x != nil { + return x.ResetQuery + } + return 0 +} + +type Rpki struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Conf *RPKIConf `protobuf:"bytes,1,opt,name=conf,proto3" json:"conf,omitempty"` + State *RPKIState `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *Rpki) Reset() { + *x = Rpki{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[147] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Rpki) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Rpki) ProtoMessage() {} + +func (x *Rpki) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[147] + 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 Rpki.ProtoReflect.Descriptor instead. +func (*Rpki) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{147} +} + +func (x *Rpki) GetConf() *RPKIConf { + if x != nil { + return x.Conf + } + return nil +} + +func (x *Rpki) GetState() *RPKIState { + if x != nil { + return x.State + } + return nil +} + +type SetLogLevelRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Level SetLogLevelRequest_Level `protobuf:"varint,1,opt,name=level,proto3,enum=apipb.SetLogLevelRequest_Level" json:"level,omitempty"` +} + +func (x *SetLogLevelRequest) Reset() { + *x = SetLogLevelRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[148] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetLogLevelRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetLogLevelRequest) ProtoMessage() {} + +func (x *SetLogLevelRequest) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[148] + 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 SetLogLevelRequest.ProtoReflect.Descriptor instead. +func (*SetLogLevelRequest) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{148} +} + +func (x *SetLogLevelRequest) GetLevel() SetLogLevelRequest_Level { + if x != nil { + return x.Level + } + return SetLogLevelRequest_PANIC +} + +type WatchEventRequest_Peer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *WatchEventRequest_Peer) Reset() { + *x = WatchEventRequest_Peer{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[149] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventRequest_Peer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventRequest_Peer) ProtoMessage() {} + +func (x *WatchEventRequest_Peer) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[149] + 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 WatchEventRequest_Peer.ProtoReflect.Descriptor instead. +func (*WatchEventRequest_Peer) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4, 0} +} + +type WatchEventRequest_Table struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filters []*WatchEventRequest_Table_Filter `protobuf:"bytes,1,rep,name=filters,proto3" json:"filters,omitempty"` +} + +func (x *WatchEventRequest_Table) Reset() { + *x = WatchEventRequest_Table{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[150] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventRequest_Table) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventRequest_Table) ProtoMessage() {} + +func (x *WatchEventRequest_Table) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[150] + 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 WatchEventRequest_Table.ProtoReflect.Descriptor instead. +func (*WatchEventRequest_Table) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *WatchEventRequest_Table) GetFilters() []*WatchEventRequest_Table_Filter { + if x != nil { + return x.Filters + } + return nil +} + +type WatchEventRequest_Table_Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type WatchEventRequest_Table_Filter_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.WatchEventRequest_Table_Filter_Type" json:"type,omitempty"` + Init bool `protobuf:"varint,2,opt,name=init,proto3" json:"init,omitempty"` +} + +func (x *WatchEventRequest_Table_Filter) Reset() { + *x = WatchEventRequest_Table_Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[151] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventRequest_Table_Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventRequest_Table_Filter) ProtoMessage() {} + +func (x *WatchEventRequest_Table_Filter) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[151] + 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 WatchEventRequest_Table_Filter.ProtoReflect.Descriptor instead. +func (*WatchEventRequest_Table_Filter) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{4, 1, 0} +} + +func (x *WatchEventRequest_Table_Filter) GetType() WatchEventRequest_Table_Filter_Type { + if x != nil { + return x.Type + } + return WatchEventRequest_Table_Filter_BEST +} + +func (x *WatchEventRequest_Table_Filter) GetInit() bool { + if x != nil { + return x.Init + } + return false +} + +type WatchEventResponse_PeerEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type WatchEventResponse_PeerEvent_Type `protobuf:"varint,1,opt,name=type,proto3,enum=apipb.WatchEventResponse_PeerEvent_Type" json:"type,omitempty"` + Peer *Peer `protobuf:"bytes,2,opt,name=peer,proto3" json:"peer,omitempty"` +} + +func (x *WatchEventResponse_PeerEvent) Reset() { + *x = WatchEventResponse_PeerEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[152] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventResponse_PeerEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventResponse_PeerEvent) ProtoMessage() {} + +func (x *WatchEventResponse_PeerEvent) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[152] + 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 WatchEventResponse_PeerEvent.ProtoReflect.Descriptor instead. +func (*WatchEventResponse_PeerEvent) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *WatchEventResponse_PeerEvent) GetType() WatchEventResponse_PeerEvent_Type { + if x != nil { + return x.Type + } + return WatchEventResponse_PeerEvent_UNKNOWN +} + +func (x *WatchEventResponse_PeerEvent) GetPeer() *Peer { + if x != nil { + return x.Peer + } + return nil +} + +type WatchEventResponse_TableEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Paths []*Path `protobuf:"bytes,2,rep,name=paths,proto3" json:"paths,omitempty"` +} + +func (x *WatchEventResponse_TableEvent) Reset() { + *x = WatchEventResponse_TableEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[153] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WatchEventResponse_TableEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchEventResponse_TableEvent) ProtoMessage() {} + +func (x *WatchEventResponse_TableEvent) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[153] + 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 WatchEventResponse_TableEvent.ProtoReflect.Descriptor instead. +func (*WatchEventResponse_TableEvent) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{5, 1} +} + +func (x *WatchEventResponse_TableEvent) GetPaths() []*Path { + if x != nil { + return x.Paths + } + return nil +} + +type ListBmpResponse_BmpStation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Conf *ListBmpResponse_BmpStation_Conf `protobuf:"bytes,1,opt,name=conf,proto3" json:"conf,omitempty"` + State *ListBmpResponse_BmpStation_State `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` +} + +func (x *ListBmpResponse_BmpStation) Reset() { + *x = ListBmpResponse_BmpStation{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[154] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListBmpResponse_BmpStation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBmpResponse_BmpStation) ProtoMessage() {} + +func (x *ListBmpResponse_BmpStation) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[154] + 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 ListBmpResponse_BmpStation.ProtoReflect.Descriptor instead. +func (*ListBmpResponse_BmpStation) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{72, 0} +} + +func (x *ListBmpResponse_BmpStation) GetConf() *ListBmpResponse_BmpStation_Conf { + if x != nil { + return x.Conf + } + return nil +} + +func (x *ListBmpResponse_BmpStation) GetState() *ListBmpResponse_BmpStation_State { + if x != nil { + return x.State + } + return nil +} + +type ListBmpResponse_BmpStation_Conf struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` +} + +func (x *ListBmpResponse_BmpStation_Conf) Reset() { + *x = ListBmpResponse_BmpStation_Conf{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[155] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListBmpResponse_BmpStation_Conf) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBmpResponse_BmpStation_Conf) ProtoMessage() {} + +func (x *ListBmpResponse_BmpStation_Conf) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[155] + 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 ListBmpResponse_BmpStation_Conf.ProtoReflect.Descriptor instead. +func (*ListBmpResponse_BmpStation_Conf) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{72, 0, 0} +} + +func (x *ListBmpResponse_BmpStation_Conf) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *ListBmpResponse_BmpStation_Conf) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type ListBmpResponse_BmpStation_State struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uptime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=uptime,proto3" json:"uptime,omitempty"` + Downtime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=downtime,proto3" json:"downtime,omitempty"` +} + +func (x *ListBmpResponse_BmpStation_State) Reset() { + *x = ListBmpResponse_BmpStation_State{} + if protoimpl.UnsafeEnabled { + mi := &file_gobgp_proto_msgTypes[156] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListBmpResponse_BmpStation_State) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBmpResponse_BmpStation_State) ProtoMessage() {} + +func (x *ListBmpResponse_BmpStation_State) ProtoReflect() protoreflect.Message { + mi := &file_gobgp_proto_msgTypes[156] + 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 ListBmpResponse_BmpStation_State.ProtoReflect.Descriptor instead. +func (*ListBmpResponse_BmpStation_State) Descriptor() ([]byte, []int) { + return file_gobgp_proto_rawDescGZIP(), []int{72, 0, 1} +} + +func (x *ListBmpResponse_BmpStation_State) GetUptime() *timestamppb.Timestamp { + if x != nil { + return x.Uptime + } + return nil +} + +func (x *ListBmpResponse_BmpStation_State) GetDowntime() *timestamppb.Timestamp { + if x != nil { + return x.Downtime + } + return nil +} + +var File_gobgp_proto protoreflect.FileDescriptor + +var file_gobgp_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x67, 0x6f, 0x62, 0x67, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 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, 0x22, 0x38, 0x0a, + 0x0f, 0x53, 0x74, 0x61, 0x72, 0x74, 0x42, 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x25, 0x0a, 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, + 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x22, 0x10, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x70, 0x42, + 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x47, 0x65, 0x74, + 0x42, 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x37, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x42, 0x67, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x06, 0x67, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x22, 0xdc, 0x02, 0x0a, 0x11, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x70, 0x65, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x05, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x1a, 0xd5, 0x01, 0x0a, 0x05, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x8a, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, + 0x69, 0x6e, 0x69, 0x74, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, + 0x42, 0x45, 0x53, 0x54, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x44, 0x4a, 0x49, 0x4e, 0x10, + 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x4f, 0x53, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, + 0x10, 0x02, 0x22, 0xef, 0x02, 0x0a, 0x12, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x70, 0x65, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x04, + 0x70, 0x65, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x05, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x1a, 0xa5, 0x01, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, + 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, + 0x39, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x01, 0x12, 0x0f, + 0x0a, 0x0b, 0x45, 0x4e, 0x44, 0x5f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x02, 0x12, + 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, 0x54, 0x45, 0x10, 0x03, 0x1a, 0x2f, 0x0a, 0x0a, 0x54, 0x61, + 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x22, 0x31, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x22, 0x4b, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, + 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x22, 0x57, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x2a, 0x0a, 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x64, 0x76, 0x65, 0x72, + 0x74, 0x69, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x41, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x22, 0x33, 0x0a, + 0x10, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, + 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x10, 0x64, 0x6f, 0x5f, 0x73, + 0x6f, 0x66, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x64, 0x6f, 0x53, 0x6f, 0x66, 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x49, + 0x6e, 0x22, 0x43, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, + 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x53, 0x6f, 0x66, 0x74, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x22, 0xe1, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x65, 0x74, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, + 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x6f, 0x66, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x6f, 0x66, 0x74, 0x12, + 0x48, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x6f, 0x66, 0x74, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x12, 0x53, 0x6f, 0x66, + 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x55, 0x54, 0x10, 0x01, + 0x12, 0x08, 0x0a, 0x04, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x02, 0x22, 0x55, 0x0a, 0x13, 0x53, 0x68, + 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 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, 0x12, 0x24, 0x0a, 0x0d, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0x2d, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x54, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, + 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x46, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, + 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, + 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x72, 0x0a, 0x16, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x09, 0x70, 0x65, + 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x27, 0x0a, 0x10, 0x64, 0x6f, 0x5f, 0x73, 0x6f, + 0x66, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0d, 0x64, 0x6f, 0x53, 0x6f, 0x66, 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x49, 0x6e, + 0x22, 0x48, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x13, 0x6e, + 0x65, 0x65, 0x64, 0x73, 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, + 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x53, + 0x6f, 0x66, 0x74, 0x52, 0x65, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x22, 0x3e, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x48, 0x0a, 0x15, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0x5e, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x44, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x41, 0x0a, 0x10, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x5f, 0x6e, 0x65, 0x69, + 0x67, 0x68, 0x62, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, + 0x62, 0x6f, 0x72, 0x52, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, + 0x68, 0x62, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x3b, 0x0a, 0x1a, 0x4c, + 0x69, 0x73, 0x74, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, + 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x60, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, + 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x64, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x5f, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, + 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x0f, 0x64, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x22, 0x79, 0x0a, 0x0e, 0x41, 0x64, + 0x64, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, + 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x72, 0x66, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x25, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0xb7, 0x01, 0x0a, + 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x72, 0x66, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, + 0x79, 0x12, 0x1f, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x22, 0x8a, 0x01, 0x0a, 0x11, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x2e, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x09, 0x0a, 0x05, 0x45, 0x58, 0x41, 0x43, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, + 0x4e, 0x47, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x48, 0x4f, 0x52, 0x54, 0x45, + 0x52, 0x10, 0x02, 0x22, 0xa2, 0x03, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x06, + 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, + 0x69, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, + 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, + 0x08, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x09, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x73, + 0x6f, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, + 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6e, 0x6c, 0x72, 0x69, 0x5f, + 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6c, 0x72, 0x69, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x36, + 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x22, 0x20, 0x0a, 0x08, 0x53, 0x6f, 0x72, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, + 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x10, 0x01, 0x22, 0x48, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0x81, 0x01, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x06, + 0x76, 0x72, 0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x72, + 0x66, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, + 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0x7d, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x09, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x79, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, + 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0e, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6e, 0x75, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, + 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x22, 0x2d, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x56, 0x72, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1c, 0x0a, 0x03, 0x76, 0x72, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x56, 0x72, 0x66, 0x52, 0x03, 0x76, 0x72, 0x66, 0x22, + 0x26, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x56, 0x72, 0x66, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x24, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x72, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2f, 0x0a, + 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x72, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1c, 0x0a, 0x03, 0x76, 0x72, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x56, 0x72, 0x66, 0x52, 0x03, 0x76, 0x72, 0x66, 0x22, 0x75, + 0x0a, 0x10, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x3a, 0x0a, 0x19, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7f, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x12, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x27, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x3b, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xb0, 0x01, 0x0a, + 0x12, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x73, + 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x0b, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0x4a, 0x0a, 0x14, 0x41, 0x64, 0x64, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x65, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, + 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x22, 0x5f, 0x0a, 0x17, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, + 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x0a, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x62, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x4c, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x0b, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, + 0x65, 0x74, 0x52, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x22, 0x45, + 0x0a, 0x13, 0x41, 0x64, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2e, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, + 0x6c, 0x22, 0x2a, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x47, 0x0a, + 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x6a, 0x0a, + 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, + 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x67, 0x0a, 0x1b, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x09, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0x57, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x1a, 0x53, + 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x22, 0x5a, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, + 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x41, + 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, + 0x74, 0x22, 0x38, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, + 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x22, 0x37, 0x0a, 0x10, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x06, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x70, + 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x54, 0x0a, 0x10, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x73, 0x6f, 0x66, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x6f, 0x66, + 0x74, 0x22, 0x3d, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, + 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x22, 0x35, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x03, 0x72, 0x6f, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, + 0x6f, 0x61, 0x52, 0x03, 0x72, 0x6f, 0x61, 0x22, 0xa3, 0x02, 0x0a, 0x12, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x5a, 0x65, 0x62, 0x72, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x6e, + 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x6e, 0x65, 0x78, + 0x74, 0x68, 0x6f, 0x70, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x32, 0x0a, 0x15, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x5f, 0x74, 0x72, 0x69, + 0x67, 0x67, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, + 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x31, 0x0a, 0x15, 0x6d, 0x70, 0x6c, 0x73, 0x5f, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x6d, 0x70, 0x6c, 0x73, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x6f, 0x66, 0x74, + 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xda, 0x01, + 0x0a, 0x10, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, + 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x75, 0x6d, + 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0x22, 0x0a, 0x08, 0x44, 0x75, 0x6d, 0x70, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x53, 0x10, 0x00, 0x12, + 0x09, 0x0a, 0x05, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x22, 0x2f, 0x0a, 0x11, 0x44, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xa5, 0x02, 0x0a, 0x0d, + 0x41, 0x64, 0x64, 0x42, 0x6d, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x42, 0x6d, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2c, 0x0a, 0x11, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, + 0x73, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x79, 0x73, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x79, 0x73, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x79, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x79, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x22, 0x43, + 0x0a, 0x10, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x52, 0x45, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, + 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x02, 0x12, + 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, + 0x4c, 0x10, 0x04, 0x22, 0x40, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6d, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6d, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x83, 0x03, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, + 0x42, 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6d, 0x70, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x07, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xb2, 0x02, 0x0a, 0x0a, 0x42, 0x6d, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x42, 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6d, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x52, 0x04, 0x63, + 0x6f, 0x6e, 0x66, 0x12, 0x3d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x6d, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6d, 0x70, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x43, 0x6f, 0x6e, 0x66, 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, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x73, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x32, 0x0a, 0x06, 0x75, 0x70, 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, 0x06, 0x75, + 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x64, 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 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, 0x64, 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x91, 0x04, + 0x0a, 0x06, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x23, 0x0a, 0x03, 0x61, 0x66, 0x69, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x2e, 0x41, 0x66, 0x69, 0x52, 0x03, 0x61, 0x66, 0x69, 0x12, 0x26, 0x0a, + 0x04, 0x73, 0x61, 0x66, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x2e, 0x53, 0x61, 0x66, 0x69, 0x52, + 0x04, 0x73, 0x61, 0x66, 0x69, 0x22, 0x5e, 0x0a, 0x03, 0x41, 0x66, 0x69, 0x12, 0x0f, 0x0a, 0x0b, + 0x41, 0x46, 0x49, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, + 0x06, 0x41, 0x46, 0x49, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x46, 0x49, + 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x46, 0x49, 0x5f, 0x4c, 0x32, + 0x56, 0x50, 0x4e, 0x10, 0x19, 0x12, 0x0c, 0x0a, 0x06, 0x41, 0x46, 0x49, 0x5f, 0x4c, 0x53, 0x10, + 0x84, 0x80, 0x01, 0x12, 0x10, 0x0a, 0x0a, 0x41, 0x46, 0x49, 0x5f, 0x4f, 0x50, 0x41, 0x51, 0x55, + 0x45, 0x10, 0x8d, 0x80, 0x01, 0x22, 0xd9, 0x02, 0x0a, 0x04, 0x53, 0x61, 0x66, 0x69, 0x12, 0x10, + 0x0a, 0x0c, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x55, 0x4e, 0x49, 0x43, 0x41, 0x53, 0x54, + 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, + 0x43, 0x41, 0x53, 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4d, + 0x50, 0x4c, 0x53, 0x5f, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x53, + 0x41, 0x46, 0x49, 0x5f, 0x45, 0x4e, 0x43, 0x41, 0x50, 0x53, 0x55, 0x4c, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x56, 0x50, 0x4c, 0x53, + 0x10, 0x41, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x45, 0x56, 0x50, 0x4e, 0x10, + 0x46, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4c, 0x53, 0x10, 0x47, 0x12, 0x12, + 0x0a, 0x0e, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x53, 0x52, 0x5f, 0x50, 0x4f, 0x4c, 0x49, 0x43, 0x59, + 0x10, 0x49, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4d, 0x55, 0x50, 0x10, 0x55, + 0x12, 0x12, 0x0a, 0x0d, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4d, 0x50, 0x4c, 0x53, 0x5f, 0x56, 0x50, + 0x4e, 0x10, 0x80, 0x01, 0x12, 0x1c, 0x0a, 0x17, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4d, 0x50, 0x4c, + 0x53, 0x5f, 0x56, 0x50, 0x4e, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x43, 0x41, 0x53, 0x54, 0x10, + 0x81, 0x01, 0x12, 0x22, 0x0a, 0x1d, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, + 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x54, 0x52, 0x41, 0x49, + 0x4e, 0x54, 0x53, 0x10, 0x84, 0x01, 0x12, 0x1b, 0x0a, 0x16, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x46, + 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x50, 0x45, 0x43, 0x5f, 0x55, 0x4e, 0x49, 0x43, 0x41, 0x53, 0x54, + 0x10, 0x85, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x53, 0x41, 0x46, 0x49, 0x5f, 0x46, 0x4c, 0x4f, 0x57, + 0x5f, 0x53, 0x50, 0x45, 0x43, 0x5f, 0x56, 0x50, 0x4e, 0x10, 0x86, 0x01, 0x12, 0x13, 0x0a, 0x0e, + 0x53, 0x41, 0x46, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0xf1, + 0x01, 0x22, 0x8b, 0x03, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x30, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x24, 0x0a, 0x07, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x61, 0x52, 0x07, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x0d, 0x75, 0x6e, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x61, 0x52, 0x0c, 0x75, 0x6e, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x64, 0x41, 0x73, 0x6e, 0x12, 0x35, 0x0a, 0x10, 0x75, 0x6e, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x61, 0x52, 0x0f, + 0x75, 0x6e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, + 0x50, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, + 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x0f, 0x0a, + 0x0b, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x12, 0x11, + 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, + 0x03, 0x22, 0x3c, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x0f, 0x0a, 0x0b, 0x52, + 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x41, 0x53, 0x4e, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x10, 0x02, 0x22, + 0xd9, 0x05, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x28, 0x0a, 0x04, 0x6e, 0x6c, 0x72, 0x69, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x04, 0x6e, 0x6c, + 0x72, 0x69, 0x12, 0x2c, 0x0a, 0x06, 0x70, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x06, 0x70, 0x61, 0x74, 0x74, 0x72, 0x73, + 0x12, 0x2c, 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, 0x03, 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, 0x03, 0x61, 0x67, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x62, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x62, 0x65, + 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x12, 0x31, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x6f, 0x5f, 0x69, 0x6d, 0x70, + 0x6c, 0x69, 0x63, 0x69, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6e, 0x6f, 0x49, 0x6d, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, + 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x73, 0x6e, 0x12, 0x1b, + 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, + 0x10, 0x69, 0x73, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x69, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x45, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x69, 0x67, 0x68, + 0x62, 0x6f, 0x72, 0x5f, 0x69, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, + 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x49, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x2c, 0x0a, 0x12, + 0x69, 0x73, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x73, 0x4e, 0x65, 0x78, 0x74, + 0x68, 0x6f, 0x70, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6c, 0x72, 0x69, 0x5f, 0x62, 0x69, + 0x6e, 0x61, 0x72, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6e, 0x6c, 0x72, 0x69, + 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x74, 0x72, 0x73, + 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x15, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x70, + 0x61, 0x74, 0x74, 0x72, 0x73, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x22, 0x48, 0x0a, 0x0b, 0x44, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x12, 0x21, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, + 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb9, 0x04, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x35, + 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x12, 0x38, 0x0a, 0x0d, 0x65, 0x62, + 0x67, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x62, 0x67, 0x70, 0x4d, 0x75, + 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 0x52, 0x0c, 0x65, 0x62, 0x67, 0x70, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x68, 0x6f, 0x70, 0x12, 0x3e, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, + 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x06, + 0x74, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x52, 0x06, 0x74, 0x69, 0x6d, + 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x6f, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0b, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x10, 0x67, 0x72, + 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x72, 0x61, + 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x0f, 0x67, 0x72, + 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a, + 0x09, 0x61, 0x66, 0x69, 0x5f, 0x73, 0x61, 0x66, 0x69, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, + 0x52, 0x08, 0x61, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, 0x74, + 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x74, 0x6c, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x0b, 0x74, 0x74, 0x6c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x22, 0xc6, 0x04, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, + 0x35, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, + 0x12, 0x38, 0x0a, 0x0d, 0x65, 0x62, 0x67, 0x70, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x68, 0x6f, + 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x45, 0x62, 0x67, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 0x52, 0x0c, 0x65, 0x62, + 0x67, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 0x12, 0x3e, 0x0a, 0x0f, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x04, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x25, 0x0a, 0x06, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x72, 0x73, 0x52, 0x06, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x09, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x0c, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x5f, + 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x0f, 0x67, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2b, 0x0a, 0x09, 0x61, 0x66, 0x69, 0x5f, 0x73, 0x61, + 0x66, 0x69, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x41, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, 0x52, 0x08, 0x61, 0x66, 0x69, 0x53, 0x61, + 0x66, 0x69, 0x73, 0x12, 0x35, 0x0a, 0x0c, 0x74, 0x74, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x54, 0x74, 0x6c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0b, 0x74, + 0x74, 0x6c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x22, 0x48, 0x0a, 0x0f, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x16, 0x0a, + 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x22, 0xbf, 0x01, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x12, 0x34, 0x0a, 0x09, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x08, 0x69, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x3c, 0x0a, 0x0d, 0x65, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x3c, 0x0a, 0x0d, 0x69, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x8d, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x65, 0x66, 0x69, + 0x78, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x46, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x21, 0x0a, + 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, + 0x12, 0x34, 0x0a, 0x16, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x74, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x14, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, + 0x6f, 0x6c, 0x64, 0x50, 0x63, 0x74, 0x22, 0xb8, 0x04, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, + 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6e, 0x65, 0x69, 0x67, 0x68, + 0x62, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, 0x41, 0x73, 0x6e, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x23, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, + 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x2c, + 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x70, 0x5f, 0x64, 0x61, 0x6d, + 0x70, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x46, 0x6c, 0x61, 0x70, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, + 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x74, 0x79, 0x12, 0x2d, 0x0a, 0x12, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x11, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x72, 0x66, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x76, 0x72, 0x66, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6f, 0x77, + 0x6e, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x4f, 0x77, 0x6e, 0x41, 0x73, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x63, 0x65, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x50, 0x65, 0x65, 0x72, 0x41, + 0x73, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x64, 0x6f, 0x77, 0x6e, + 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x44, 0x6f, 0x77, + 0x6e, 0x22, 0xed, 0x02, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, + 0x6f, 0x6e, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, + 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, 0x5f, + 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, 0x41, + 0x73, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x70, 0x5f, 0x64, 0x61, 0x6d, 0x70, 0x69, + 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x46, + 0x6c, 0x61, 0x70, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, + 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x79, 0x22, 0xb6, 0x03, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, + 0x68, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x65, 0x72, + 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x65, 0x72, + 0x41, 0x73, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x65, + 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x0d, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, + 0x12, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x70, 0x5f, 0x64, 0x61, 0x6d, 0x70, + 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x46, 0x6c, 0x61, 0x70, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x73, + 0x65, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x73, 0x22, 0x40, 0x0a, 0x0b, 0x54, 0x74, + 0x6c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 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, 0x17, 0x0a, 0x07, 0x74, 0x74, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x74, 0x74, 0x6c, 0x4d, 0x69, 0x6e, 0x22, 0x4b, 0x0a, 0x0c, + 0x45, 0x62, 0x67, 0x70, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 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, 0x21, 0x0a, 0x0c, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x68, + 0x6f, 0x70, 0x5f, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x68, 0x6f, 0x70, 0x54, 0x74, 0x6c, 0x22, 0x83, 0x01, 0x0a, 0x0e, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x1a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x66, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, + 0xad, 0x07, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x73, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x73, + 0x6e, 0x12, 0x2b, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x73, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x29, + 0x0a, 0x10, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, + 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x65, 0x65, + 0x72, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x70, 0x65, 0x65, + 0x72, 0x41, 0x73, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x12, 0x23, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x54, 0x79, + 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x71, 0x75, 0x65, 0x75, + 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x51, 0x75, 0x65, 0x75, 0x65, 0x73, 0x52, 0x06, 0x71, 0x75, 0x65, 0x75, 0x65, 0x73, 0x12, + 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x70, 0x5f, 0x64, 0x61, 0x6d, 0x70, 0x69, + 0x6e, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x46, + 0x6c, 0x61, 0x70, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, + 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x79, 0x12, 0x42, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x6f, 0x75, 0x74, 0x5f, 0x71, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x04, 0x6f, 0x75, 0x74, 0x51, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x6f, 0x70, + 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x6f, 0x70, 0x73, 0x12, 0x33, + 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x61, 0x70, 0x18, 0x12, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x09, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x43, 0x61, 0x70, 0x12, 0x31, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x70, + 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x43, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x72, 0x49, 0x64, 0x22, 0x6e, 0x0a, 0x0c, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x08, 0x0a, 0x04, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, + 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x45, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4f, 0x50, 0x45, 0x4e, 0x53, 0x45, 0x4e, 0x54, 0x10, + 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x4f, 0x50, 0x45, 0x4e, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, + 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, + 0x44, 0x10, 0x06, 0x22, 0x2a, 0x0a, 0x0a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x06, 0x0a, 0x02, 0x55, 0x50, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x4f, 0x57, + 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x46, 0x58, 0x5f, 0x43, 0x54, 0x10, 0x02, 0x22, + 0x5a, 0x0a, 0x08, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x08, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x22, 0x97, 0x02, 0x0a, 0x07, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, + 0x6c, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, + 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, + 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x09, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x77, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x27, 0x0a, 0x0f, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x36, 0x0a, 0x06, 0x51, 0x75, 0x65, 0x75, 0x65, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x5f, 0x0a, + 0x06, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x81, + 0x02, 0x0a, 0x0c, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x74, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x6f, 0x6c, 0x64, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x6b, + 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x12, 0x44, 0x0a, 0x1e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x61, 0x64, 0x76, 0x65, + 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, + 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, + 0x6d, 0x41, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3a, 0x0a, 0x1a, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x68, + 0x6f, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x72, + 0x65, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x69, 0x64, 0x6c, 0x65, + 0x48, 0x6f, 0x6c, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x65, 0x74, 0x22, 0xe2, 0x02, 0x0a, 0x0b, 0x54, 0x69, 0x6d, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, + 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x74, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, 0x6c, 0x64, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x6f, 0x6c, 0x64, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, + 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x11, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x12, 0x44, 0x0a, 0x1e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x61, + 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1c, 0x6d, 0x69, 0x6e, + 0x69, 0x6d, 0x75, 0x6d, 0x41, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x65, 0x67, + 0x6f, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x6e, 0x65, 0x67, 0x6f, 0x74, 0x69, 0x61, + 0x74, 0x65, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x75, + 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 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, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, + 0x36, 0x0a, 0x08, 0x64, 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 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, 0x64, + 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x9f, 0x02, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x74, 0x75, + 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x6d, 0x74, 0x75, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, 0x21, + 0x0a, 0x0c, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x63, 0x70, + 0x5f, 0x6d, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x74, 0x63, 0x70, 0x4d, + 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x69, 0x6e, 0x64, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x66, 0x0a, 0x0b, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x22, 0xb4, 0x03, 0x0a, 0x0f, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 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, + 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x5f, 0x6f, 0x6e, 0x6c, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x68, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x4f, + 0x6e, 0x6c, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x65, + 0x72, 0x72, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x14, 0x6e, 0x6f, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x6c, + 0x6f, 0x6e, 0x67, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x6f, 0x6e, 0x67, 0x6c, 0x69, 0x76, 0x65, + 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x6c, + 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x6c, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0f, 0x70, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x33, 0x0a, 0x17, 0x4d, 0x70, 0x47, 0x72, + 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 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, 0x22, 0xc4, 0x01, + 0x0a, 0x16, 0x4d, 0x70, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1e, + 0x0a, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x12, 0x2d, + 0x0a, 0x13, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x5f, 0x72, 0x69, 0x62, 0x5f, 0x72, 0x65, 0x63, + 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x6e, 0x64, + 0x4f, 0x66, 0x52, 0x69, 0x62, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x25, 0x0a, + 0x0f, 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x5f, 0x72, 0x69, 0x62, 0x5f, 0x73, 0x65, 0x6e, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x52, 0x69, 0x62, + 0x53, 0x65, 0x6e, 0x74, 0x22, 0x80, 0x01, 0x0a, 0x11, 0x4d, 0x70, 0x47, 0x72, 0x61, 0x63, 0x65, + 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x4d, 0x70, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x33, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x70, 0x47, 0x72, 0x61, 0x63, + 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x50, 0x0a, 0x0d, 0x41, 0x66, 0x69, 0x53, 0x61, + 0x66, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, + 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xa7, 0x01, 0x0a, 0x0c, 0x41, 0x66, + 0x69, 0x53, 0x61, 0x66, 0x69, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x06, 0x66, 0x61, 0x6d, 0x69, 0x6c, + 0x79, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, + 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x61, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, + 0x73, 0x65, 0x64, 0x22, 0x93, 0x03, 0x0a, 0x1b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x5f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x10, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x4d, 0x65, + 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x41, 0x73, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x1a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x3a, 0x0a, 0x19, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x5f, 0x69, + 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x49, + 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x69, 0x67, 0x70, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x69, 0x67, 0x70, 0x12, 0x3a, + 0x0a, 0x1a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x68, 0x6f, + 0x70, 0x5f, 0x69, 0x67, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x16, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4e, 0x65, 0x78, 0x74, 0x48, 0x6f, + 0x70, 0x49, 0x67, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x3d, 0x0a, 0x1b, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x18, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x92, 0x03, 0x0a, 0x1a, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x77, 0x61, + 0x79, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x43, 0x6f, 0x6d, 0x70, + 0x61, 0x72, 0x65, 0x4d, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x5f, 0x61, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x41, 0x73, 0x50, + 0x61, 0x74, 0x68, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x1a, 0x65, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x19, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, + 0x69, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x64, 0x76, 0x65, 0x72, + 0x74, 0x69, 0x73, 0x65, 0x49, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x69, 0x67, + 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, + 0x69, 0x67, 0x70, 0x12, 0x3a, 0x0a, 0x1a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x67, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4e, + 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x49, 0x67, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, + 0x3d, 0x0a, 0x1b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x65, 0x73, + 0x74, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8c, + 0x01, 0x0a, 0x15, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x32, 0x0a, + 0x16, 0x55, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x22, 0x31, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x22, 0x5f, 0x0a, 0x0a, 0x45, 0x62, 0x67, 0x70, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x41, 0x73, 0x6e, + 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0x5e, 0x0a, 0x09, 0x45, 0x62, 0x67, 0x70, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x41, 0x73, 0x6e, + 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0x59, 0x0a, 0x04, 0x45, 0x62, 0x67, 0x70, 0x12, 0x29, 0x0a, + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x62, 0x67, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x45, 0x62, 0x67, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x31, 0x0a, 0x0a, 0x49, 0x62, 0x67, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, + 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x22, 0x30, 0x0a, 0x09, 0x49, 0x62, 0x67, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0x59, 0x0a, 0x04, 0x49, 0x62, 0x67, 0x70, 0x12, 0x29, 0x0a, + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x49, 0x62, 0x67, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x49, 0x62, 0x67, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x22, 0xbf, 0x01, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x55, 0x73, + 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x1f, 0x0a, 0x04, 0x65, 0x62, 0x67, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x62, 0x67, 0x70, 0x52, 0x04, 0x65, 0x62, 0x67, + 0x70, 0x12, 0x1f, 0x0a, 0x04, 0x69, 0x62, 0x67, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x49, 0x62, 0x67, 0x70, 0x52, 0x04, 0x69, 0x62, + 0x67, 0x70, 0x22, 0x42, 0x0a, 0x1b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, + 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x41, 0x0a, 0x1a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x64, 0x65, 0x66, + 0x65, 0x72, 0x72, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x15, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x37, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x5d, 0x0a, 0x1e, 0x4c, 0x6f, 0x6e, 0x67, + 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xde, 0x01, 0x0a, 0x1d, 0x4c, 0x6f, 0x6e, 0x67, + 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, + 0x1e, 0x0a, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x64, 0x12, + 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x65, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x1a, 0x70, + 0x65, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x72, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x17, 0x70, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x72, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x22, 0x95, 0x01, 0x0a, 0x18, 0x4c, 0x6f, 0x6e, + 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x6f, + 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x6e, 0x67, + 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x9d, 0x05, 0x0a, 0x07, 0x41, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, 0x12, 0x48, 0x0a, 0x13, + 0x6d, 0x70, 0x5f, 0x67, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4d, 0x70, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x52, 0x11, 0x6d, 0x70, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, + 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x66, 0x69, 0x53, + 0x61, 0x66, 0x69, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x35, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x54, 0x0a, 0x17, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x15, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x0a, 0x12, + 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, + 0x68, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x55, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x52, 0x10, 0x75, 0x73, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x12, 0x37, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x52, 0x0c, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x17, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x15, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x12, 0x5e, 0x0a, 0x1b, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x64, + 0x5f, 0x67, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x4c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, + 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x18, 0x6c, 0x6f, 0x6e, 0x67, 0x4c, 0x69, + 0x76, 0x65, 0x64, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, + 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x08, 0x61, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, + 0x22, 0x45, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, + 0x73, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x44, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x73, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x65, 0x0a, + 0x08, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x73, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x22, 0x75, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1b, + 0x0a, 0x09, 0x69, 0x70, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x69, 0x70, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x6d, + 0x61, 0x73, 0x6b, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x61, 0x73, 0x6b, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x73, 0x6b, 0x5f, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x61, + 0x73, 0x6b, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x22, 0x96, 0x01, 0x0a, 0x0a, + 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x64, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x08, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x65, 0x73, 0x22, 0x6e, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, + 0x12, 0x28, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x2e, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x24, + 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, + 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4e, 0x56, 0x45, + 0x52, 0x54, 0x10, 0x02, 0x22, 0x74, 0x0a, 0x0c, 0x41, 0x73, 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x73, 0x50, 0x61, 0x74, + 0x68, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x1e, 0x0a, 0x04, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x06, 0x0a, 0x02, 0x45, 0x51, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x47, 0x45, + 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x4c, 0x45, 0x10, 0x02, 0x22, 0xaf, 0x05, 0x0a, 0x0a, 0x43, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x0a, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x52, 0x09, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x53, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x0c, 0x6e, 0x65, 0x69, + 0x67, 0x68, 0x62, 0x6f, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, + 0x52, 0x0b, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x12, 0x39, 0x0a, + 0x0e, 0x61, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x73, + 0x50, 0x61, 0x74, 0x68, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, 0x0c, 0x61, 0x73, 0x50, 0x61, + 0x74, 0x68, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x2f, 0x0a, 0x0b, 0x61, 0x73, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x52, 0x09, + 0x61, 0x73, 0x50, 0x61, 0x74, 0x68, 0x53, 0x65, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, + 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, + 0x74, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x65, 0x74, 0x12, + 0x3b, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x5f, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x52, 0x0f, 0x65, 0x78, 0x74, + 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x72, 0x70, 0x6b, 0x69, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0a, 0x72, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3a, 0x0a, + 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3f, 0x0a, 0x13, 0x6c, 0x61, 0x72, + 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x74, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, + 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x52, 0x11, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, + 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x10, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x48, 0x6f, 0x70, 0x49, 0x6e, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0b, 0x61, 0x66, 0x69, 0x5f, 0x73, 0x61, 0x66, 0x69, 0x5f, + 0x69, 0x6e, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x09, 0x61, 0x66, 0x69, 0x53, 0x61, 0x66, 0x69, + 0x49, 0x6e, 0x22, 0x68, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x13, 0x0a, 0x0f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, + 0x4e, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x17, 0x0a, + 0x13, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, + 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x22, 0x8e, 0x01, 0x0a, + 0x0f, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x22, 0x28, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, + 0x44, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x10, 0x01, + 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0x6a, 0x0a, + 0x09, 0x4d, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x4d, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1c, 0x0a, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4d, 0x4f, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x01, 0x22, 0x5f, 0x0a, 0x0f, 0x41, 0x73, 0x50, + 0x72, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, + 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, + 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x5f, 0x6c, 0x65, + 0x66, 0x74, 0x5f, 0x6d, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x75, + 0x73, 0x65, 0x4c, 0x65, 0x66, 0x74, 0x4d, 0x6f, 0x73, 0x74, 0x22, 0x5b, 0x0a, 0x0d, 0x4e, 0x65, + 0x78, 0x74, 0x68, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6c, 0x66, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x65, 0x6c, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x6e, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x75, 0x6e, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x27, 0x0a, 0x0f, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x50, 0x72, 0x65, 0x66, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x22, 0xb6, 0x03, 0x0a, 0x07, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x0c, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x12, 0x22, 0x0a, 0x03, 0x6d, 0x65, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4d, + 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x6d, 0x65, 0x64, 0x12, 0x35, 0x0a, + 0x0a, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x73, 0x50, 0x72, 0x65, 0x70, + 0x65, 0x6e, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x61, 0x73, 0x50, 0x72, 0x65, + 0x70, 0x65, 0x6e, 0x64, 0x12, 0x3b, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x78, 0x74, 0x68, + 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, + 0x70, 0x12, 0x35, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6c, + 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x72, 0x65, 0x66, 0x12, 0x3f, 0x0a, 0x0f, 0x6c, 0x61, 0x72, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x74, 0x79, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6c, 0x61, 0x72, 0x67, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x22, 0x7c, 0x0a, 0x09, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x0a, 0x63, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x0a, + 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4e, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xc2, 0x01, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x34, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x12, 0x39, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x70, 0x0a, 0x0d, + 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x34, 0x0a, + 0x0c, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, + 0x65, 0x74, 0x73, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x8a, + 0x01, 0x0a, 0x03, 0x52, 0x6f, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x6c, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x6c, 0x65, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x6c, 0x65, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x6c, 0x65, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x4b, + 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x52, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x22, 0xb5, 0x01, 0x0a, 0x03, + 0x56, 0x72, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x72, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x72, 0x64, 0x12, 0x31, 0x0a, + 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x74, + 0x12, 0x31, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x74, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x65, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x86, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x17, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x64, + 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xd8, 0x04, 0x0a, + 0x06, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x73, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x61, 0x73, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0f, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x2c, + 0x0a, 0x12, 0x75, 0x73, 0x65, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x75, 0x73, 0x65, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x5a, 0x0a, 0x17, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x15, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x51, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x14, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x63, + 0x6f, 0x6e, 0x66, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x64, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x10, 0x67, 0x72, 0x61, 0x63, 0x65, + 0x66, 0x75, 0x6c, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x72, 0x61, 0x63, 0x65, 0x66, + 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x0f, 0x67, 0x72, 0x61, 0x63, 0x65, + 0x66, 0x75, 0x6c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x61, 0x70, + 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x54, + 0x6f, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x6f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x65, + 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x61, 0x73, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x41, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x45, 0x0a, 0x08, 0x52, 0x50, 0x4b, 0x49, + 0x43, 0x6f, 0x6e, 0x66, 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, 0x12, 0x1f, + 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x22, + 0xd4, 0x04, 0x0a, 0x09, 0x52, 0x50, 0x4b, 0x49, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, + 0x06, 0x75, 0x70, 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, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, + 0x65, 0x12, 0x36, 0x0a, 0x08, 0x64, 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, 0x65, 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, 0x64, 0x6f, 0x77, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x75, 0x70, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x75, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x63, + 0x6f, 0x72, 0x64, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, + 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x70, 0x76, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x70, 0x76, 0x36, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x49, 0x70, 0x76, 0x34, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x49, 0x70, 0x76, 0x36, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x49, 0x70, 0x76, 0x34, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x49, 0x70, 0x76, 0x36, 0x12, + 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x72, 0x65, + 0x73, 0x65, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0b, + 0x65, 0x6e, 0x64, 0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x4f, 0x66, 0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x65, + 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x22, 0x53, 0x0a, 0x04, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x23, + 0x0a, 0x04, 0x63, 0x6f, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x4b, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x52, 0x04, 0x63, + 0x6f, 0x6e, 0x66, 0x12, 0x26, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x50, 0x4b, 0x49, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x12, + 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x35, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x52, 0x0a, 0x05, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x09, 0x0a, + 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x08, 0x0a, + 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, + 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x06, 0x2a, 0x44, 0x0a, + 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, + 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, + 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x44, 0x4a, 0x5f, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x0b, 0x0a, + 0x07, 0x41, 0x44, 0x4a, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x56, 0x52, + 0x46, 0x10, 0x04, 0x2a, 0x26, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0c, 0x0a, + 0x08, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x2a, 0x3d, 0x0a, 0x0d, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, + 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, + 0x0a, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, + 0x07, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x2a, 0x82, 0x01, 0x0a, 0x0b, 0x44, + 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x52, + 0x45, 0x46, 0x49, 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x45, 0x49, 0x47, 0x48, 0x42, + 0x4f, 0x52, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x41, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, + 0x07, 0x41, 0x53, 0x5f, 0x50, 0x41, 0x54, 0x48, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, + 0x4d, 0x4d, 0x55, 0x4e, 0x49, 0x54, 0x59, 0x10, 0x04, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x58, 0x54, + 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x55, 0x4e, 0x49, 0x54, 0x59, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, + 0x4c, 0x41, 0x52, 0x47, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x55, 0x4e, 0x49, 0x54, 0x59, 0x10, + 0x06, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x45, 0x58, 0x54, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x07, 0x2a, + 0x2f, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, + 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, + 0x50, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x02, + 0x2a, 0x36, 0x0a, 0x0f, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, + 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x02, 0x32, 0xc2, 0x1d, 0x0a, 0x08, 0x47, 0x6f, 0x62, + 0x67, 0x70, 0x41, 0x70, 0x69, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x74, 0x61, 0x72, 0x74, 0x42, 0x67, + 0x70, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x42, + 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x38, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x70, 0x42, 0x67, 0x70, 0x12, 0x15, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x42, 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x06, 0x47, + 0x65, 0x74, 0x42, 0x67, 0x70, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x65, + 0x74, 0x42, 0x67, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x67, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x43, 0x0a, 0x0a, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x50, 0x65, + 0x65, 0x72, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3e, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x12, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3d, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x16, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, + 0x12, 0x41, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x12, 0x18, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, + 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x50, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x50, 0x65, 0x65, + 0x72, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, + 0x77, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0a, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, + 0x65, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x0b, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x50, 0x65, + 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x41, 0x64, 0x64, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1d, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, + 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x44, 0x79, 0x6e, 0x61, + 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x20, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, + 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5e, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x79, 0x6e, + 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x21, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x79, 0x6e, 0x61, + 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, + 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x12, 0x23, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x79, 0x6e, + 0x61, 0x6d, 0x69, 0x63, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x38, 0x0a, 0x07, 0x41, + 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, + 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, + 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x50, 0x61, 0x74, 0x68, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, + 0x64, 0x50, 0x61, 0x74, 0x68, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x3b, 0x0a, 0x08, + 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x41, 0x64, 0x64, + 0x56, 0x72, 0x66, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x56, + 0x72, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x56, 0x72, 0x66, 0x12, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x56, 0x72, 0x66, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x3a, 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x72, 0x66, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x72, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x72, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x09, 0x41, + 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, + 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x18, 0x2e, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x30, 0x01, 0x12, 0x40, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x44, 0x65, 0x66, 0x69, 0x6e, + 0x65, 0x64, 0x53, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, + 0x64, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4a, 0x0a, 0x10, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x12, 0x1e, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x66, + 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4f, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, + 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x41, 0x64, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1d, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x56, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x24, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x61, 0x0a, + 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, + 0x12, 0x50, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x53, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x38, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x15, 0x2e, + 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0a, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x08, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, + 0x69, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0a, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x0b, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3c, 0x0a, + 0x09, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x0d, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1b, 0x2e, 0x61, + 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x70, + 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x70, 0x6b, 0x69, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x40, 0x0a, 0x0b, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x5a, 0x65, 0x62, 0x72, 0x61, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5a, 0x65, 0x62, 0x72, 0x61, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, + 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0a, 0x44, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, + 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x06, 0x41, 0x64, 0x64, + 0x42, 0x6d, 0x70, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x42, + 0x6d, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3c, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6d, 0x70, 0x12, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6d, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x3a, 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6d, 0x70, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6d, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6d, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x40, 0x0a, 0x0b, 0x53, + 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x24, 0x5a, + 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x73, 0x72, 0x67, + 0x2f, 0x67, 0x6f, 0x62, 0x67, 0x70, 0x2f, 0x76, 0x33, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, + 0x69, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_gobgp_proto_rawDescOnce sync.Once + file_gobgp_proto_rawDescData = file_gobgp_proto_rawDesc +) + +func file_gobgp_proto_rawDescGZIP() []byte { + file_gobgp_proto_rawDescOnce.Do(func() { + file_gobgp_proto_rawDescData = protoimpl.X.CompressGZIP(file_gobgp_proto_rawDescData) + }) + return file_gobgp_proto_rawDescData +} + +var file_gobgp_proto_enumTypes = make([]protoimpl.EnumInfo, 25) +var file_gobgp_proto_msgTypes = make([]protoimpl.MessageInfo, 157) +var file_gobgp_proto_goTypes = []interface{}{ + (TableType)(0), // 0: apipb.TableType + (PeerType)(0), // 1: apipb.PeerType + (RemovePrivate)(0), // 2: apipb.RemovePrivate + (DefinedType)(0), // 3: apipb.DefinedType + (RouteAction)(0), // 4: apipb.RouteAction + (PolicyDirection)(0), // 5: apipb.PolicyDirection + (WatchEventRequest_Table_Filter_Type)(0), // 6: apipb.WatchEventRequest.Table.Filter.Type + (WatchEventResponse_PeerEvent_Type)(0), // 7: apipb.WatchEventResponse.PeerEvent.Type + (ResetPeerRequest_SoftResetDirection)(0), // 8: apipb.ResetPeerRequest.SoftResetDirection + (TableLookupPrefix_Type)(0), // 9: apipb.TableLookupPrefix.Type + (ListPathRequest_SortType)(0), // 10: apipb.ListPathRequest.SortType + (EnableMrtRequest_DumpType)(0), // 11: apipb.EnableMrtRequest.DumpType + (AddBmpRequest_MonitoringPolicy)(0), // 12: apipb.AddBmpRequest.MonitoringPolicy + (Family_Afi)(0), // 13: apipb.Family.Afi + (Family_Safi)(0), // 14: apipb.Family.Safi + (Validation_State)(0), // 15: apipb.Validation.State + (Validation_Reason)(0), // 16: apipb.Validation.Reason + (PeerState_SessionState)(0), // 17: apipb.PeerState.SessionState + (PeerState_AdminState)(0), // 18: apipb.PeerState.AdminState + (MatchSet_Type)(0), // 19: apipb.MatchSet.Type + (AsPathLength_Type)(0), // 20: apipb.AsPathLength.Type + (Conditions_RouteType)(0), // 21: apipb.Conditions.RouteType + (CommunityAction_Type)(0), // 22: apipb.CommunityAction.Type + (MedAction_Type)(0), // 23: apipb.MedAction.Type + (SetLogLevelRequest_Level)(0), // 24: apipb.SetLogLevelRequest.Level + (*StartBgpRequest)(nil), // 25: apipb.StartBgpRequest + (*StopBgpRequest)(nil), // 26: apipb.StopBgpRequest + (*GetBgpRequest)(nil), // 27: apipb.GetBgpRequest + (*GetBgpResponse)(nil), // 28: apipb.GetBgpResponse + (*WatchEventRequest)(nil), // 29: apipb.WatchEventRequest + (*WatchEventResponse)(nil), // 30: apipb.WatchEventResponse + (*AddPeerRequest)(nil), // 31: apipb.AddPeerRequest + (*DeletePeerRequest)(nil), // 32: apipb.DeletePeerRequest + (*ListPeerRequest)(nil), // 33: apipb.ListPeerRequest + (*ListPeerResponse)(nil), // 34: apipb.ListPeerResponse + (*UpdatePeerRequest)(nil), // 35: apipb.UpdatePeerRequest + (*UpdatePeerResponse)(nil), // 36: apipb.UpdatePeerResponse + (*ResetPeerRequest)(nil), // 37: apipb.ResetPeerRequest + (*ShutdownPeerRequest)(nil), // 38: apipb.ShutdownPeerRequest + (*EnablePeerRequest)(nil), // 39: apipb.EnablePeerRequest + (*DisablePeerRequest)(nil), // 40: apipb.DisablePeerRequest + (*AddPeerGroupRequest)(nil), // 41: apipb.AddPeerGroupRequest + (*DeletePeerGroupRequest)(nil), // 42: apipb.DeletePeerGroupRequest + (*UpdatePeerGroupRequest)(nil), // 43: apipb.UpdatePeerGroupRequest + (*UpdatePeerGroupResponse)(nil), // 44: apipb.UpdatePeerGroupResponse + (*ListPeerGroupRequest)(nil), // 45: apipb.ListPeerGroupRequest + (*ListPeerGroupResponse)(nil), // 46: apipb.ListPeerGroupResponse + (*AddDynamicNeighborRequest)(nil), // 47: apipb.AddDynamicNeighborRequest + (*DeleteDynamicNeighborRequest)(nil), // 48: apipb.DeleteDynamicNeighborRequest + (*ListDynamicNeighborRequest)(nil), // 49: apipb.ListDynamicNeighborRequest + (*ListDynamicNeighborResponse)(nil), // 50: apipb.ListDynamicNeighborResponse + (*AddPathRequest)(nil), // 51: apipb.AddPathRequest + (*AddPathResponse)(nil), // 52: apipb.AddPathResponse + (*DeletePathRequest)(nil), // 53: apipb.DeletePathRequest + (*TableLookupPrefix)(nil), // 54: apipb.TableLookupPrefix + (*ListPathRequest)(nil), // 55: apipb.ListPathRequest + (*ListPathResponse)(nil), // 56: apipb.ListPathResponse + (*AddPathStreamRequest)(nil), // 57: apipb.AddPathStreamRequest + (*GetTableRequest)(nil), // 58: apipb.GetTableRequest + (*GetTableResponse)(nil), // 59: apipb.GetTableResponse + (*AddVrfRequest)(nil), // 60: apipb.AddVrfRequest + (*DeleteVrfRequest)(nil), // 61: apipb.DeleteVrfRequest + (*ListVrfRequest)(nil), // 62: apipb.ListVrfRequest + (*ListVrfResponse)(nil), // 63: apipb.ListVrfResponse + (*AddPolicyRequest)(nil), // 64: apipb.AddPolicyRequest + (*DeletePolicyRequest)(nil), // 65: apipb.DeletePolicyRequest + (*ListPolicyRequest)(nil), // 66: apipb.ListPolicyRequest + (*ListPolicyResponse)(nil), // 67: apipb.ListPolicyResponse + (*SetPoliciesRequest)(nil), // 68: apipb.SetPoliciesRequest + (*AddDefinedSetRequest)(nil), // 69: apipb.AddDefinedSetRequest + (*DeleteDefinedSetRequest)(nil), // 70: apipb.DeleteDefinedSetRequest + (*ListDefinedSetRequest)(nil), // 71: apipb.ListDefinedSetRequest + (*ListDefinedSetResponse)(nil), // 72: apipb.ListDefinedSetResponse + (*AddStatementRequest)(nil), // 73: apipb.AddStatementRequest + (*DeleteStatementRequest)(nil), // 74: apipb.DeleteStatementRequest + (*ListStatementRequest)(nil), // 75: apipb.ListStatementRequest + (*ListStatementResponse)(nil), // 76: apipb.ListStatementResponse + (*AddPolicyAssignmentRequest)(nil), // 77: apipb.AddPolicyAssignmentRequest + (*DeletePolicyAssignmentRequest)(nil), // 78: apipb.DeletePolicyAssignmentRequest + (*ListPolicyAssignmentRequest)(nil), // 79: apipb.ListPolicyAssignmentRequest + (*ListPolicyAssignmentResponse)(nil), // 80: apipb.ListPolicyAssignmentResponse + (*SetPolicyAssignmentRequest)(nil), // 81: apipb.SetPolicyAssignmentRequest + (*AddRpkiRequest)(nil), // 82: apipb.AddRpkiRequest + (*DeleteRpkiRequest)(nil), // 83: apipb.DeleteRpkiRequest + (*ListRpkiRequest)(nil), // 84: apipb.ListRpkiRequest + (*ListRpkiResponse)(nil), // 85: apipb.ListRpkiResponse + (*EnableRpkiRequest)(nil), // 86: apipb.EnableRpkiRequest + (*DisableRpkiRequest)(nil), // 87: apipb.DisableRpkiRequest + (*ResetRpkiRequest)(nil), // 88: apipb.ResetRpkiRequest + (*ListRpkiTableRequest)(nil), // 89: apipb.ListRpkiTableRequest + (*ListRpkiTableResponse)(nil), // 90: apipb.ListRpkiTableResponse + (*EnableZebraRequest)(nil), // 91: apipb.EnableZebraRequest + (*EnableMrtRequest)(nil), // 92: apipb.EnableMrtRequest + (*DisableMrtRequest)(nil), // 93: apipb.DisableMrtRequest + (*AddBmpRequest)(nil), // 94: apipb.AddBmpRequest + (*DeleteBmpRequest)(nil), // 95: apipb.DeleteBmpRequest + (*ListBmpRequest)(nil), // 96: apipb.ListBmpRequest + (*ListBmpResponse)(nil), // 97: apipb.ListBmpResponse + (*Family)(nil), // 98: apipb.Family + (*Validation)(nil), // 99: apipb.Validation + (*Path)(nil), // 100: apipb.Path + (*Destination)(nil), // 101: apipb.Destination + (*Peer)(nil), // 102: apipb.Peer + (*PeerGroup)(nil), // 103: apipb.PeerGroup + (*DynamicNeighbor)(nil), // 104: apipb.DynamicNeighbor + (*ApplyPolicy)(nil), // 105: apipb.ApplyPolicy + (*PrefixLimit)(nil), // 106: apipb.PrefixLimit + (*PeerConf)(nil), // 107: apipb.PeerConf + (*PeerGroupConf)(nil), // 108: apipb.PeerGroupConf + (*PeerGroupState)(nil), // 109: apipb.PeerGroupState + (*TtlSecurity)(nil), // 110: apipb.TtlSecurity + (*EbgpMultihop)(nil), // 111: apipb.EbgpMultihop + (*RouteReflector)(nil), // 112: apipb.RouteReflector + (*PeerState)(nil), // 113: apipb.PeerState + (*Messages)(nil), // 114: apipb.Messages + (*Message)(nil), // 115: apipb.Message + (*Queues)(nil), // 116: apipb.Queues + (*Timers)(nil), // 117: apipb.Timers + (*TimersConfig)(nil), // 118: apipb.TimersConfig + (*TimersState)(nil), // 119: apipb.TimersState + (*Transport)(nil), // 120: apipb.Transport + (*RouteServer)(nil), // 121: apipb.RouteServer + (*GracefulRestart)(nil), // 122: apipb.GracefulRestart + (*MpGracefulRestartConfig)(nil), // 123: apipb.MpGracefulRestartConfig + (*MpGracefulRestartState)(nil), // 124: apipb.MpGracefulRestartState + (*MpGracefulRestart)(nil), // 125: apipb.MpGracefulRestart + (*AfiSafiConfig)(nil), // 126: apipb.AfiSafiConfig + (*AfiSafiState)(nil), // 127: apipb.AfiSafiState + (*RouteSelectionOptionsConfig)(nil), // 128: apipb.RouteSelectionOptionsConfig + (*RouteSelectionOptionsState)(nil), // 129: apipb.RouteSelectionOptionsState + (*RouteSelectionOptions)(nil), // 130: apipb.RouteSelectionOptions + (*UseMultiplePathsConfig)(nil), // 131: apipb.UseMultiplePathsConfig + (*UseMultiplePathsState)(nil), // 132: apipb.UseMultiplePathsState + (*EbgpConfig)(nil), // 133: apipb.EbgpConfig + (*EbgpState)(nil), // 134: apipb.EbgpState + (*Ebgp)(nil), // 135: apipb.Ebgp + (*IbgpConfig)(nil), // 136: apipb.IbgpConfig + (*IbgpState)(nil), // 137: apipb.IbgpState + (*Ibgp)(nil), // 138: apipb.Ibgp + (*UseMultiplePaths)(nil), // 139: apipb.UseMultiplePaths + (*RouteTargetMembershipConfig)(nil), // 140: apipb.RouteTargetMembershipConfig + (*RouteTargetMembershipState)(nil), // 141: apipb.RouteTargetMembershipState + (*RouteTargetMembership)(nil), // 142: apipb.RouteTargetMembership + (*LongLivedGracefulRestartConfig)(nil), // 143: apipb.LongLivedGracefulRestartConfig + (*LongLivedGracefulRestartState)(nil), // 144: apipb.LongLivedGracefulRestartState + (*LongLivedGracefulRestart)(nil), // 145: apipb.LongLivedGracefulRestart + (*AfiSafi)(nil), // 146: apipb.AfiSafi + (*AddPathsConfig)(nil), // 147: apipb.AddPathsConfig + (*AddPathsState)(nil), // 148: apipb.AddPathsState + (*AddPaths)(nil), // 149: apipb.AddPaths + (*Prefix)(nil), // 150: apipb.Prefix + (*DefinedSet)(nil), // 151: apipb.DefinedSet + (*MatchSet)(nil), // 152: apipb.MatchSet + (*AsPathLength)(nil), // 153: apipb.AsPathLength + (*Conditions)(nil), // 154: apipb.Conditions + (*CommunityAction)(nil), // 155: apipb.CommunityAction + (*MedAction)(nil), // 156: apipb.MedAction + (*AsPrependAction)(nil), // 157: apipb.AsPrependAction + (*NexthopAction)(nil), // 158: apipb.NexthopAction + (*LocalPrefAction)(nil), // 159: apipb.LocalPrefAction + (*Actions)(nil), // 160: apipb.Actions + (*Statement)(nil), // 161: apipb.Statement + (*Policy)(nil), // 162: apipb.Policy + (*PolicyAssignment)(nil), // 163: apipb.PolicyAssignment + (*RoutingPolicy)(nil), // 164: apipb.RoutingPolicy + (*Roa)(nil), // 165: apipb.Roa + (*Vrf)(nil), // 166: apipb.Vrf + (*DefaultRouteDistance)(nil), // 167: apipb.DefaultRouteDistance + (*Global)(nil), // 168: apipb.Global + (*Confederation)(nil), // 169: apipb.Confederation + (*RPKIConf)(nil), // 170: apipb.RPKIConf + (*RPKIState)(nil), // 171: apipb.RPKIState + (*Rpki)(nil), // 172: apipb.Rpki + (*SetLogLevelRequest)(nil), // 173: apipb.SetLogLevelRequest + (*WatchEventRequest_Peer)(nil), // 174: apipb.WatchEventRequest.Peer + (*WatchEventRequest_Table)(nil), // 175: apipb.WatchEventRequest.Table + (*WatchEventRequest_Table_Filter)(nil), // 176: apipb.WatchEventRequest.Table.Filter + (*WatchEventResponse_PeerEvent)(nil), // 177: apipb.WatchEventResponse.PeerEvent + (*WatchEventResponse_TableEvent)(nil), // 178: apipb.WatchEventResponse.TableEvent + (*ListBmpResponse_BmpStation)(nil), // 179: apipb.ListBmpResponse.BmpStation + (*ListBmpResponse_BmpStation_Conf)(nil), // 180: apipb.ListBmpResponse.BmpStation.Conf + (*ListBmpResponse_BmpStation_State)(nil), // 181: apipb.ListBmpResponse.BmpStation.State + (*anypb.Any)(nil), // 182: google.protobuf.Any + (*timestamppb.Timestamp)(nil), // 183: google.protobuf.Timestamp + (*emptypb.Empty)(nil), // 184: google.protobuf.Empty +} +var file_gobgp_proto_depIdxs = []int32{ + 168, // 0: apipb.StartBgpRequest.global:type_name -> apipb.Global + 168, // 1: apipb.GetBgpResponse.global:type_name -> apipb.Global + 174, // 2: apipb.WatchEventRequest.peer:type_name -> apipb.WatchEventRequest.Peer + 175, // 3: apipb.WatchEventRequest.table:type_name -> apipb.WatchEventRequest.Table + 177, // 4: apipb.WatchEventResponse.peer:type_name -> apipb.WatchEventResponse.PeerEvent + 178, // 5: apipb.WatchEventResponse.table:type_name -> apipb.WatchEventResponse.TableEvent + 102, // 6: apipb.AddPeerRequest.peer:type_name -> apipb.Peer + 102, // 7: apipb.ListPeerResponse.peer:type_name -> apipb.Peer + 102, // 8: apipb.UpdatePeerRequest.peer:type_name -> apipb.Peer + 8, // 9: apipb.ResetPeerRequest.direction:type_name -> apipb.ResetPeerRequest.SoftResetDirection + 103, // 10: apipb.AddPeerGroupRequest.peer_group:type_name -> apipb.PeerGroup + 103, // 11: apipb.UpdatePeerGroupRequest.peer_group:type_name -> apipb.PeerGroup + 103, // 12: apipb.ListPeerGroupResponse.peer_group:type_name -> apipb.PeerGroup + 104, // 13: apipb.AddDynamicNeighborRequest.dynamic_neighbor:type_name -> apipb.DynamicNeighbor + 104, // 14: apipb.ListDynamicNeighborResponse.dynamic_neighbor:type_name -> apipb.DynamicNeighbor + 0, // 15: apipb.AddPathRequest.table_type:type_name -> apipb.TableType + 100, // 16: apipb.AddPathRequest.path:type_name -> apipb.Path + 0, // 17: apipb.DeletePathRequest.table_type:type_name -> apipb.TableType + 98, // 18: apipb.DeletePathRequest.family:type_name -> apipb.Family + 100, // 19: apipb.DeletePathRequest.path:type_name -> apipb.Path + 9, // 20: apipb.TableLookupPrefix.type:type_name -> apipb.TableLookupPrefix.Type + 0, // 21: apipb.ListPathRequest.table_type:type_name -> apipb.TableType + 98, // 22: apipb.ListPathRequest.family:type_name -> apipb.Family + 54, // 23: apipb.ListPathRequest.prefixes:type_name -> apipb.TableLookupPrefix + 10, // 24: apipb.ListPathRequest.sort_type:type_name -> apipb.ListPathRequest.SortType + 101, // 25: apipb.ListPathResponse.destination:type_name -> apipb.Destination + 0, // 26: apipb.AddPathStreamRequest.table_type:type_name -> apipb.TableType + 100, // 27: apipb.AddPathStreamRequest.paths:type_name -> apipb.Path + 0, // 28: apipb.GetTableRequest.table_type:type_name -> apipb.TableType + 98, // 29: apipb.GetTableRequest.family:type_name -> apipb.Family + 166, // 30: apipb.AddVrfRequest.vrf:type_name -> apipb.Vrf + 166, // 31: apipb.ListVrfResponse.vrf:type_name -> apipb.Vrf + 162, // 32: apipb.AddPolicyRequest.policy:type_name -> apipb.Policy + 162, // 33: apipb.DeletePolicyRequest.policy:type_name -> apipb.Policy + 162, // 34: apipb.ListPolicyResponse.policy:type_name -> apipb.Policy + 151, // 35: apipb.SetPoliciesRequest.defined_sets:type_name -> apipb.DefinedSet + 162, // 36: apipb.SetPoliciesRequest.policies:type_name -> apipb.Policy + 163, // 37: apipb.SetPoliciesRequest.assignments:type_name -> apipb.PolicyAssignment + 151, // 38: apipb.AddDefinedSetRequest.defined_set:type_name -> apipb.DefinedSet + 151, // 39: apipb.DeleteDefinedSetRequest.defined_set:type_name -> apipb.DefinedSet + 3, // 40: apipb.ListDefinedSetRequest.defined_type:type_name -> apipb.DefinedType + 151, // 41: apipb.ListDefinedSetResponse.defined_set:type_name -> apipb.DefinedSet + 161, // 42: apipb.AddStatementRequest.statement:type_name -> apipb.Statement + 161, // 43: apipb.DeleteStatementRequest.statement:type_name -> apipb.Statement + 161, // 44: apipb.ListStatementResponse.statement:type_name -> apipb.Statement + 163, // 45: apipb.AddPolicyAssignmentRequest.assignment:type_name -> apipb.PolicyAssignment + 163, // 46: apipb.DeletePolicyAssignmentRequest.assignment:type_name -> apipb.PolicyAssignment + 5, // 47: apipb.ListPolicyAssignmentRequest.direction:type_name -> apipb.PolicyDirection + 163, // 48: apipb.ListPolicyAssignmentResponse.assignment:type_name -> apipb.PolicyAssignment + 163, // 49: apipb.SetPolicyAssignmentRequest.assignment:type_name -> apipb.PolicyAssignment + 98, // 50: apipb.ListRpkiRequest.family:type_name -> apipb.Family + 172, // 51: apipb.ListRpkiResponse.server:type_name -> apipb.Rpki + 98, // 52: apipb.ListRpkiTableRequest.family:type_name -> apipb.Family + 165, // 53: apipb.ListRpkiTableResponse.roa:type_name -> apipb.Roa + 11, // 54: apipb.EnableMrtRequest.type:type_name -> apipb.EnableMrtRequest.DumpType + 12, // 55: apipb.AddBmpRequest.policy:type_name -> apipb.AddBmpRequest.MonitoringPolicy + 179, // 56: apipb.ListBmpResponse.station:type_name -> apipb.ListBmpResponse.BmpStation + 13, // 57: apipb.Family.afi:type_name -> apipb.Family.Afi + 14, // 58: apipb.Family.safi:type_name -> apipb.Family.Safi + 15, // 59: apipb.Validation.state:type_name -> apipb.Validation.State + 16, // 60: apipb.Validation.reason:type_name -> apipb.Validation.Reason + 165, // 61: apipb.Validation.matched:type_name -> apipb.Roa + 165, // 62: apipb.Validation.unmatched_asn:type_name -> apipb.Roa + 165, // 63: apipb.Validation.unmatched_length:type_name -> apipb.Roa + 182, // 64: apipb.Path.nlri:type_name -> google.protobuf.Any + 182, // 65: apipb.Path.pattrs:type_name -> google.protobuf.Any + 183, // 66: apipb.Path.age:type_name -> google.protobuf.Timestamp + 99, // 67: apipb.Path.validation:type_name -> apipb.Validation + 98, // 68: apipb.Path.family:type_name -> apipb.Family + 100, // 69: apipb.Destination.paths:type_name -> apipb.Path + 105, // 70: apipb.Peer.apply_policy:type_name -> apipb.ApplyPolicy + 107, // 71: apipb.Peer.conf:type_name -> apipb.PeerConf + 111, // 72: apipb.Peer.ebgp_multihop:type_name -> apipb.EbgpMultihop + 112, // 73: apipb.Peer.route_reflector:type_name -> apipb.RouteReflector + 113, // 74: apipb.Peer.state:type_name -> apipb.PeerState + 117, // 75: apipb.Peer.timers:type_name -> apipb.Timers + 120, // 76: apipb.Peer.transport:type_name -> apipb.Transport + 121, // 77: apipb.Peer.route_server:type_name -> apipb.RouteServer + 122, // 78: apipb.Peer.graceful_restart:type_name -> apipb.GracefulRestart + 146, // 79: apipb.Peer.afi_safis:type_name -> apipb.AfiSafi + 110, // 80: apipb.Peer.ttl_security:type_name -> apipb.TtlSecurity + 105, // 81: apipb.PeerGroup.apply_policy:type_name -> apipb.ApplyPolicy + 108, // 82: apipb.PeerGroup.conf:type_name -> apipb.PeerGroupConf + 111, // 83: apipb.PeerGroup.ebgp_multihop:type_name -> apipb.EbgpMultihop + 112, // 84: apipb.PeerGroup.route_reflector:type_name -> apipb.RouteReflector + 109, // 85: apipb.PeerGroup.info:type_name -> apipb.PeerGroupState + 117, // 86: apipb.PeerGroup.timers:type_name -> apipb.Timers + 120, // 87: apipb.PeerGroup.transport:type_name -> apipb.Transport + 121, // 88: apipb.PeerGroup.route_server:type_name -> apipb.RouteServer + 122, // 89: apipb.PeerGroup.graceful_restart:type_name -> apipb.GracefulRestart + 146, // 90: apipb.PeerGroup.afi_safis:type_name -> apipb.AfiSafi + 110, // 91: apipb.PeerGroup.ttl_security:type_name -> apipb.TtlSecurity + 163, // 92: apipb.ApplyPolicy.in_policy:type_name -> apipb.PolicyAssignment + 163, // 93: apipb.ApplyPolicy.export_policy:type_name -> apipb.PolicyAssignment + 163, // 94: apipb.ApplyPolicy.import_policy:type_name -> apipb.PolicyAssignment + 98, // 95: apipb.PrefixLimit.family:type_name -> apipb.Family + 1, // 96: apipb.PeerConf.type:type_name -> apipb.PeerType + 2, // 97: apipb.PeerConf.remove_private:type_name -> apipb.RemovePrivate + 1, // 98: apipb.PeerGroupConf.type:type_name -> apipb.PeerType + 2, // 99: apipb.PeerGroupConf.remove_private:type_name -> apipb.RemovePrivate + 1, // 100: apipb.PeerGroupState.type:type_name -> apipb.PeerType + 2, // 101: apipb.PeerGroupState.remove_private:type_name -> apipb.RemovePrivate + 114, // 102: apipb.PeerState.messages:type_name -> apipb.Messages + 1, // 103: apipb.PeerState.type:type_name -> apipb.PeerType + 116, // 104: apipb.PeerState.queues:type_name -> apipb.Queues + 2, // 105: apipb.PeerState.remove_private:type_name -> apipb.RemovePrivate + 17, // 106: apipb.PeerState.session_state:type_name -> apipb.PeerState.SessionState + 18, // 107: apipb.PeerState.admin_state:type_name -> apipb.PeerState.AdminState + 182, // 108: apipb.PeerState.remote_cap:type_name -> google.protobuf.Any + 182, // 109: apipb.PeerState.local_cap:type_name -> google.protobuf.Any + 115, // 110: apipb.Messages.received:type_name -> apipb.Message + 115, // 111: apipb.Messages.sent:type_name -> apipb.Message + 118, // 112: apipb.Timers.config:type_name -> apipb.TimersConfig + 119, // 113: apipb.Timers.state:type_name -> apipb.TimersState + 183, // 114: apipb.TimersState.uptime:type_name -> google.protobuf.Timestamp + 183, // 115: apipb.TimersState.downtime:type_name -> google.protobuf.Timestamp + 123, // 116: apipb.MpGracefulRestart.config:type_name -> apipb.MpGracefulRestartConfig + 124, // 117: apipb.MpGracefulRestart.state:type_name -> apipb.MpGracefulRestartState + 98, // 118: apipb.AfiSafiConfig.family:type_name -> apipb.Family + 98, // 119: apipb.AfiSafiState.family:type_name -> apipb.Family + 128, // 120: apipb.RouteSelectionOptions.config:type_name -> apipb.RouteSelectionOptionsConfig + 129, // 121: apipb.RouteSelectionOptions.state:type_name -> apipb.RouteSelectionOptionsState + 133, // 122: apipb.Ebgp.config:type_name -> apipb.EbgpConfig + 134, // 123: apipb.Ebgp.state:type_name -> apipb.EbgpState + 136, // 124: apipb.Ibgp.config:type_name -> apipb.IbgpConfig + 137, // 125: apipb.Ibgp.state:type_name -> apipb.IbgpState + 131, // 126: apipb.UseMultiplePaths.config:type_name -> apipb.UseMultiplePathsConfig + 132, // 127: apipb.UseMultiplePaths.state:type_name -> apipb.UseMultiplePathsState + 135, // 128: apipb.UseMultiplePaths.ebgp:type_name -> apipb.Ebgp + 138, // 129: apipb.UseMultiplePaths.ibgp:type_name -> apipb.Ibgp + 140, // 130: apipb.RouteTargetMembership.config:type_name -> apipb.RouteTargetMembershipConfig + 141, // 131: apipb.RouteTargetMembership.state:type_name -> apipb.RouteTargetMembershipState + 143, // 132: apipb.LongLivedGracefulRestart.config:type_name -> apipb.LongLivedGracefulRestartConfig + 144, // 133: apipb.LongLivedGracefulRestart.state:type_name -> apipb.LongLivedGracefulRestartState + 125, // 134: apipb.AfiSafi.mp_graceful_restart:type_name -> apipb.MpGracefulRestart + 126, // 135: apipb.AfiSafi.config:type_name -> apipb.AfiSafiConfig + 127, // 136: apipb.AfiSafi.state:type_name -> apipb.AfiSafiState + 105, // 137: apipb.AfiSafi.apply_policy:type_name -> apipb.ApplyPolicy + 130, // 138: apipb.AfiSafi.route_selection_options:type_name -> apipb.RouteSelectionOptions + 139, // 139: apipb.AfiSafi.use_multiple_paths:type_name -> apipb.UseMultiplePaths + 106, // 140: apipb.AfiSafi.prefix_limits:type_name -> apipb.PrefixLimit + 142, // 141: apipb.AfiSafi.route_target_membership:type_name -> apipb.RouteTargetMembership + 145, // 142: apipb.AfiSafi.long_lived_graceful_restart:type_name -> apipb.LongLivedGracefulRestart + 149, // 143: apipb.AfiSafi.add_paths:type_name -> apipb.AddPaths + 147, // 144: apipb.AddPaths.config:type_name -> apipb.AddPathsConfig + 148, // 145: apipb.AddPaths.state:type_name -> apipb.AddPathsState + 3, // 146: apipb.DefinedSet.defined_type:type_name -> apipb.DefinedType + 150, // 147: apipb.DefinedSet.prefixes:type_name -> apipb.Prefix + 19, // 148: apipb.MatchSet.type:type_name -> apipb.MatchSet.Type + 20, // 149: apipb.AsPathLength.type:type_name -> apipb.AsPathLength.Type + 152, // 150: apipb.Conditions.prefix_set:type_name -> apipb.MatchSet + 152, // 151: apipb.Conditions.neighbor_set:type_name -> apipb.MatchSet + 153, // 152: apipb.Conditions.as_path_length:type_name -> apipb.AsPathLength + 152, // 153: apipb.Conditions.as_path_set:type_name -> apipb.MatchSet + 152, // 154: apipb.Conditions.community_set:type_name -> apipb.MatchSet + 152, // 155: apipb.Conditions.ext_community_set:type_name -> apipb.MatchSet + 21, // 156: apipb.Conditions.route_type:type_name -> apipb.Conditions.RouteType + 152, // 157: apipb.Conditions.large_community_set:type_name -> apipb.MatchSet + 98, // 158: apipb.Conditions.afi_safi_in:type_name -> apipb.Family + 22, // 159: apipb.CommunityAction.type:type_name -> apipb.CommunityAction.Type + 23, // 160: apipb.MedAction.type:type_name -> apipb.MedAction.Type + 4, // 161: apipb.Actions.route_action:type_name -> apipb.RouteAction + 155, // 162: apipb.Actions.community:type_name -> apipb.CommunityAction + 156, // 163: apipb.Actions.med:type_name -> apipb.MedAction + 157, // 164: apipb.Actions.as_prepend:type_name -> apipb.AsPrependAction + 155, // 165: apipb.Actions.ext_community:type_name -> apipb.CommunityAction + 158, // 166: apipb.Actions.nexthop:type_name -> apipb.NexthopAction + 159, // 167: apipb.Actions.local_pref:type_name -> apipb.LocalPrefAction + 155, // 168: apipb.Actions.large_community:type_name -> apipb.CommunityAction + 154, // 169: apipb.Statement.conditions:type_name -> apipb.Conditions + 160, // 170: apipb.Statement.actions:type_name -> apipb.Actions + 161, // 171: apipb.Policy.statements:type_name -> apipb.Statement + 5, // 172: apipb.PolicyAssignment.direction:type_name -> apipb.PolicyDirection + 162, // 173: apipb.PolicyAssignment.policies:type_name -> apipb.Policy + 4, // 174: apipb.PolicyAssignment.default_action:type_name -> apipb.RouteAction + 151, // 175: apipb.RoutingPolicy.defined_sets:type_name -> apipb.DefinedSet + 162, // 176: apipb.RoutingPolicy.policies:type_name -> apipb.Policy + 170, // 177: apipb.Roa.conf:type_name -> apipb.RPKIConf + 182, // 178: apipb.Vrf.rd:type_name -> google.protobuf.Any + 182, // 179: apipb.Vrf.import_rt:type_name -> google.protobuf.Any + 182, // 180: apipb.Vrf.export_rt:type_name -> google.protobuf.Any + 128, // 181: apipb.Global.route_selection_options:type_name -> apipb.RouteSelectionOptionsConfig + 167, // 182: apipb.Global.default_route_distance:type_name -> apipb.DefaultRouteDistance + 169, // 183: apipb.Global.confederation:type_name -> apipb.Confederation + 122, // 184: apipb.Global.graceful_restart:type_name -> apipb.GracefulRestart + 105, // 185: apipb.Global.apply_policy:type_name -> apipb.ApplyPolicy + 183, // 186: apipb.RPKIState.uptime:type_name -> google.protobuf.Timestamp + 183, // 187: apipb.RPKIState.downtime:type_name -> google.protobuf.Timestamp + 170, // 188: apipb.Rpki.conf:type_name -> apipb.RPKIConf + 171, // 189: apipb.Rpki.state:type_name -> apipb.RPKIState + 24, // 190: apipb.SetLogLevelRequest.level:type_name -> apipb.SetLogLevelRequest.Level + 176, // 191: apipb.WatchEventRequest.Table.filters:type_name -> apipb.WatchEventRequest.Table.Filter + 6, // 192: apipb.WatchEventRequest.Table.Filter.type:type_name -> apipb.WatchEventRequest.Table.Filter.Type + 7, // 193: apipb.WatchEventResponse.PeerEvent.type:type_name -> apipb.WatchEventResponse.PeerEvent.Type + 102, // 194: apipb.WatchEventResponse.PeerEvent.peer:type_name -> apipb.Peer + 100, // 195: apipb.WatchEventResponse.TableEvent.paths:type_name -> apipb.Path + 180, // 196: apipb.ListBmpResponse.BmpStation.conf:type_name -> apipb.ListBmpResponse.BmpStation.Conf + 181, // 197: apipb.ListBmpResponse.BmpStation.state:type_name -> apipb.ListBmpResponse.BmpStation.State + 183, // 198: apipb.ListBmpResponse.BmpStation.State.uptime:type_name -> google.protobuf.Timestamp + 183, // 199: apipb.ListBmpResponse.BmpStation.State.downtime:type_name -> google.protobuf.Timestamp + 25, // 200: apipb.GobgpApi.StartBgp:input_type -> apipb.StartBgpRequest + 26, // 201: apipb.GobgpApi.StopBgp:input_type -> apipb.StopBgpRequest + 27, // 202: apipb.GobgpApi.GetBgp:input_type -> apipb.GetBgpRequest + 29, // 203: apipb.GobgpApi.WatchEvent:input_type -> apipb.WatchEventRequest + 31, // 204: apipb.GobgpApi.AddPeer:input_type -> apipb.AddPeerRequest + 32, // 205: apipb.GobgpApi.DeletePeer:input_type -> apipb.DeletePeerRequest + 33, // 206: apipb.GobgpApi.ListPeer:input_type -> apipb.ListPeerRequest + 35, // 207: apipb.GobgpApi.UpdatePeer:input_type -> apipb.UpdatePeerRequest + 37, // 208: apipb.GobgpApi.ResetPeer:input_type -> apipb.ResetPeerRequest + 38, // 209: apipb.GobgpApi.ShutdownPeer:input_type -> apipb.ShutdownPeerRequest + 39, // 210: apipb.GobgpApi.EnablePeer:input_type -> apipb.EnablePeerRequest + 40, // 211: apipb.GobgpApi.DisablePeer:input_type -> apipb.DisablePeerRequest + 41, // 212: apipb.GobgpApi.AddPeerGroup:input_type -> apipb.AddPeerGroupRequest + 42, // 213: apipb.GobgpApi.DeletePeerGroup:input_type -> apipb.DeletePeerGroupRequest + 45, // 214: apipb.GobgpApi.ListPeerGroup:input_type -> apipb.ListPeerGroupRequest + 43, // 215: apipb.GobgpApi.UpdatePeerGroup:input_type -> apipb.UpdatePeerGroupRequest + 47, // 216: apipb.GobgpApi.AddDynamicNeighbor:input_type -> apipb.AddDynamicNeighborRequest + 49, // 217: apipb.GobgpApi.ListDynamicNeighbor:input_type -> apipb.ListDynamicNeighborRequest + 48, // 218: apipb.GobgpApi.DeleteDynamicNeighbor:input_type -> apipb.DeleteDynamicNeighborRequest + 51, // 219: apipb.GobgpApi.AddPath:input_type -> apipb.AddPathRequest + 53, // 220: apipb.GobgpApi.DeletePath:input_type -> apipb.DeletePathRequest + 55, // 221: apipb.GobgpApi.ListPath:input_type -> apipb.ListPathRequest + 57, // 222: apipb.GobgpApi.AddPathStream:input_type -> apipb.AddPathStreamRequest + 58, // 223: apipb.GobgpApi.GetTable:input_type -> apipb.GetTableRequest + 60, // 224: apipb.GobgpApi.AddVrf:input_type -> apipb.AddVrfRequest + 61, // 225: apipb.GobgpApi.DeleteVrf:input_type -> apipb.DeleteVrfRequest + 62, // 226: apipb.GobgpApi.ListVrf:input_type -> apipb.ListVrfRequest + 64, // 227: apipb.GobgpApi.AddPolicy:input_type -> apipb.AddPolicyRequest + 65, // 228: apipb.GobgpApi.DeletePolicy:input_type -> apipb.DeletePolicyRequest + 66, // 229: apipb.GobgpApi.ListPolicy:input_type -> apipb.ListPolicyRequest + 68, // 230: apipb.GobgpApi.SetPolicies:input_type -> apipb.SetPoliciesRequest + 69, // 231: apipb.GobgpApi.AddDefinedSet:input_type -> apipb.AddDefinedSetRequest + 70, // 232: apipb.GobgpApi.DeleteDefinedSet:input_type -> apipb.DeleteDefinedSetRequest + 71, // 233: apipb.GobgpApi.ListDefinedSet:input_type -> apipb.ListDefinedSetRequest + 73, // 234: apipb.GobgpApi.AddStatement:input_type -> apipb.AddStatementRequest + 74, // 235: apipb.GobgpApi.DeleteStatement:input_type -> apipb.DeleteStatementRequest + 75, // 236: apipb.GobgpApi.ListStatement:input_type -> apipb.ListStatementRequest + 77, // 237: apipb.GobgpApi.AddPolicyAssignment:input_type -> apipb.AddPolicyAssignmentRequest + 78, // 238: apipb.GobgpApi.DeletePolicyAssignment:input_type -> apipb.DeletePolicyAssignmentRequest + 79, // 239: apipb.GobgpApi.ListPolicyAssignment:input_type -> apipb.ListPolicyAssignmentRequest + 81, // 240: apipb.GobgpApi.SetPolicyAssignment:input_type -> apipb.SetPolicyAssignmentRequest + 82, // 241: apipb.GobgpApi.AddRpki:input_type -> apipb.AddRpkiRequest + 83, // 242: apipb.GobgpApi.DeleteRpki:input_type -> apipb.DeleteRpkiRequest + 84, // 243: apipb.GobgpApi.ListRpki:input_type -> apipb.ListRpkiRequest + 86, // 244: apipb.GobgpApi.EnableRpki:input_type -> apipb.EnableRpkiRequest + 87, // 245: apipb.GobgpApi.DisableRpki:input_type -> apipb.DisableRpkiRequest + 88, // 246: apipb.GobgpApi.ResetRpki:input_type -> apipb.ResetRpkiRequest + 89, // 247: apipb.GobgpApi.ListRpkiTable:input_type -> apipb.ListRpkiTableRequest + 91, // 248: apipb.GobgpApi.EnableZebra:input_type -> apipb.EnableZebraRequest + 92, // 249: apipb.GobgpApi.EnableMrt:input_type -> apipb.EnableMrtRequest + 93, // 250: apipb.GobgpApi.DisableMrt:input_type -> apipb.DisableMrtRequest + 94, // 251: apipb.GobgpApi.AddBmp:input_type -> apipb.AddBmpRequest + 95, // 252: apipb.GobgpApi.DeleteBmp:input_type -> apipb.DeleteBmpRequest + 96, // 253: apipb.GobgpApi.ListBmp:input_type -> apipb.ListBmpRequest + 173, // 254: apipb.GobgpApi.SetLogLevel:input_type -> apipb.SetLogLevelRequest + 184, // 255: apipb.GobgpApi.StartBgp:output_type -> google.protobuf.Empty + 184, // 256: apipb.GobgpApi.StopBgp:output_type -> google.protobuf.Empty + 28, // 257: apipb.GobgpApi.GetBgp:output_type -> apipb.GetBgpResponse + 30, // 258: apipb.GobgpApi.WatchEvent:output_type -> apipb.WatchEventResponse + 184, // 259: apipb.GobgpApi.AddPeer:output_type -> google.protobuf.Empty + 184, // 260: apipb.GobgpApi.DeletePeer:output_type -> google.protobuf.Empty + 34, // 261: apipb.GobgpApi.ListPeer:output_type -> apipb.ListPeerResponse + 36, // 262: apipb.GobgpApi.UpdatePeer:output_type -> apipb.UpdatePeerResponse + 184, // 263: apipb.GobgpApi.ResetPeer:output_type -> google.protobuf.Empty + 184, // 264: apipb.GobgpApi.ShutdownPeer:output_type -> google.protobuf.Empty + 184, // 265: apipb.GobgpApi.EnablePeer:output_type -> google.protobuf.Empty + 184, // 266: apipb.GobgpApi.DisablePeer:output_type -> google.protobuf.Empty + 184, // 267: apipb.GobgpApi.AddPeerGroup:output_type -> google.protobuf.Empty + 184, // 268: apipb.GobgpApi.DeletePeerGroup:output_type -> google.protobuf.Empty + 46, // 269: apipb.GobgpApi.ListPeerGroup:output_type -> apipb.ListPeerGroupResponse + 44, // 270: apipb.GobgpApi.UpdatePeerGroup:output_type -> apipb.UpdatePeerGroupResponse + 184, // 271: apipb.GobgpApi.AddDynamicNeighbor:output_type -> google.protobuf.Empty + 50, // 272: apipb.GobgpApi.ListDynamicNeighbor:output_type -> apipb.ListDynamicNeighborResponse + 184, // 273: apipb.GobgpApi.DeleteDynamicNeighbor:output_type -> google.protobuf.Empty + 52, // 274: apipb.GobgpApi.AddPath:output_type -> apipb.AddPathResponse + 184, // 275: apipb.GobgpApi.DeletePath:output_type -> google.protobuf.Empty + 56, // 276: apipb.GobgpApi.ListPath:output_type -> apipb.ListPathResponse + 184, // 277: apipb.GobgpApi.AddPathStream:output_type -> google.protobuf.Empty + 59, // 278: apipb.GobgpApi.GetTable:output_type -> apipb.GetTableResponse + 184, // 279: apipb.GobgpApi.AddVrf:output_type -> google.protobuf.Empty + 184, // 280: apipb.GobgpApi.DeleteVrf:output_type -> google.protobuf.Empty + 63, // 281: apipb.GobgpApi.ListVrf:output_type -> apipb.ListVrfResponse + 184, // 282: apipb.GobgpApi.AddPolicy:output_type -> google.protobuf.Empty + 184, // 283: apipb.GobgpApi.DeletePolicy:output_type -> google.protobuf.Empty + 67, // 284: apipb.GobgpApi.ListPolicy:output_type -> apipb.ListPolicyResponse + 184, // 285: apipb.GobgpApi.SetPolicies:output_type -> google.protobuf.Empty + 184, // 286: apipb.GobgpApi.AddDefinedSet:output_type -> google.protobuf.Empty + 184, // 287: apipb.GobgpApi.DeleteDefinedSet:output_type -> google.protobuf.Empty + 72, // 288: apipb.GobgpApi.ListDefinedSet:output_type -> apipb.ListDefinedSetResponse + 184, // 289: apipb.GobgpApi.AddStatement:output_type -> google.protobuf.Empty + 184, // 290: apipb.GobgpApi.DeleteStatement:output_type -> google.protobuf.Empty + 76, // 291: apipb.GobgpApi.ListStatement:output_type -> apipb.ListStatementResponse + 184, // 292: apipb.GobgpApi.AddPolicyAssignment:output_type -> google.protobuf.Empty + 184, // 293: apipb.GobgpApi.DeletePolicyAssignment:output_type -> google.protobuf.Empty + 80, // 294: apipb.GobgpApi.ListPolicyAssignment:output_type -> apipb.ListPolicyAssignmentResponse + 184, // 295: apipb.GobgpApi.SetPolicyAssignment:output_type -> google.protobuf.Empty + 184, // 296: apipb.GobgpApi.AddRpki:output_type -> google.protobuf.Empty + 184, // 297: apipb.GobgpApi.DeleteRpki:output_type -> google.protobuf.Empty + 85, // 298: apipb.GobgpApi.ListRpki:output_type -> apipb.ListRpkiResponse + 184, // 299: apipb.GobgpApi.EnableRpki:output_type -> google.protobuf.Empty + 184, // 300: apipb.GobgpApi.DisableRpki:output_type -> google.protobuf.Empty + 184, // 301: apipb.GobgpApi.ResetRpki:output_type -> google.protobuf.Empty + 90, // 302: apipb.GobgpApi.ListRpkiTable:output_type -> apipb.ListRpkiTableResponse + 184, // 303: apipb.GobgpApi.EnableZebra:output_type -> google.protobuf.Empty + 184, // 304: apipb.GobgpApi.EnableMrt:output_type -> google.protobuf.Empty + 184, // 305: apipb.GobgpApi.DisableMrt:output_type -> google.protobuf.Empty + 184, // 306: apipb.GobgpApi.AddBmp:output_type -> google.protobuf.Empty + 184, // 307: apipb.GobgpApi.DeleteBmp:output_type -> google.protobuf.Empty + 97, // 308: apipb.GobgpApi.ListBmp:output_type -> apipb.ListBmpResponse + 184, // 309: apipb.GobgpApi.SetLogLevel:output_type -> google.protobuf.Empty + 255, // [255:310] is the sub-list for method output_type + 200, // [200:255] is the sub-list for method input_type + 200, // [200:200] is the sub-list for extension type_name + 200, // [200:200] is the sub-list for extension extendee + 0, // [0:200] is the sub-list for field type_name +} + +func init() { file_gobgp_proto_init() } +func file_gobgp_proto_init() { + if File_gobgp_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_gobgp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartBgpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StopBgpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBgpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetBgpResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPeerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdatePeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdatePeerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResetPeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ShutdownPeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnablePeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DisablePeerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPeerGroupRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePeerGroupRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdatePeerGroupRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdatePeerGroupResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPeerGroupRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPeerGroupResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddDynamicNeighborRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteDynamicNeighborRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDynamicNeighborRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDynamicNeighborResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePathRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TableLookupPrefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPathRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPathResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathStreamRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTableRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTableResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddVrfRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteVrfRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListVrfRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListVrfResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPolicyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPolicyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetPoliciesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddDefinedSetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteDefinedSetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDefinedSetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDefinedSetResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddStatementRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteStatementRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListStatementRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListStatementResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPolicyAssignmentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeletePolicyAssignmentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPolicyAssignmentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPolicyAssignmentResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetPolicyAssignmentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRpkiResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnableRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DisableRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResetRpkiRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRpkiTableRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListRpkiTableResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnableZebraRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EnableMrtRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DisableMrtRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddBmpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteBmpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListBmpRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListBmpResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Family); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Validation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Path); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Destination); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Peer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerGroup); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DynamicNeighbor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ApplyPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PrefixLimit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerConf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerGroupConf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerGroupState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TtlSecurity); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EbgpMultihop); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteReflector); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Messages); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Message); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Queues); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Timers); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TimersConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TimersState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Transport); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteServer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GracefulRestart); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MpGracefulRestartConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MpGracefulRestartState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MpGracefulRestart); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AfiSafiConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AfiSafiState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteSelectionOptionsConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteSelectionOptionsState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteSelectionOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UseMultiplePathsConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UseMultiplePathsState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EbgpConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[109].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EbgpState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ebgp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IbgpConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IbgpState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[113].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ibgp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UseMultiplePaths); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteTargetMembershipConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[116].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteTargetMembershipState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[117].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RouteTargetMembership); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[118].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LongLivedGracefulRestartConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[119].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LongLivedGracefulRestartState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[120].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LongLivedGracefulRestart); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[121].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AfiSafi); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[122].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathsConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[123].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPathsState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[124].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPaths); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[125].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Prefix); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[126].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DefinedSet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[127].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MatchSet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[128].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AsPathLength); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[129].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Conditions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[130].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommunityAction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[131].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MedAction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[132].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AsPrependAction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[133].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NexthopAction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[134].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LocalPrefAction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[135].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Actions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[136].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Statement); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[137].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[138].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyAssignment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[139].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RoutingPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[140].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Roa); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[141].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Vrf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[142].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DefaultRouteDistance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[143].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Global); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[144].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Confederation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[145].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPKIConf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[146].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPKIState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[147].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Rpki); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[148].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetLogLevelRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[149].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventRequest_Peer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[150].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventRequest_Table); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[151].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventRequest_Table_Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[152].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventResponse_PeerEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[153].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WatchEventResponse_TableEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[154].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListBmpResponse_BmpStation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[155].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListBmpResponse_BmpStation_Conf); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gobgp_proto_msgTypes[156].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListBmpResponse_BmpStation_State); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_gobgp_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*WatchEventResponse_Peer)(nil), + (*WatchEventResponse_Table)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_gobgp_proto_rawDesc, + NumEnums: 25, + NumMessages: 157, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_gobgp_proto_goTypes, + DependencyIndexes: file_gobgp_proto_depIdxs, + EnumInfos: file_gobgp_proto_enumTypes, + MessageInfos: file_gobgp_proto_msgTypes, + }.Build() + File_gobgp_proto = out.File + file_gobgp_proto_rawDesc = nil + file_gobgp_proto_goTypes = nil + file_gobgp_proto_depIdxs = nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/gobgp.proto b/vendor/github.com/osrg/gobgp/v3/api/gobgp.proto new file mode 100644 index 000000000..fd6e19059 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/gobgp.proto @@ -0,0 +1,1115 @@ +// Copyright (C) 2015-2017 Nippon Telegraph and Telephone Corporation. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation files +// (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +syntax = "proto3"; + +package apipb; +option go_package = "github.com/osrg/gobgp/v3/api;apipb"; + +import "google/protobuf/any.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; + + +// Interface exported by the server. + +service GobgpApi { + rpc StartBgp(StartBgpRequest) returns(google.protobuf.Empty); + rpc StopBgp(StopBgpRequest) returns(google.protobuf.Empty); + rpc GetBgp(GetBgpRequest) returns(GetBgpResponse); + + rpc WatchEvent(WatchEventRequest) returns(stream WatchEventResponse); + + rpc AddPeer(AddPeerRequest) returns(google.protobuf.Empty); + rpc DeletePeer(DeletePeerRequest) returns(google.protobuf.Empty); + rpc ListPeer(ListPeerRequest) returns(stream ListPeerResponse); + rpc UpdatePeer(UpdatePeerRequest) returns(UpdatePeerResponse); + rpc ResetPeer(ResetPeerRequest) returns(google.protobuf.Empty); + rpc ShutdownPeer(ShutdownPeerRequest) returns(google.protobuf.Empty); + rpc EnablePeer(EnablePeerRequest) returns(google.protobuf.Empty); + rpc DisablePeer(DisablePeerRequest) returns(google.protobuf.Empty); + + rpc AddPeerGroup(AddPeerGroupRequest) returns(google.protobuf.Empty); + rpc DeletePeerGroup(DeletePeerGroupRequest) returns(google.protobuf.Empty); + rpc ListPeerGroup(ListPeerGroupRequest) returns(stream ListPeerGroupResponse); + rpc UpdatePeerGroup(UpdatePeerGroupRequest) returns(UpdatePeerGroupResponse); + + rpc AddDynamicNeighbor(AddDynamicNeighborRequest) returns(google.protobuf.Empty); + rpc ListDynamicNeighbor(ListDynamicNeighborRequest) returns(stream ListDynamicNeighborResponse); + rpc DeleteDynamicNeighbor(DeleteDynamicNeighborRequest) returns(google.protobuf.Empty); + + rpc AddPath(AddPathRequest) returns(AddPathResponse); + rpc DeletePath(DeletePathRequest) returns(google.protobuf.Empty); + rpc ListPath(ListPathRequest) returns(stream ListPathResponse); + rpc AddPathStream(stream AddPathStreamRequest) returns(google.protobuf.Empty); + + rpc GetTable(GetTableRequest) returns(GetTableResponse); + + rpc AddVrf(AddVrfRequest) returns(google.protobuf.Empty); + rpc DeleteVrf(DeleteVrfRequest) returns(google.protobuf.Empty); + rpc ListVrf(ListVrfRequest) returns(stream ListVrfResponse); + + rpc AddPolicy(AddPolicyRequest) returns(google.protobuf.Empty); + rpc DeletePolicy(DeletePolicyRequest) returns(google.protobuf.Empty); + rpc ListPolicy(ListPolicyRequest) returns(stream ListPolicyResponse); + rpc SetPolicies(SetPoliciesRequest) returns(google.protobuf.Empty); + + rpc AddDefinedSet(AddDefinedSetRequest) returns(google.protobuf.Empty); + rpc DeleteDefinedSet(DeleteDefinedSetRequest) returns(google.protobuf.Empty); + rpc ListDefinedSet(ListDefinedSetRequest) + returns(stream ListDefinedSetResponse); + + rpc AddStatement(AddStatementRequest) returns(google.protobuf.Empty); + rpc DeleteStatement(DeleteStatementRequest) returns(google.protobuf.Empty); + rpc ListStatement(ListStatementRequest) returns(stream ListStatementResponse); + + rpc AddPolicyAssignment(AddPolicyAssignmentRequest) + returns(google.protobuf.Empty); + rpc DeletePolicyAssignment(DeletePolicyAssignmentRequest) + returns(google.protobuf.Empty); + rpc ListPolicyAssignment(ListPolicyAssignmentRequest) + returns(stream ListPolicyAssignmentResponse); + rpc SetPolicyAssignment(SetPolicyAssignmentRequest) + returns(google.protobuf.Empty); + + rpc AddRpki(AddRpkiRequest) returns(google.protobuf.Empty); + rpc DeleteRpki(DeleteRpkiRequest) returns(google.protobuf.Empty); + rpc ListRpki(ListRpkiRequest) returns(stream ListRpkiResponse); + rpc EnableRpki(EnableRpkiRequest) returns(google.protobuf.Empty); + rpc DisableRpki(DisableRpkiRequest) returns(google.protobuf.Empty); + rpc ResetRpki(ResetRpkiRequest) returns(google.protobuf.Empty); + rpc ListRpkiTable(ListRpkiTableRequest) returns(stream ListRpkiTableResponse); + + rpc EnableZebra(EnableZebraRequest) returns(google.protobuf.Empty); + + rpc EnableMrt(EnableMrtRequest) returns(google.protobuf.Empty); + rpc DisableMrt(DisableMrtRequest) returns(google.protobuf.Empty); + + rpc AddBmp(AddBmpRequest) returns(google.protobuf.Empty); + rpc DeleteBmp(DeleteBmpRequest) returns(google.protobuf.Empty); + rpc ListBmp(ListBmpRequest) returns(stream ListBmpResponse); + + rpc SetLogLevel(SetLogLevelRequest) returns(google.protobuf.Empty); +} + +message StartBgpRequest { Global global = 1; } + +message StopBgpRequest {} + +message GetBgpRequest {} + +message GetBgpResponse { Global global = 1; } + +message WatchEventRequest { + message Peer { + } + Peer peer = 1; + + message Table { + message Filter { + enum Type { BEST = 0; ADJIN = 1; POST_POLICY = 2; } + Type type = 1; + bool init = 2; + } + repeated Filter filters = 1; + } + Table table = 2; +} + +message WatchEventResponse { + message PeerEvent { + enum Type { UNKNOWN = 0; INIT = 1; END_OF_INIT = 2; STATE = 3; } + Type type = 1; + Peer peer = 2; + } + + message TableEvent { + repeated Path paths = 2; + } + + oneof event { + PeerEvent peer = 2; + TableEvent table = 3; + } +} + +message AddPeerRequest { Peer peer = 1; } + +message DeletePeerRequest { + string address = 1; + string interface = 2; +} + +message ListPeerRequest { + string address = 1; + bool enableAdvertised = 2; +} + +message ListPeerResponse { Peer peer = 1; } + +message UpdatePeerRequest { + Peer peer = 1; + // Calls SoftResetIn after updating the peer configuration if needed. + bool do_soft_reset_in = 2; +} + +message UpdatePeerResponse { + // Indicates whether calling SoftResetIn is required due to this update. If + // "true" is set, the client should call SoftResetIn manually. If + // "do_soft_reset_in = true" is set in the request, always returned with + // "false". + bool needs_soft_reset_in = 1; +} + +message ResetPeerRequest { + string address = 1; + string communication = 2; + bool soft = 3; + enum SoftResetDirection { IN = 0; OUT = 1; BOTH = 2; } + SoftResetDirection direction = 4; +} + +message ShutdownPeerRequest { + string address = 1; + string communication = 2; +} + +message EnablePeerRequest { string address = 1; } + +message DisablePeerRequest { + string address = 1; + string communication = 2; +} + +message AddPeerGroupRequest { PeerGroup peer_group = 1; } + +message DeletePeerGroupRequest { string name = 1; } + +message UpdatePeerGroupRequest { + PeerGroup peer_group = 1; + bool do_soft_reset_in = 2; +} + +message UpdatePeerGroupResponse { bool needs_soft_reset_in = 1; } + +message ListPeerGroupRequest { string peer_group_name = 1; } + +message ListPeerGroupResponse { PeerGroup peer_group = 1; } + +message AddDynamicNeighborRequest { DynamicNeighbor dynamic_neighbor = 1; } + +message DeleteDynamicNeighborRequest { + string prefix = 1; + string peer_group = 2; +} + +message ListDynamicNeighborRequest { string peer_group = 1; } + +message ListDynamicNeighborResponse { DynamicNeighbor dynamic_neighbor = 1; } + +message AddPathRequest { + TableType table_type = 1; + string vrf_id = 2; + Path path = 3; +} + +message AddPathResponse { bytes uuid = 1; } + +message DeletePathRequest { + TableType table_type = 1; + string vrf_id = 2; + Family family = 3; + Path path = 4; + bytes uuid = 5; +} + +// API representation of table.LookupPrefix +message TableLookupPrefix { + // API representation of table.LookupOption + enum Type { EXACT = 0; LONGER = 1; SHORTER = 2; } + string prefix = 1; + Type type = 2; +} + +message ListPathRequest { + TableType table_type = 1; + string name = 2; + Family family = 3; + repeated TableLookupPrefix prefixes = 4; + enum SortType { NONE = 0; PREFIX = 1; } + SortType sort_type = 5; + bool enable_filtered = 6; + bool enable_nlri_binary = 7; + bool enable_attribute_binary = 8; +} + +message ListPathResponse { Destination destination = 1; } + +message AddPathStreamRequest { + TableType table_type = 1; + string vrf_id = 2; + repeated Path paths = 3; +} + +message GetTableRequest { + TableType table_type = 1; + Family family = 2; + string name = 3; +} + +message GetTableResponse { + uint64 num_destination = 1; + uint64 num_path = 2; + uint64 num_accepted = 3; // only meaningful when type == ADJ_IN +} + +message AddVrfRequest { Vrf vrf = 1; } + +message DeleteVrfRequest { string name = 1; } + +message ListVrfRequest { string name = 1; } + +message ListVrfResponse { Vrf vrf = 1; } + +message AddPolicyRequest { + Policy policy = 1; + // if this flag is set, gobgpd won't define new statements + // but refer existing statements using statement's names in this arguments. + bool refer_existing_statements = 2; +} + +message DeletePolicyRequest { + Policy policy = 1; + // if this flag is set, gobgpd won't delete any statements + // even if some statements get not used by any policy by this operation. + bool preserve_statements = 2; + bool all = 3; +} + +message ListPolicyRequest { string name = 1; } + +message ListPolicyResponse { Policy policy = 1; } + +message SetPoliciesRequest { + repeated DefinedSet defined_sets = 1; + repeated Policy policies = 2; + repeated PolicyAssignment assignments = 3; +} + +message AddDefinedSetRequest { DefinedSet defined_set = 1; } + +message DeleteDefinedSetRequest { + DefinedSet defined_set = 1; + bool all = 2; +} + +message ListDefinedSetRequest { + DefinedType defined_type = 1; + string name = 2; +} + +message ListDefinedSetResponse { DefinedSet defined_set = 1; } + +message AddStatementRequest { Statement statement = 1; } + +message DeleteStatementRequest { + Statement statement = 1; + bool all = 2; +} + +message ListStatementRequest { string name = 1; } + +message ListStatementResponse { Statement statement = 1; } + +message AddPolicyAssignmentRequest { PolicyAssignment assignment = 1; } + +message DeletePolicyAssignmentRequest { + PolicyAssignment assignment = 1; + bool all = 2; +} + +message ListPolicyAssignmentRequest { + string name = 1; + PolicyDirection direction = 2; +} + +message ListPolicyAssignmentResponse { PolicyAssignment assignment = 1; } + +message SetPolicyAssignmentRequest { PolicyAssignment assignment = 1; } + +message AddRpkiRequest { + string address = 1; + uint32 port = 2; + int64 lifetime = 3; +} + +message DeleteRpkiRequest { + string address = 1; + uint32 port = 2; +} + +message ListRpkiRequest { Family family = 1; } + +message ListRpkiResponse { Rpki server = 1; } + +message EnableRpkiRequest { + string address = 1; + uint32 port = 2; +} + +message DisableRpkiRequest { + string address = 1; + uint32 port = 2; +} + +message ResetRpkiRequest { + string address = 1; + uint32 port = 2; + bool soft = 3; +} + +message ListRpkiTableRequest { Family family = 1; } + +message ListRpkiTableResponse { Roa roa = 1; } + +message EnableZebraRequest { + string url = 1; + repeated string route_types = 2; + uint32 version = 3; + bool nexthop_trigger_enable = 4; + uint32 nexthop_trigger_delay = 5; + uint32 mpls_label_range_size = 6; + string software_name = 7; +} + +message EnableMrtRequest { + enum DumpType { UPDATES = 0; TABLE = 1; } + DumpType type = 1; + string filename = 2; + uint64 dump_interval = 3; + uint64 rotation_interval = 4; +} + +message DisableMrtRequest { + string filename = 1; +} + +message AddBmpRequest { + string address = 1; + uint32 port = 2; + enum MonitoringPolicy { PRE = 0; POST = 1; BOTH = 2; LOCAL = 3; ALL = 4; } + MonitoringPolicy policy = 3; + int32 StatisticsTimeout = 4; + string SysName = 5; + string SysDescr = 6; +} + +message DeleteBmpRequest { + string address = 1; + uint32 port = 2; +} + +message ListBmpRequest {} + +message ListBmpResponse { + message BmpStation { + message Conf { + string address = 1; + uint32 port = 2; + } + Conf conf = 1; + message State { + google.protobuf.Timestamp uptime = 1; + google.protobuf.Timestamp downtime = 2; + } + State state = 2; + } + + BmpStation station = 1; +} + +message Family { + enum Afi { + AFI_UNKNOWN = 0; AFI_IP = 1; AFI_IP6 = 2; AFI_L2VPN = 25; AFI_LS = 16388; + AFI_OPAQUE = 16397; + } + + enum Safi { + SAFI_UNKNOWN = 0; SAFI_UNICAST = 1; SAFI_MULTICAST = 2; SAFI_MPLS_LABEL = 4; + SAFI_ENCAPSULATION = 7; + SAFI_VPLS = 65; + SAFI_EVPN = 70; + SAFI_LS = 71; + SAFI_SR_POLICY = 73; + SAFI_MUP = 85; + SAFI_MPLS_VPN = 128; + SAFI_MPLS_VPN_MULTICAST = 129; + SAFI_ROUTE_TARGET_CONSTRAINTS = 132; + SAFI_FLOW_SPEC_UNICAST = 133; + SAFI_FLOW_SPEC_VPN = 134; + SAFI_KEY_VALUE = 241; + } + + Afi afi = 1; + Safi safi = 2; +} + +enum TableType { GLOBAL = 0; LOCAL = 1; ADJ_IN = 2; ADJ_OUT = 3; VRF = 4; } + +message Validation { + enum State { + STATE_NONE = 0; STATE_NOT_FOUND = 1; STATE_VALID = 2; STATE_INVALID = 3; + } + + enum Reason { REASON_NONE = 0; REASON_ASN = 1; REASON_LENGTH = 2; } + + State state = 1; + Reason reason = 2; + repeated Roa matched = 3; + repeated Roa unmatched_asn = 4; + repeated Roa unmatched_length = 5; +} + +message Path { + // One of the following defined in "api/attribute.proto": + // - IPAddressPrefix + // - LabeledIPAddressPrefix + // - EncapsulationNLRI + // - EVPNEthernetAutoDiscoveryRoute + // - EVPNMACIPAdvertisementRoute + // - EVPNInclusiveMulticastEthernetTagRoute + // - EVPNEthernetSegmentRoute + // - EVPNIPPrefixRoute + // - EVPNIPMSIRoute + // - LabeledVPNIPAddressPrefix + // - RouteTargetMembershipNLRI + // - FlowSpecNLRI + // - VPNFlowSpecNLRI + // - OpaqueNLRI + // - LsAddrPrefix + // - SRPolicyNLRI + // - MUPInterworkSegmentDiscoveryRoute + // - MUPDirectSegmentDiscoveryRoute + // - MUPType1SessionTransformedRoute + // - MUPType2SessionTransformedRoute + google.protobuf.Any nlri = 1; + // Each attribute must be one of *Attribute defined in + // "api/attribute.proto". + repeated google.protobuf.Any pattrs = 2; + google.protobuf.Timestamp age = 3; + bool best = 4; + bool is_withdraw = 5; + Validation validation = 7; + bool no_implicit_withdraw = 8; + Family family = 9; + uint32 source_asn = 10; + string source_id = 11; + bool filtered = 12; + bool stale = 13; + bool is_from_external = 14; + string neighbor_ip = 15; + bytes uuid = 16; // only paths installed by AddPath API have this + bool is_nexthop_invalid = 17; + uint32 identifier = 18; + uint32 local_identifier = 19; + bytes nlri_binary = 20; + repeated bytes pattrs_binary = 21; +} + +message Destination { + string prefix = 1; + repeated Path paths = 2; +} + +message Peer { + ApplyPolicy apply_policy = 1; + PeerConf conf = 2; + EbgpMultihop ebgp_multihop = 3; + RouteReflector route_reflector = 4; + PeerState state = 5; + Timers timers = 6; + Transport transport = 7; + RouteServer route_server = 8; + GracefulRestart graceful_restart = 9; + repeated AfiSafi afi_safis = 10; + TtlSecurity ttl_security = 11; +} + +message PeerGroup { + ApplyPolicy apply_policy = 1; + PeerGroupConf conf = 2; + EbgpMultihop ebgp_multihop = 3; + RouteReflector route_reflector = 4; + PeerGroupState info = 5; + Timers timers = 6; + Transport transport = 7; + RouteServer route_server = 8; + GracefulRestart graceful_restart = 9; + repeated AfiSafi afi_safis = 10; + TtlSecurity ttl_security = 11; +} + +message DynamicNeighbor { + string prefix = 1; + string peer_group = 2; +} + +message ApplyPolicy { + PolicyAssignment in_policy = 1; + PolicyAssignment export_policy = 2; + PolicyAssignment import_policy = 3; +} + +message PrefixLimit { + Family family = 1; + uint32 max_prefixes = 2; + uint32 shutdown_threshold_pct = 3; +} + +enum PeerType { INTERNAL = 0; EXTERNAL = 1; } + +enum RemovePrivate { REMOVE_NONE = 0; REMOVE_ALL = 1; REPLACE = 2; } + +message PeerConf { + string auth_password = 1; + string description = 2; + uint32 local_asn = 3; + string neighbor_address = 4; + uint32 peer_asn = 5; + string peer_group = 6; + PeerType type = 7; + RemovePrivate remove_private = 8; + bool route_flap_damping = 9; + uint32 send_community = 10; + string neighbor_interface = 11; + string vrf = 12; + uint32 allow_own_asn = 13; + bool replace_peer_asn = 14; + bool admin_down = 15; +} + +message PeerGroupConf { + string auth_password = 1; + string description = 2; + uint32 local_asn = 3; + uint32 peer_asn = 4; + string peer_group_name = 5; + PeerType type = 6; + RemovePrivate remove_private = 7; + bool route_flap_damping = 8; + uint32 send_community = 9; +} + +message PeerGroupState { + string auth_password = 1; + string description = 2; + uint32 local_asn = 3; + uint32 peer_asn = 4; + string peer_group_name = 5; + PeerType type = 6; + RemovePrivate remove_private = 7; + bool route_flap_damping = 8; + uint32 send_community = 9; + uint32 total_paths = 10; + uint32 total_prefixes = 11; +} + +message TtlSecurity { + bool enabled = 1; + uint32 ttl_min = 2; +} + +message EbgpMultihop { + bool enabled = 1; + uint32 multihop_ttl = 2; +} + +message RouteReflector { + bool route_reflector_client = 1; + string route_reflector_cluster_id = 2; +} + +message PeerState { + string auth_password = 1; + string description = 2; + uint32 local_asn = 3; + Messages messages = 4; + string neighbor_address = 5; + uint32 peer_asn = 6; + string peer_group = 7; + PeerType type = 8; + Queues queues = 9; + RemovePrivate remove_private = 10; + bool route_flap_damping = 11; + uint32 send_community = 12; + enum SessionState { + UNKNOWN = 0; IDLE = 1; CONNECT = 2; ACTIVE = 3; OPENSENT = 4; + OPENCONFIRM = 5; + ESTABLISHED = 6; + } + SessionState session_state = 13; + enum AdminState { + UP = 0; DOWN = 1; PFX_CT = 2; // prefix counter over limit + } + AdminState admin_state = 15; + uint32 out_q = 16; + uint32 flops = 17; + // Each attribute must be one of *Capability defined in + // "api/capability.proto". + repeated google.protobuf.Any remote_cap = 18; + repeated google.protobuf.Any local_cap = 19; + string router_id = 20; +} + +message Messages { + Message received = 1; + Message sent = 2; +} + +message Message { + uint64 notification = 1; + uint64 update = 2; + uint64 open = 3; + uint64 keepalive = 4; + uint64 refresh = 5; + uint64 discarded = 6; + uint64 total = 7; + uint64 withdraw_update = 8; + uint64 withdraw_prefix = 9; +} + +message Queues { + uint32 input = 1; + uint32 output = 2; +} + +message Timers { + TimersConfig config = 1; + TimersState state = 2; +} + +message TimersConfig { + uint64 connect_retry = 1; + uint64 hold_time = 2; + uint64 keepalive_interval = 3; + uint64 minimum_advertisement_interval = 4; + uint64 idle_hold_time_after_reset = 5; +} + +message TimersState { + uint64 connect_retry = 1; + uint64 hold_time = 2; + uint64 keepalive_interval = 3; + uint64 minimum_advertisement_interval = 4; + uint64 negotiated_hold_time = 5; + google.protobuf.Timestamp uptime = 6; + google.protobuf.Timestamp downtime = 7; +} + +message Transport { + string local_address = 1; + uint32 local_port = 2; + bool mtu_discovery = 3; + bool passive_mode = 4; + string remote_address = 5; + uint32 remote_port = 6; + uint32 tcp_mss = 7; + string bind_interface = 8; +} + +message RouteServer { + bool route_server_client = 1; + bool secondary_route = 2; +} + +message GracefulRestart { + bool enabled = 1; + uint32 restart_time = 2; + bool helper_only = 3; + uint32 deferral_time = 4; + bool notification_enabled = 5; + bool longlived_enabled = 6; + uint32 stale_routes_time = 7; + uint32 peer_restart_time = 8; + bool peer_restarting = 9; + bool local_restarting = 10; + string mode = 11; +} + +message MpGracefulRestartConfig { bool enabled = 1; } + +message MpGracefulRestartState { + bool enabled = 1; + bool received = 2; + bool advertised = 3; + bool end_of_rib_received = 4; + bool end_of_rib_sent = 5; +} +message MpGracefulRestart { + MpGracefulRestartConfig config = 1; + MpGracefulRestartState state = 2; +} + +message AfiSafiConfig { + Family family = 1; + bool enabled = 2; +} + +message AfiSafiState { + Family family = 1; + bool enabled = 2; + uint64 received = 3; + uint64 accepted = 4; + uint64 advertised = 5; +} + +message RouteSelectionOptionsConfig { + bool always_compare_med = 1; + bool ignore_as_path_length = 2; + bool external_compare_router_id = 3; + bool advertise_inactive_routes = 4; + bool enable_aigp = 5; + bool ignore_next_hop_igp_metric = 6; + bool disable_best_path_selection = 7; +} + +message RouteSelectionOptionsState { + bool always_compare_med = 1; + bool ignore_as_path_length = 2; + bool external_compare_router_id = 3; + bool advertise_inactive_routes = 4; + bool enable_aigp = 5; + bool ignore_next_hop_igp_metric = 6; + bool disable_best_path_selection = 7; +} + +message RouteSelectionOptions { + RouteSelectionOptionsConfig config = 1; + RouteSelectionOptionsState state = 2; +} + +message UseMultiplePathsConfig { bool enabled = 1; } + +message UseMultiplePathsState { bool enabled = 1; } + +message EbgpConfig { + bool allow_multiple_asn = 1; + uint32 maximum_paths = 2; +} + +message EbgpState { + bool allow_multiple_asn = 1; + uint32 maximum_paths = 2; +} + +message Ebgp { + EbgpConfig config = 1; + EbgpState state = 2; +} + +message IbgpConfig { uint32 maximum_paths = 1; } + +message IbgpState { uint32 maximum_paths = 1; } + +message Ibgp { + IbgpConfig config = 1; + IbgpState state = 2; +} + +message UseMultiplePaths { + UseMultiplePathsConfig config = 1; + UseMultiplePathsState state = 2; + Ebgp ebgp = 3; + Ibgp ibgp = 4; +} + +message RouteTargetMembershipConfig { uint32 deferral_time = 1; } + +message RouteTargetMembershipState { uint32 deferral_time = 1; } + +message RouteTargetMembership { + RouteTargetMembershipConfig config = 1; + RouteTargetMembershipState state = 2; +} + +message LongLivedGracefulRestartConfig { + bool enabled = 1; + uint32 restart_time = 2; +} + +message LongLivedGracefulRestartState { + bool enabled = 1; + bool received = 2; + bool advertised = 3; + uint32 peer_restart_time = 4; + bool peer_restart_timer_expired = 5; +} + +message LongLivedGracefulRestart { + LongLivedGracefulRestartConfig config = 1; + LongLivedGracefulRestartState state = 2; +} + +message AfiSafi { + MpGracefulRestart mp_graceful_restart = 1; + AfiSafiConfig config = 2; + AfiSafiState state = 3; + ApplyPolicy apply_policy = 4; + // TODO: + // Support the following structures: + // - Ipv4Unicast + // - Ipv6Unicast + // - Ipv4LabelledUnicast + // - Ipv6LabelledUnicast + // - L3vpnIpv4Unicast + // - L3vpnIpv6Unicast + // - L3vpnIpv4Multicast + // - L3vpnIpv6Multicast + // - L2vpnVpls + // - L2vpnEvpn + RouteSelectionOptions route_selection_options = 5; + UseMultiplePaths use_multiple_paths = 6; + PrefixLimit prefix_limits = 7; + RouteTargetMembership route_target_membership = 8; + LongLivedGracefulRestart long_lived_graceful_restart = 9; + AddPaths add_paths = 10; +} + +message AddPathsConfig { + bool receive = 1; + uint32 send_max = 2; +} + +message AddPathsState { + bool receive = 1; + uint32 send_max = 2; +} + +message AddPaths { + AddPathsConfig config = 1; + AddPathsState state = 2; +} + +message Prefix { + string ip_prefix = 1; + uint32 mask_length_min = 2; + uint32 mask_length_max = 3; +} + +enum DefinedType { + PREFIX = 0; NEIGHBOR = 1; TAG = 2; AS_PATH = 3; COMMUNITY = 4; + EXT_COMMUNITY = 5; + LARGE_COMMUNITY = 6; + NEXT_HOP = 7; +} + +message DefinedSet { + DefinedType defined_type = 1; + string name = 2; + repeated string list = 3; + repeated Prefix prefixes = 4; +} + +message MatchSet { + enum Type { ANY = 0; ALL = 1; INVERT = 2; } + Type type = 1; + string name = 2; +} + +message AsPathLength { + enum Type { EQ = 0; GE = 1; LE = 2; } + Type type = 1; + uint32 length = 2; +} + +message Conditions { + MatchSet prefix_set = 1; + MatchSet neighbor_set = 2; + AsPathLength as_path_length = 3; + MatchSet as_path_set = 4; + MatchSet community_set = 5; + MatchSet ext_community_set = 6; + int32 rpki_result = 7; + enum RouteType { + ROUTE_TYPE_NONE = 0; ROUTE_TYPE_INTERNAL = 1; ROUTE_TYPE_EXTERNAL = 2; ROUTE_TYPE_LOCAL = 3; + } + RouteType route_type = 8; + MatchSet large_community_set = 9; + repeated string next_hop_in_list = 10; + repeated Family afi_safi_in = 11; +} + +enum RouteAction { NONE = 0; ACCEPT = 1; REJECT = 2; } + +message CommunityAction { + enum Type { + ADD = 0; REMOVE = 1; REPLACE = 2; + } + Type type = 1; + repeated string communities = 2; +} + +message MedAction { + enum Type { MOD = 0; REPLACE = 1; } + Type type = 1; + int64 value = 2; +} + +message AsPrependAction { + uint32 asn = 1; + uint32 repeat = 2; + bool use_left_most = 3; +} + +message NexthopAction { + string address = 1; + bool self = 2; + bool unchanged = 3; +} + +message LocalPrefAction { uint32 value = 1; } + +message Actions { + RouteAction route_action = 1; + CommunityAction community = 2; + MedAction med = 3; + AsPrependAction as_prepend = 4; + CommunityAction ext_community = 5; + NexthopAction nexthop = 6; + LocalPrefAction local_pref = 7; + CommunityAction large_community = 8; +} + +message Statement { + string name = 1; + Conditions conditions = 2; + Actions actions = 3; +} + +message Policy { + string name = 1; + repeated Statement statements = 2; +} + +enum PolicyDirection { UNKNOWN = 0; IMPORT = 1; EXPORT = 2; } + +message PolicyAssignment { + string name = 1; + PolicyDirection direction = 2; + repeated Policy policies = 4; + RouteAction default_action = 5; +} + +message RoutingPolicy { + repeated DefinedSet defined_sets = 1; + repeated Policy policies = 2; +} + +message Roa { + uint32 asn = 1; + uint32 prefixlen = 2; + uint32 maxlen = 3; + string prefix = 4; + RPKIConf conf = 5; +} + +message Vrf { + string name = 1; + // Route Distinguisher must be one of + // RouteDistinguisherTwoOctetAS, + // RouteDistinguisherIPAddressAS, + // or RouteDistinguisherFourOctetAS. + google.protobuf.Any rd = 2; + // List of the Import Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + repeated google.protobuf.Any import_rt = 3; + // List of the Export Route Targets. Each must be one of + // TwoOctetAsSpecificExtended, + // IPv4AddressSpecificExtended, + // or FourOctetAsSpecificExtended. + repeated google.protobuf.Any export_rt = 4; + uint32 id = 5; +} + +message DefaultRouteDistance { + uint32 external_route_distance = 1; + uint32 internal_route_distance = 2; +} + +message Global { + uint32 asn = 1; + string router_id = 2; + int32 listen_port = 3; + repeated string listen_addresses = 4; + repeated uint32 families = 5; + bool use_multiple_paths = 6; + RouteSelectionOptionsConfig route_selection_options = 7; + DefaultRouteDistance default_route_distance = 8; + Confederation confederation = 9; + GracefulRestart graceful_restart = 10; + ApplyPolicy apply_policy = 11; + string bind_to_device = 12; +} + +message Confederation { + bool enabled = 1; + uint32 identifier = 2; + repeated uint32 member_as_list = 3; +} + +message RPKIConf { + string address = 1; + uint32 remote_port = 2; +} + +message RPKIState { + google.protobuf.Timestamp uptime = 1; + google.protobuf.Timestamp downtime = 2; + bool up = 3; + uint32 record_ipv4 = 4; + uint32 record_ipv6 = 5; + uint32 prefix_ipv4 = 6; + uint32 prefix_ipv6 = 7; + uint32 serial = 8; + int64 received_ipv4 = 9; + int64 received_ipv6 = 10; + int64 serial_notify = 11; + int64 cache_reset = 12; + int64 cache_response = 13; + int64 end_of_data = 14; + int64 error = 15; + int64 serial_query = 16; + int64 reset_query = 17; +} + +message Rpki { + RPKIConf conf = 1; + RPKIState state = 2; +} + +message SetLogLevelRequest { + enum Level { + PANIC = 0; FATAL = 1; ERROR = 2; WARN = 3; INFO = 4; DEBUG = 5; TRACE = 6; + } + Level level = 1; +} diff --git a/vendor/github.com/osrg/gobgp/v3/api/gobgp_grpc.pb.go b/vendor/github.com/osrg/gobgp/v3/api/gobgp_grpc.pb.go new file mode 100644 index 000000000..3d9ac1039 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/api/gobgp_grpc.pb.go @@ -0,0 +1,2436 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.19.1 +// source: gobgp.proto + +package apipb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// GobgpApiClient is the client API for GobgpApi service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GobgpApiClient interface { + StartBgp(ctx context.Context, in *StartBgpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + StopBgp(ctx context.Context, in *StopBgpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + GetBgp(ctx context.Context, in *GetBgpRequest, opts ...grpc.CallOption) (*GetBgpResponse, error) + WatchEvent(ctx context.Context, in *WatchEventRequest, opts ...grpc.CallOption) (GobgpApi_WatchEventClient, error) + AddPeer(ctx context.Context, in *AddPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeletePeer(ctx context.Context, in *DeletePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListPeer(ctx context.Context, in *ListPeerRequest, opts ...grpc.CallOption) (GobgpApi_ListPeerClient, error) + UpdatePeer(ctx context.Context, in *UpdatePeerRequest, opts ...grpc.CallOption) (*UpdatePeerResponse, error) + ResetPeer(ctx context.Context, in *ResetPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ShutdownPeer(ctx context.Context, in *ShutdownPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + EnablePeer(ctx context.Context, in *EnablePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DisablePeer(ctx context.Context, in *DisablePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + AddPeerGroup(ctx context.Context, in *AddPeerGroupRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeletePeerGroup(ctx context.Context, in *DeletePeerGroupRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListPeerGroup(ctx context.Context, in *ListPeerGroupRequest, opts ...grpc.CallOption) (GobgpApi_ListPeerGroupClient, error) + UpdatePeerGroup(ctx context.Context, in *UpdatePeerGroupRequest, opts ...grpc.CallOption) (*UpdatePeerGroupResponse, error) + AddDynamicNeighbor(ctx context.Context, in *AddDynamicNeighborRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListDynamicNeighbor(ctx context.Context, in *ListDynamicNeighborRequest, opts ...grpc.CallOption) (GobgpApi_ListDynamicNeighborClient, error) + DeleteDynamicNeighbor(ctx context.Context, in *DeleteDynamicNeighborRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + AddPath(ctx context.Context, in *AddPathRequest, opts ...grpc.CallOption) (*AddPathResponse, error) + DeletePath(ctx context.Context, in *DeletePathRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListPath(ctx context.Context, in *ListPathRequest, opts ...grpc.CallOption) (GobgpApi_ListPathClient, error) + AddPathStream(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_AddPathStreamClient, error) + GetTable(ctx context.Context, in *GetTableRequest, opts ...grpc.CallOption) (*GetTableResponse, error) + AddVrf(ctx context.Context, in *AddVrfRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteVrf(ctx context.Context, in *DeleteVrfRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListVrf(ctx context.Context, in *ListVrfRequest, opts ...grpc.CallOption) (GobgpApi_ListVrfClient, error) + AddPolicy(ctx context.Context, in *AddPolicyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeletePolicy(ctx context.Context, in *DeletePolicyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListPolicy(ctx context.Context, in *ListPolicyRequest, opts ...grpc.CallOption) (GobgpApi_ListPolicyClient, error) + SetPolicies(ctx context.Context, in *SetPoliciesRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + AddDefinedSet(ctx context.Context, in *AddDefinedSetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteDefinedSet(ctx context.Context, in *DeleteDefinedSetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListDefinedSet(ctx context.Context, in *ListDefinedSetRequest, opts ...grpc.CallOption) (GobgpApi_ListDefinedSetClient, error) + AddStatement(ctx context.Context, in *AddStatementRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteStatement(ctx context.Context, in *DeleteStatementRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListStatement(ctx context.Context, in *ListStatementRequest, opts ...grpc.CallOption) (GobgpApi_ListStatementClient, error) + AddPolicyAssignment(ctx context.Context, in *AddPolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeletePolicyAssignment(ctx context.Context, in *DeletePolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListPolicyAssignment(ctx context.Context, in *ListPolicyAssignmentRequest, opts ...grpc.CallOption) (GobgpApi_ListPolicyAssignmentClient, error) + SetPolicyAssignment(ctx context.Context, in *SetPolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + AddRpki(ctx context.Context, in *AddRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteRpki(ctx context.Context, in *DeleteRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListRpki(ctx context.Context, in *ListRpkiRequest, opts ...grpc.CallOption) (GobgpApi_ListRpkiClient, error) + EnableRpki(ctx context.Context, in *EnableRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DisableRpki(ctx context.Context, in *DisableRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ResetRpki(ctx context.Context, in *ResetRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListRpkiTable(ctx context.Context, in *ListRpkiTableRequest, opts ...grpc.CallOption) (GobgpApi_ListRpkiTableClient, error) + EnableZebra(ctx context.Context, in *EnableZebraRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + EnableMrt(ctx context.Context, in *EnableMrtRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DisableMrt(ctx context.Context, in *DisableMrtRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + AddBmp(ctx context.Context, in *AddBmpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + DeleteBmp(ctx context.Context, in *DeleteBmpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + ListBmp(ctx context.Context, in *ListBmpRequest, opts ...grpc.CallOption) (GobgpApi_ListBmpClient, error) + SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) +} + +type gobgpApiClient struct { + cc grpc.ClientConnInterface +} + +func NewGobgpApiClient(cc grpc.ClientConnInterface) GobgpApiClient { + return &gobgpApiClient{cc} +} + +func (c *gobgpApiClient) StartBgp(ctx context.Context, in *StartBgpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/StartBgp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) StopBgp(ctx context.Context, in *StopBgpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/StopBgp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) GetBgp(ctx context.Context, in *GetBgpRequest, opts ...grpc.CallOption) (*GetBgpResponse, error) { + out := new(GetBgpResponse) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/GetBgp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) WatchEvent(ctx context.Context, in *WatchEventRequest, opts ...grpc.CallOption) (GobgpApi_WatchEventClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[0], "/apipb.GobgpApi/WatchEvent", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiWatchEventClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_WatchEventClient interface { + Recv() (*WatchEventResponse, error) + grpc.ClientStream +} + +type gobgpApiWatchEventClient struct { + grpc.ClientStream +} + +func (x *gobgpApiWatchEventClient) Recv() (*WatchEventResponse, error) { + m := new(WatchEventResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) AddPeer(ctx context.Context, in *AddPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddPeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePeer(ctx context.Context, in *DeletePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeletePeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListPeer(ctx context.Context, in *ListPeerRequest, opts ...grpc.CallOption) (GobgpApi_ListPeerClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[1], "/apipb.GobgpApi/ListPeer", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListPeerClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListPeerClient interface { + Recv() (*ListPeerResponse, error) + grpc.ClientStream +} + +type gobgpApiListPeerClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListPeerClient) Recv() (*ListPeerResponse, error) { + m := new(ListPeerResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) UpdatePeer(ctx context.Context, in *UpdatePeerRequest, opts ...grpc.CallOption) (*UpdatePeerResponse, error) { + out := new(UpdatePeerResponse) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/UpdatePeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ResetPeer(ctx context.Context, in *ResetPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/ResetPeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ShutdownPeer(ctx context.Context, in *ShutdownPeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/ShutdownPeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) EnablePeer(ctx context.Context, in *EnablePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/EnablePeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DisablePeer(ctx context.Context, in *DisablePeerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DisablePeer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddPeerGroup(ctx context.Context, in *AddPeerGroupRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddPeerGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePeerGroup(ctx context.Context, in *DeletePeerGroupRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeletePeerGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListPeerGroup(ctx context.Context, in *ListPeerGroupRequest, opts ...grpc.CallOption) (GobgpApi_ListPeerGroupClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[2], "/apipb.GobgpApi/ListPeerGroup", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListPeerGroupClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListPeerGroupClient interface { + Recv() (*ListPeerGroupResponse, error) + grpc.ClientStream +} + +type gobgpApiListPeerGroupClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListPeerGroupClient) Recv() (*ListPeerGroupResponse, error) { + m := new(ListPeerGroupResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) UpdatePeerGroup(ctx context.Context, in *UpdatePeerGroupRequest, opts ...grpc.CallOption) (*UpdatePeerGroupResponse, error) { + out := new(UpdatePeerGroupResponse) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/UpdatePeerGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddDynamicNeighbor(ctx context.Context, in *AddDynamicNeighborRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddDynamicNeighbor", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListDynamicNeighbor(ctx context.Context, in *ListDynamicNeighborRequest, opts ...grpc.CallOption) (GobgpApi_ListDynamicNeighborClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[3], "/apipb.GobgpApi/ListDynamicNeighbor", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListDynamicNeighborClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListDynamicNeighborClient interface { + Recv() (*ListDynamicNeighborResponse, error) + grpc.ClientStream +} + +type gobgpApiListDynamicNeighborClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListDynamicNeighborClient) Recv() (*ListDynamicNeighborResponse, error) { + m := new(ListDynamicNeighborResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) DeleteDynamicNeighbor(ctx context.Context, in *DeleteDynamicNeighborRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteDynamicNeighbor", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddPath(ctx context.Context, in *AddPathRequest, opts ...grpc.CallOption) (*AddPathResponse, error) { + out := new(AddPathResponse) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddPath", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePath(ctx context.Context, in *DeletePathRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeletePath", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListPath(ctx context.Context, in *ListPathRequest, opts ...grpc.CallOption) (GobgpApi_ListPathClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[4], "/apipb.GobgpApi/ListPath", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListPathClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListPathClient interface { + Recv() (*ListPathResponse, error) + grpc.ClientStream +} + +type gobgpApiListPathClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListPathClient) Recv() (*ListPathResponse, error) { + m := new(ListPathResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) AddPathStream(ctx context.Context, opts ...grpc.CallOption) (GobgpApi_AddPathStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[5], "/apipb.GobgpApi/AddPathStream", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiAddPathStreamClient{stream} + return x, nil +} + +type GobgpApi_AddPathStreamClient interface { + Send(*AddPathStreamRequest) error + CloseAndRecv() (*emptypb.Empty, error) + grpc.ClientStream +} + +type gobgpApiAddPathStreamClient struct { + grpc.ClientStream +} + +func (x *gobgpApiAddPathStreamClient) Send(m *AddPathStreamRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *gobgpApiAddPathStreamClient) CloseAndRecv() (*emptypb.Empty, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(emptypb.Empty) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) GetTable(ctx context.Context, in *GetTableRequest, opts ...grpc.CallOption) (*GetTableResponse, error) { + out := new(GetTableResponse) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/GetTable", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddVrf(ctx context.Context, in *AddVrfRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddVrf", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeleteVrf(ctx context.Context, in *DeleteVrfRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteVrf", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListVrf(ctx context.Context, in *ListVrfRequest, opts ...grpc.CallOption) (GobgpApi_ListVrfClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[6], "/apipb.GobgpApi/ListVrf", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListVrfClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListVrfClient interface { + Recv() (*ListVrfResponse, error) + grpc.ClientStream +} + +type gobgpApiListVrfClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListVrfClient) Recv() (*ListVrfResponse, error) { + m := new(ListVrfResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) AddPolicy(ctx context.Context, in *AddPolicyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePolicy(ctx context.Context, in *DeletePolicyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeletePolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListPolicy(ctx context.Context, in *ListPolicyRequest, opts ...grpc.CallOption) (GobgpApi_ListPolicyClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[7], "/apipb.GobgpApi/ListPolicy", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListPolicyClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListPolicyClient interface { + Recv() (*ListPolicyResponse, error) + grpc.ClientStream +} + +type gobgpApiListPolicyClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListPolicyClient) Recv() (*ListPolicyResponse, error) { + m := new(ListPolicyResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) SetPolicies(ctx context.Context, in *SetPoliciesRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/SetPolicies", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddDefinedSet(ctx context.Context, in *AddDefinedSetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddDefinedSet", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeleteDefinedSet(ctx context.Context, in *DeleteDefinedSetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteDefinedSet", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListDefinedSet(ctx context.Context, in *ListDefinedSetRequest, opts ...grpc.CallOption) (GobgpApi_ListDefinedSetClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[8], "/apipb.GobgpApi/ListDefinedSet", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListDefinedSetClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListDefinedSetClient interface { + Recv() (*ListDefinedSetResponse, error) + grpc.ClientStream +} + +type gobgpApiListDefinedSetClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListDefinedSetClient) Recv() (*ListDefinedSetResponse, error) { + m := new(ListDefinedSetResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) AddStatement(ctx context.Context, in *AddStatementRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddStatement", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeleteStatement(ctx context.Context, in *DeleteStatementRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteStatement", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListStatement(ctx context.Context, in *ListStatementRequest, opts ...grpc.CallOption) (GobgpApi_ListStatementClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[9], "/apipb.GobgpApi/ListStatement", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListStatementClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListStatementClient interface { + Recv() (*ListStatementResponse, error) + grpc.ClientStream +} + +type gobgpApiListStatementClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListStatementClient) Recv() (*ListStatementResponse, error) { + m := new(ListStatementResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) AddPolicyAssignment(ctx context.Context, in *AddPolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddPolicyAssignment", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeletePolicyAssignment(ctx context.Context, in *DeletePolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeletePolicyAssignment", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListPolicyAssignment(ctx context.Context, in *ListPolicyAssignmentRequest, opts ...grpc.CallOption) (GobgpApi_ListPolicyAssignmentClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[10], "/apipb.GobgpApi/ListPolicyAssignment", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListPolicyAssignmentClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListPolicyAssignmentClient interface { + Recv() (*ListPolicyAssignmentResponse, error) + grpc.ClientStream +} + +type gobgpApiListPolicyAssignmentClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListPolicyAssignmentClient) Recv() (*ListPolicyAssignmentResponse, error) { + m := new(ListPolicyAssignmentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) SetPolicyAssignment(ctx context.Context, in *SetPolicyAssignmentRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/SetPolicyAssignment", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddRpki(ctx context.Context, in *AddRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddRpki", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeleteRpki(ctx context.Context, in *DeleteRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteRpki", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListRpki(ctx context.Context, in *ListRpkiRequest, opts ...grpc.CallOption) (GobgpApi_ListRpkiClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[11], "/apipb.GobgpApi/ListRpki", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListRpkiClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListRpkiClient interface { + Recv() (*ListRpkiResponse, error) + grpc.ClientStream +} + +type gobgpApiListRpkiClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListRpkiClient) Recv() (*ListRpkiResponse, error) { + m := new(ListRpkiResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) EnableRpki(ctx context.Context, in *EnableRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/EnableRpki", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DisableRpki(ctx context.Context, in *DisableRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DisableRpki", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ResetRpki(ctx context.Context, in *ResetRpkiRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/ResetRpki", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListRpkiTable(ctx context.Context, in *ListRpkiTableRequest, opts ...grpc.CallOption) (GobgpApi_ListRpkiTableClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[12], "/apipb.GobgpApi/ListRpkiTable", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListRpkiTableClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListRpkiTableClient interface { + Recv() (*ListRpkiTableResponse, error) + grpc.ClientStream +} + +type gobgpApiListRpkiTableClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListRpkiTableClient) Recv() (*ListRpkiTableResponse, error) { + m := new(ListRpkiTableResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) EnableZebra(ctx context.Context, in *EnableZebraRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/EnableZebra", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) EnableMrt(ctx context.Context, in *EnableMrtRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/EnableMrt", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DisableMrt(ctx context.Context, in *DisableMrtRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DisableMrt", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) AddBmp(ctx context.Context, in *AddBmpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/AddBmp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) DeleteBmp(ctx context.Context, in *DeleteBmpRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/DeleteBmp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gobgpApiClient) ListBmp(ctx context.Context, in *ListBmpRequest, opts ...grpc.CallOption) (GobgpApi_ListBmpClient, error) { + stream, err := c.cc.NewStream(ctx, &GobgpApi_ServiceDesc.Streams[13], "/apipb.GobgpApi/ListBmp", opts...) + if err != nil { + return nil, err + } + x := &gobgpApiListBmpClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GobgpApi_ListBmpClient interface { + Recv() (*ListBmpResponse, error) + grpc.ClientStream +} + +type gobgpApiListBmpClient struct { + grpc.ClientStream +} + +func (x *gobgpApiListBmpClient) Recv() (*ListBmpResponse, error) { + m := new(ListBmpResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gobgpApiClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/apipb.GobgpApi/SetLogLevel", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GobgpApiServer is the server API for GobgpApi service. +// All implementations must embed UnimplementedGobgpApiServer +// for forward compatibility +type GobgpApiServer interface { + StartBgp(context.Context, *StartBgpRequest) (*emptypb.Empty, error) + StopBgp(context.Context, *StopBgpRequest) (*emptypb.Empty, error) + GetBgp(context.Context, *GetBgpRequest) (*GetBgpResponse, error) + WatchEvent(*WatchEventRequest, GobgpApi_WatchEventServer) error + AddPeer(context.Context, *AddPeerRequest) (*emptypb.Empty, error) + DeletePeer(context.Context, *DeletePeerRequest) (*emptypb.Empty, error) + ListPeer(*ListPeerRequest, GobgpApi_ListPeerServer) error + UpdatePeer(context.Context, *UpdatePeerRequest) (*UpdatePeerResponse, error) + ResetPeer(context.Context, *ResetPeerRequest) (*emptypb.Empty, error) + ShutdownPeer(context.Context, *ShutdownPeerRequest) (*emptypb.Empty, error) + EnablePeer(context.Context, *EnablePeerRequest) (*emptypb.Empty, error) + DisablePeer(context.Context, *DisablePeerRequest) (*emptypb.Empty, error) + AddPeerGroup(context.Context, *AddPeerGroupRequest) (*emptypb.Empty, error) + DeletePeerGroup(context.Context, *DeletePeerGroupRequest) (*emptypb.Empty, error) + ListPeerGroup(*ListPeerGroupRequest, GobgpApi_ListPeerGroupServer) error + UpdatePeerGroup(context.Context, *UpdatePeerGroupRequest) (*UpdatePeerGroupResponse, error) + AddDynamicNeighbor(context.Context, *AddDynamicNeighborRequest) (*emptypb.Empty, error) + ListDynamicNeighbor(*ListDynamicNeighborRequest, GobgpApi_ListDynamicNeighborServer) error + DeleteDynamicNeighbor(context.Context, *DeleteDynamicNeighborRequest) (*emptypb.Empty, error) + AddPath(context.Context, *AddPathRequest) (*AddPathResponse, error) + DeletePath(context.Context, *DeletePathRequest) (*emptypb.Empty, error) + ListPath(*ListPathRequest, GobgpApi_ListPathServer) error + AddPathStream(GobgpApi_AddPathStreamServer) error + GetTable(context.Context, *GetTableRequest) (*GetTableResponse, error) + AddVrf(context.Context, *AddVrfRequest) (*emptypb.Empty, error) + DeleteVrf(context.Context, *DeleteVrfRequest) (*emptypb.Empty, error) + ListVrf(*ListVrfRequest, GobgpApi_ListVrfServer) error + AddPolicy(context.Context, *AddPolicyRequest) (*emptypb.Empty, error) + DeletePolicy(context.Context, *DeletePolicyRequest) (*emptypb.Empty, error) + ListPolicy(*ListPolicyRequest, GobgpApi_ListPolicyServer) error + SetPolicies(context.Context, *SetPoliciesRequest) (*emptypb.Empty, error) + AddDefinedSet(context.Context, *AddDefinedSetRequest) (*emptypb.Empty, error) + DeleteDefinedSet(context.Context, *DeleteDefinedSetRequest) (*emptypb.Empty, error) + ListDefinedSet(*ListDefinedSetRequest, GobgpApi_ListDefinedSetServer) error + AddStatement(context.Context, *AddStatementRequest) (*emptypb.Empty, error) + DeleteStatement(context.Context, *DeleteStatementRequest) (*emptypb.Empty, error) + ListStatement(*ListStatementRequest, GobgpApi_ListStatementServer) error + AddPolicyAssignment(context.Context, *AddPolicyAssignmentRequest) (*emptypb.Empty, error) + DeletePolicyAssignment(context.Context, *DeletePolicyAssignmentRequest) (*emptypb.Empty, error) + ListPolicyAssignment(*ListPolicyAssignmentRequest, GobgpApi_ListPolicyAssignmentServer) error + SetPolicyAssignment(context.Context, *SetPolicyAssignmentRequest) (*emptypb.Empty, error) + AddRpki(context.Context, *AddRpkiRequest) (*emptypb.Empty, error) + DeleteRpki(context.Context, *DeleteRpkiRequest) (*emptypb.Empty, error) + ListRpki(*ListRpkiRequest, GobgpApi_ListRpkiServer) error + EnableRpki(context.Context, *EnableRpkiRequest) (*emptypb.Empty, error) + DisableRpki(context.Context, *DisableRpkiRequest) (*emptypb.Empty, error) + ResetRpki(context.Context, *ResetRpkiRequest) (*emptypb.Empty, error) + ListRpkiTable(*ListRpkiTableRequest, GobgpApi_ListRpkiTableServer) error + EnableZebra(context.Context, *EnableZebraRequest) (*emptypb.Empty, error) + EnableMrt(context.Context, *EnableMrtRequest) (*emptypb.Empty, error) + DisableMrt(context.Context, *DisableMrtRequest) (*emptypb.Empty, error) + AddBmp(context.Context, *AddBmpRequest) (*emptypb.Empty, error) + DeleteBmp(context.Context, *DeleteBmpRequest) (*emptypb.Empty, error) + ListBmp(*ListBmpRequest, GobgpApi_ListBmpServer) error + SetLogLevel(context.Context, *SetLogLevelRequest) (*emptypb.Empty, error) + mustEmbedUnimplementedGobgpApiServer() +} + +// UnimplementedGobgpApiServer must be embedded to have forward compatible implementations. +type UnimplementedGobgpApiServer struct { +} + +func (UnimplementedGobgpApiServer) StartBgp(context.Context, *StartBgpRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method StartBgp not implemented") +} +func (UnimplementedGobgpApiServer) StopBgp(context.Context, *StopBgpRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method StopBgp not implemented") +} +func (UnimplementedGobgpApiServer) GetBgp(context.Context, *GetBgpRequest) (*GetBgpResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBgp not implemented") +} +func (UnimplementedGobgpApiServer) WatchEvent(*WatchEventRequest, GobgpApi_WatchEventServer) error { + return status.Errorf(codes.Unimplemented, "method WatchEvent not implemented") +} +func (UnimplementedGobgpApiServer) AddPeer(context.Context, *AddPeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPeer not implemented") +} +func (UnimplementedGobgpApiServer) DeletePeer(context.Context, *DeletePeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePeer not implemented") +} +func (UnimplementedGobgpApiServer) ListPeer(*ListPeerRequest, GobgpApi_ListPeerServer) error { + return status.Errorf(codes.Unimplemented, "method ListPeer not implemented") +} +func (UnimplementedGobgpApiServer) UpdatePeer(context.Context, *UpdatePeerRequest) (*UpdatePeerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdatePeer not implemented") +} +func (UnimplementedGobgpApiServer) ResetPeer(context.Context, *ResetPeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResetPeer not implemented") +} +func (UnimplementedGobgpApiServer) ShutdownPeer(context.Context, *ShutdownPeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method ShutdownPeer not implemented") +} +func (UnimplementedGobgpApiServer) EnablePeer(context.Context, *EnablePeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnablePeer not implemented") +} +func (UnimplementedGobgpApiServer) DisablePeer(context.Context, *DisablePeerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisablePeer not implemented") +} +func (UnimplementedGobgpApiServer) AddPeerGroup(context.Context, *AddPeerGroupRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPeerGroup not implemented") +} +func (UnimplementedGobgpApiServer) DeletePeerGroup(context.Context, *DeletePeerGroupRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePeerGroup not implemented") +} +func (UnimplementedGobgpApiServer) ListPeerGroup(*ListPeerGroupRequest, GobgpApi_ListPeerGroupServer) error { + return status.Errorf(codes.Unimplemented, "method ListPeerGroup not implemented") +} +func (UnimplementedGobgpApiServer) UpdatePeerGroup(context.Context, *UpdatePeerGroupRequest) (*UpdatePeerGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdatePeerGroup not implemented") +} +func (UnimplementedGobgpApiServer) AddDynamicNeighbor(context.Context, *AddDynamicNeighborRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddDynamicNeighbor not implemented") +} +func (UnimplementedGobgpApiServer) ListDynamicNeighbor(*ListDynamicNeighborRequest, GobgpApi_ListDynamicNeighborServer) error { + return status.Errorf(codes.Unimplemented, "method ListDynamicNeighbor not implemented") +} +func (UnimplementedGobgpApiServer) DeleteDynamicNeighbor(context.Context, *DeleteDynamicNeighborRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteDynamicNeighbor not implemented") +} +func (UnimplementedGobgpApiServer) AddPath(context.Context, *AddPathRequest) (*AddPathResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPath not implemented") +} +func (UnimplementedGobgpApiServer) DeletePath(context.Context, *DeletePathRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePath not implemented") +} +func (UnimplementedGobgpApiServer) ListPath(*ListPathRequest, GobgpApi_ListPathServer) error { + return status.Errorf(codes.Unimplemented, "method ListPath not implemented") +} +func (UnimplementedGobgpApiServer) AddPathStream(GobgpApi_AddPathStreamServer) error { + return status.Errorf(codes.Unimplemented, "method AddPathStream not implemented") +} +func (UnimplementedGobgpApiServer) GetTable(context.Context, *GetTableRequest) (*GetTableResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTable not implemented") +} +func (UnimplementedGobgpApiServer) AddVrf(context.Context, *AddVrfRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddVrf not implemented") +} +func (UnimplementedGobgpApiServer) DeleteVrf(context.Context, *DeleteVrfRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteVrf not implemented") +} +func (UnimplementedGobgpApiServer) ListVrf(*ListVrfRequest, GobgpApi_ListVrfServer) error { + return status.Errorf(codes.Unimplemented, "method ListVrf not implemented") +} +func (UnimplementedGobgpApiServer) AddPolicy(context.Context, *AddPolicyRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPolicy not implemented") +} +func (UnimplementedGobgpApiServer) DeletePolicy(context.Context, *DeletePolicyRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePolicy not implemented") +} +func (UnimplementedGobgpApiServer) ListPolicy(*ListPolicyRequest, GobgpApi_ListPolicyServer) error { + return status.Errorf(codes.Unimplemented, "method ListPolicy not implemented") +} +func (UnimplementedGobgpApiServer) SetPolicies(context.Context, *SetPoliciesRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetPolicies not implemented") +} +func (UnimplementedGobgpApiServer) AddDefinedSet(context.Context, *AddDefinedSetRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddDefinedSet not implemented") +} +func (UnimplementedGobgpApiServer) DeleteDefinedSet(context.Context, *DeleteDefinedSetRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteDefinedSet not implemented") +} +func (UnimplementedGobgpApiServer) ListDefinedSet(*ListDefinedSetRequest, GobgpApi_ListDefinedSetServer) error { + return status.Errorf(codes.Unimplemented, "method ListDefinedSet not implemented") +} +func (UnimplementedGobgpApiServer) AddStatement(context.Context, *AddStatementRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddStatement not implemented") +} +func (UnimplementedGobgpApiServer) DeleteStatement(context.Context, *DeleteStatementRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteStatement not implemented") +} +func (UnimplementedGobgpApiServer) ListStatement(*ListStatementRequest, GobgpApi_ListStatementServer) error { + return status.Errorf(codes.Unimplemented, "method ListStatement not implemented") +} +func (UnimplementedGobgpApiServer) AddPolicyAssignment(context.Context, *AddPolicyAssignmentRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPolicyAssignment not implemented") +} +func (UnimplementedGobgpApiServer) DeletePolicyAssignment(context.Context, *DeletePolicyAssignmentRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeletePolicyAssignment not implemented") +} +func (UnimplementedGobgpApiServer) ListPolicyAssignment(*ListPolicyAssignmentRequest, GobgpApi_ListPolicyAssignmentServer) error { + return status.Errorf(codes.Unimplemented, "method ListPolicyAssignment not implemented") +} +func (UnimplementedGobgpApiServer) SetPolicyAssignment(context.Context, *SetPolicyAssignmentRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetPolicyAssignment not implemented") +} +func (UnimplementedGobgpApiServer) AddRpki(context.Context, *AddRpkiRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddRpki not implemented") +} +func (UnimplementedGobgpApiServer) DeleteRpki(context.Context, *DeleteRpkiRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteRpki not implemented") +} +func (UnimplementedGobgpApiServer) ListRpki(*ListRpkiRequest, GobgpApi_ListRpkiServer) error { + return status.Errorf(codes.Unimplemented, "method ListRpki not implemented") +} +func (UnimplementedGobgpApiServer) EnableRpki(context.Context, *EnableRpkiRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableRpki not implemented") +} +func (UnimplementedGobgpApiServer) DisableRpki(context.Context, *DisableRpkiRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableRpki not implemented") +} +func (UnimplementedGobgpApiServer) ResetRpki(context.Context, *ResetRpkiRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResetRpki not implemented") +} +func (UnimplementedGobgpApiServer) ListRpkiTable(*ListRpkiTableRequest, GobgpApi_ListRpkiTableServer) error { + return status.Errorf(codes.Unimplemented, "method ListRpkiTable not implemented") +} +func (UnimplementedGobgpApiServer) EnableZebra(context.Context, *EnableZebraRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableZebra not implemented") +} +func (UnimplementedGobgpApiServer) EnableMrt(context.Context, *EnableMrtRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableMrt not implemented") +} +func (UnimplementedGobgpApiServer) DisableMrt(context.Context, *DisableMrtRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableMrt not implemented") +} +func (UnimplementedGobgpApiServer) AddBmp(context.Context, *AddBmpRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddBmp not implemented") +} +func (UnimplementedGobgpApiServer) DeleteBmp(context.Context, *DeleteBmpRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteBmp not implemented") +} +func (UnimplementedGobgpApiServer) ListBmp(*ListBmpRequest, GobgpApi_ListBmpServer) error { + return status.Errorf(codes.Unimplemented, "method ListBmp not implemented") +} +func (UnimplementedGobgpApiServer) SetLogLevel(context.Context, *SetLogLevelRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetLogLevel not implemented") +} +func (UnimplementedGobgpApiServer) mustEmbedUnimplementedGobgpApiServer() {} + +// UnsafeGobgpApiServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GobgpApiServer will +// result in compilation errors. +type UnsafeGobgpApiServer interface { + mustEmbedUnimplementedGobgpApiServer() +} + +func RegisterGobgpApiServer(s grpc.ServiceRegistrar, srv GobgpApiServer) { + s.RegisterService(&GobgpApi_ServiceDesc, srv) +} + +func _GobgpApi_StartBgp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StartBgpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).StartBgp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/StartBgp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).StartBgp(ctx, req.(*StartBgpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_StopBgp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StopBgpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).StopBgp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/StopBgp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).StopBgp(ctx, req.(*StopBgpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_GetBgp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetBgpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).GetBgp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/GetBgp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).GetBgp(ctx, req.(*GetBgpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_WatchEvent_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(WatchEventRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).WatchEvent(m, &gobgpApiWatchEventServer{stream}) +} + +type GobgpApi_WatchEventServer interface { + Send(*WatchEventResponse) error + grpc.ServerStream +} + +type gobgpApiWatchEventServer struct { + grpc.ServerStream +} + +func (x *gobgpApiWatchEventServer) Send(m *WatchEventResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_AddPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddPeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPeer(ctx, req.(*AddPeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeletePeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePeer(ctx, req.(*DeletePeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListPeer_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListPeerRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListPeer(m, &gobgpApiListPeerServer{stream}) +} + +type GobgpApi_ListPeerServer interface { + Send(*ListPeerResponse) error + grpc.ServerStream +} + +type gobgpApiListPeerServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListPeerServer) Send(m *ListPeerResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_UpdatePeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).UpdatePeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/UpdatePeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).UpdatePeer(ctx, req.(*UpdatePeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ResetPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResetPeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).ResetPeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/ResetPeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).ResetPeer(ctx, req.(*ResetPeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ShutdownPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ShutdownPeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).ShutdownPeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/ShutdownPeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).ShutdownPeer(ctx, req.(*ShutdownPeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_EnablePeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnablePeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).EnablePeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/EnablePeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).EnablePeer(ctx, req.(*EnablePeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DisablePeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DisablePeerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DisablePeer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DisablePeer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DisablePeer(ctx, req.(*DisablePeerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddPeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddPeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPeerGroup(ctx, req.(*AddPeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeletePeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePeerGroup(ctx, req.(*DeletePeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListPeerGroup_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListPeerGroupRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListPeerGroup(m, &gobgpApiListPeerGroupServer{stream}) +} + +type GobgpApi_ListPeerGroupServer interface { + Send(*ListPeerGroupResponse) error + grpc.ServerStream +} + +type gobgpApiListPeerGroupServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListPeerGroupServer) Send(m *ListPeerGroupResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_UpdatePeerGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdatePeerGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).UpdatePeerGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/UpdatePeerGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).UpdatePeerGroup(ctx, req.(*UpdatePeerGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddDynamicNeighbor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDynamicNeighborRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddDynamicNeighbor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddDynamicNeighbor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddDynamicNeighbor(ctx, req.(*AddDynamicNeighborRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListDynamicNeighbor_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListDynamicNeighborRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListDynamicNeighbor(m, &gobgpApiListDynamicNeighborServer{stream}) +} + +type GobgpApi_ListDynamicNeighborServer interface { + Send(*ListDynamicNeighborResponse) error + grpc.ServerStream +} + +type gobgpApiListDynamicNeighborServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListDynamicNeighborServer) Send(m *ListDynamicNeighborResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_DeleteDynamicNeighbor_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteDynamicNeighborRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteDynamicNeighbor(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteDynamicNeighbor", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteDynamicNeighbor(ctx, req.(*DeleteDynamicNeighborRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPathRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPath(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddPath", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPath(ctx, req.(*AddPathRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePathRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePath(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeletePath", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePath(ctx, req.(*DeletePathRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListPath_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListPathRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListPath(m, &gobgpApiListPathServer{stream}) +} + +type GobgpApi_ListPathServer interface { + Send(*ListPathResponse) error + grpc.ServerStream +} + +type gobgpApiListPathServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListPathServer) Send(m *ListPathResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_AddPathStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GobgpApiServer).AddPathStream(&gobgpApiAddPathStreamServer{stream}) +} + +type GobgpApi_AddPathStreamServer interface { + SendAndClose(*emptypb.Empty) error + Recv() (*AddPathStreamRequest, error) + grpc.ServerStream +} + +type gobgpApiAddPathStreamServer struct { + grpc.ServerStream +} + +func (x *gobgpApiAddPathStreamServer) SendAndClose(m *emptypb.Empty) error { + return x.ServerStream.SendMsg(m) +} + +func (x *gobgpApiAddPathStreamServer) Recv() (*AddPathStreamRequest, error) { + m := new(AddPathStreamRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _GobgpApi_GetTable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTableRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).GetTable(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/GetTable", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).GetTable(ctx, req.(*GetTableRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddVrf_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddVrfRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddVrf(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddVrf", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddVrf(ctx, req.(*AddVrfRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeleteVrf_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteVrfRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteVrf(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteVrf", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteVrf(ctx, req.(*DeleteVrfRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListVrf_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListVrfRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListVrf(m, &gobgpApiListVrfServer{stream}) +} + +type GobgpApi_ListVrfServer interface { + Send(*ListVrfResponse) error + grpc.ServerStream +} + +type gobgpApiListVrfServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListVrfServer) Send(m *ListVrfResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_AddPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPolicy(ctx, req.(*AddPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeletePolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePolicy(ctx, req.(*DeletePolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListPolicy_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListPolicyRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListPolicy(m, &gobgpApiListPolicyServer{stream}) +} + +type GobgpApi_ListPolicyServer interface { + Send(*ListPolicyResponse) error + grpc.ServerStream +} + +type gobgpApiListPolicyServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListPolicyServer) Send(m *ListPolicyResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_SetPolicies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetPoliciesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).SetPolicies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/SetPolicies", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).SetPolicies(ctx, req.(*SetPoliciesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddDefinedSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDefinedSetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddDefinedSet(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddDefinedSet", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddDefinedSet(ctx, req.(*AddDefinedSetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeleteDefinedSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteDefinedSetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteDefinedSet(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteDefinedSet", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteDefinedSet(ctx, req.(*DeleteDefinedSetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListDefinedSet_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListDefinedSetRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListDefinedSet(m, &gobgpApiListDefinedSetServer{stream}) +} + +type GobgpApi_ListDefinedSetServer interface { + Send(*ListDefinedSetResponse) error + grpc.ServerStream +} + +type gobgpApiListDefinedSetServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListDefinedSetServer) Send(m *ListDefinedSetResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_AddStatement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddStatementRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddStatement(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddStatement", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddStatement(ctx, req.(*AddStatementRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeleteStatement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteStatementRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteStatement(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteStatement", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteStatement(ctx, req.(*DeleteStatementRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListStatement_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListStatementRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListStatement(m, &gobgpApiListStatementServer{stream}) +} + +type GobgpApi_ListStatementServer interface { + Send(*ListStatementResponse) error + grpc.ServerStream +} + +type gobgpApiListStatementServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListStatementServer) Send(m *ListStatementResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_AddPolicyAssignment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPolicyAssignmentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddPolicyAssignment(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddPolicyAssignment", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddPolicyAssignment(ctx, req.(*AddPolicyAssignmentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeletePolicyAssignment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeletePolicyAssignmentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeletePolicyAssignment(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeletePolicyAssignment", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeletePolicyAssignment(ctx, req.(*DeletePolicyAssignmentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListPolicyAssignment_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListPolicyAssignmentRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListPolicyAssignment(m, &gobgpApiListPolicyAssignmentServer{stream}) +} + +type GobgpApi_ListPolicyAssignmentServer interface { + Send(*ListPolicyAssignmentResponse) error + grpc.ServerStream +} + +type gobgpApiListPolicyAssignmentServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListPolicyAssignmentServer) Send(m *ListPolicyAssignmentResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_SetPolicyAssignment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetPolicyAssignmentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).SetPolicyAssignment(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/SetPolicyAssignment", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).SetPolicyAssignment(ctx, req.(*SetPolicyAssignmentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddRpki_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddRpkiRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddRpki(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddRpki", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddRpki(ctx, req.(*AddRpkiRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeleteRpki_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRpkiRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteRpki(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteRpki", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteRpki(ctx, req.(*DeleteRpkiRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListRpki_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListRpkiRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListRpki(m, &gobgpApiListRpkiServer{stream}) +} + +type GobgpApi_ListRpkiServer interface { + Send(*ListRpkiResponse) error + grpc.ServerStream +} + +type gobgpApiListRpkiServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListRpkiServer) Send(m *ListRpkiResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_EnableRpki_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnableRpkiRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).EnableRpki(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/EnableRpki", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).EnableRpki(ctx, req.(*EnableRpkiRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DisableRpki_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DisableRpkiRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DisableRpki(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DisableRpki", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DisableRpki(ctx, req.(*DisableRpkiRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ResetRpki_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResetRpkiRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).ResetRpki(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/ResetRpki", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).ResetRpki(ctx, req.(*ResetRpkiRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListRpkiTable_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListRpkiTableRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListRpkiTable(m, &gobgpApiListRpkiTableServer{stream}) +} + +type GobgpApi_ListRpkiTableServer interface { + Send(*ListRpkiTableResponse) error + grpc.ServerStream +} + +type gobgpApiListRpkiTableServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListRpkiTableServer) Send(m *ListRpkiTableResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_EnableZebra_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnableZebraRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).EnableZebra(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/EnableZebra", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).EnableZebra(ctx, req.(*EnableZebraRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_EnableMrt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnableMrtRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).EnableMrt(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/EnableMrt", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).EnableMrt(ctx, req.(*EnableMrtRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DisableMrt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DisableMrtRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DisableMrt(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DisableMrt", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DisableMrt(ctx, req.(*DisableMrtRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_AddBmp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddBmpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).AddBmp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/AddBmp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).AddBmp(ctx, req.(*AddBmpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_DeleteBmp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteBmpRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).DeleteBmp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/DeleteBmp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).DeleteBmp(ctx, req.(*DeleteBmpRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GobgpApi_ListBmp_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListBmpRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GobgpApiServer).ListBmp(m, &gobgpApiListBmpServer{stream}) +} + +type GobgpApi_ListBmpServer interface { + Send(*ListBmpResponse) error + grpc.ServerStream +} + +type gobgpApiListBmpServer struct { + grpc.ServerStream +} + +func (x *gobgpApiListBmpServer) Send(m *ListBmpResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _GobgpApi_SetLogLevel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetLogLevelRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GobgpApiServer).SetLogLevel(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/apipb.GobgpApi/SetLogLevel", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GobgpApiServer).SetLogLevel(ctx, req.(*SetLogLevelRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// GobgpApi_ServiceDesc is the grpc.ServiceDesc for GobgpApi service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var GobgpApi_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "apipb.GobgpApi", + HandlerType: (*GobgpApiServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "StartBgp", + Handler: _GobgpApi_StartBgp_Handler, + }, + { + MethodName: "StopBgp", + Handler: _GobgpApi_StopBgp_Handler, + }, + { + MethodName: "GetBgp", + Handler: _GobgpApi_GetBgp_Handler, + }, + { + MethodName: "AddPeer", + Handler: _GobgpApi_AddPeer_Handler, + }, + { + MethodName: "DeletePeer", + Handler: _GobgpApi_DeletePeer_Handler, + }, + { + MethodName: "UpdatePeer", + Handler: _GobgpApi_UpdatePeer_Handler, + }, + { + MethodName: "ResetPeer", + Handler: _GobgpApi_ResetPeer_Handler, + }, + { + MethodName: "ShutdownPeer", + Handler: _GobgpApi_ShutdownPeer_Handler, + }, + { + MethodName: "EnablePeer", + Handler: _GobgpApi_EnablePeer_Handler, + }, + { + MethodName: "DisablePeer", + Handler: _GobgpApi_DisablePeer_Handler, + }, + { + MethodName: "AddPeerGroup", + Handler: _GobgpApi_AddPeerGroup_Handler, + }, + { + MethodName: "DeletePeerGroup", + Handler: _GobgpApi_DeletePeerGroup_Handler, + }, + { + MethodName: "UpdatePeerGroup", + Handler: _GobgpApi_UpdatePeerGroup_Handler, + }, + { + MethodName: "AddDynamicNeighbor", + Handler: _GobgpApi_AddDynamicNeighbor_Handler, + }, + { + MethodName: "DeleteDynamicNeighbor", + Handler: _GobgpApi_DeleteDynamicNeighbor_Handler, + }, + { + MethodName: "AddPath", + Handler: _GobgpApi_AddPath_Handler, + }, + { + MethodName: "DeletePath", + Handler: _GobgpApi_DeletePath_Handler, + }, + { + MethodName: "GetTable", + Handler: _GobgpApi_GetTable_Handler, + }, + { + MethodName: "AddVrf", + Handler: _GobgpApi_AddVrf_Handler, + }, + { + MethodName: "DeleteVrf", + Handler: _GobgpApi_DeleteVrf_Handler, + }, + { + MethodName: "AddPolicy", + Handler: _GobgpApi_AddPolicy_Handler, + }, + { + MethodName: "DeletePolicy", + Handler: _GobgpApi_DeletePolicy_Handler, + }, + { + MethodName: "SetPolicies", + Handler: _GobgpApi_SetPolicies_Handler, + }, + { + MethodName: "AddDefinedSet", + Handler: _GobgpApi_AddDefinedSet_Handler, + }, + { + MethodName: "DeleteDefinedSet", + Handler: _GobgpApi_DeleteDefinedSet_Handler, + }, + { + MethodName: "AddStatement", + Handler: _GobgpApi_AddStatement_Handler, + }, + { + MethodName: "DeleteStatement", + Handler: _GobgpApi_DeleteStatement_Handler, + }, + { + MethodName: "AddPolicyAssignment", + Handler: _GobgpApi_AddPolicyAssignment_Handler, + }, + { + MethodName: "DeletePolicyAssignment", + Handler: _GobgpApi_DeletePolicyAssignment_Handler, + }, + { + MethodName: "SetPolicyAssignment", + Handler: _GobgpApi_SetPolicyAssignment_Handler, + }, + { + MethodName: "AddRpki", + Handler: _GobgpApi_AddRpki_Handler, + }, + { + MethodName: "DeleteRpki", + Handler: _GobgpApi_DeleteRpki_Handler, + }, + { + MethodName: "EnableRpki", + Handler: _GobgpApi_EnableRpki_Handler, + }, + { + MethodName: "DisableRpki", + Handler: _GobgpApi_DisableRpki_Handler, + }, + { + MethodName: "ResetRpki", + Handler: _GobgpApi_ResetRpki_Handler, + }, + { + MethodName: "EnableZebra", + Handler: _GobgpApi_EnableZebra_Handler, + }, + { + MethodName: "EnableMrt", + Handler: _GobgpApi_EnableMrt_Handler, + }, + { + MethodName: "DisableMrt", + Handler: _GobgpApi_DisableMrt_Handler, + }, + { + MethodName: "AddBmp", + Handler: _GobgpApi_AddBmp_Handler, + }, + { + MethodName: "DeleteBmp", + Handler: _GobgpApi_DeleteBmp_Handler, + }, + { + MethodName: "SetLogLevel", + Handler: _GobgpApi_SetLogLevel_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "WatchEvent", + Handler: _GobgpApi_WatchEvent_Handler, + ServerStreams: true, + }, + { + StreamName: "ListPeer", + Handler: _GobgpApi_ListPeer_Handler, + ServerStreams: true, + }, + { + StreamName: "ListPeerGroup", + Handler: _GobgpApi_ListPeerGroup_Handler, + ServerStreams: true, + }, + { + StreamName: "ListDynamicNeighbor", + Handler: _GobgpApi_ListDynamicNeighbor_Handler, + ServerStreams: true, + }, + { + StreamName: "ListPath", + Handler: _GobgpApi_ListPath_Handler, + ServerStreams: true, + }, + { + StreamName: "AddPathStream", + Handler: _GobgpApi_AddPathStream_Handler, + ClientStreams: true, + }, + { + StreamName: "ListVrf", + Handler: _GobgpApi_ListVrf_Handler, + ServerStreams: true, + }, + { + StreamName: "ListPolicy", + Handler: _GobgpApi_ListPolicy_Handler, + ServerStreams: true, + }, + { + StreamName: "ListDefinedSet", + Handler: _GobgpApi_ListDefinedSet_Handler, + ServerStreams: true, + }, + { + StreamName: "ListStatement", + Handler: _GobgpApi_ListStatement_Handler, + ServerStreams: true, + }, + { + StreamName: "ListPolicyAssignment", + Handler: _GobgpApi_ListPolicyAssignment_Handler, + ServerStreams: true, + }, + { + StreamName: "ListRpki", + Handler: _GobgpApi_ListRpki_Handler, + ServerStreams: true, + }, + { + StreamName: "ListRpkiTable", + Handler: _GobgpApi_ListRpkiTable_Handler, + ServerStreams: true, + }, + { + StreamName: "ListBmp", + Handler: _GobgpApi_ListBmp_Handler, + ServerStreams: true, + }, + }, + Metadata: "gobgp.proto", +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/bgp_configs.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/bgp_configs.go new file mode 100644 index 000000000..8f000fa64 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/bgp_configs.go @@ -0,0 +1,6423 @@ +// DO NOT EDIT +// generated by pyang using OpenConfig https://github.com/openconfig/public +// +// Copyright (C) 2014-2019 Nippon Telegraph and Telephone Corporation. +// +// 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. + +// Code generated by pyang. DO NOT EDIT. + +package config + +import ( + "fmt" + + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +func mapkey(index int, name string) string { + if name != "" { + return name + } + return fmt.Sprintf("%v", index) +} + +// typedef for typedef openconfig-types:std-regexp. +type StdRegexp string + +// typedef for typedef openconfig-types:percentage. +type Percentage uint8 + +// typedef for typedef bgp-types:rr-cluster-id-type. +type RrClusterIdType string + +// typedef for identity bgp-types:remove-private-as-option. +// set of options for configuring how private AS path numbers +// are removed from advertisements. +type RemovePrivateAsOption string + +const ( + REMOVE_PRIVATE_AS_OPTION_ALL RemovePrivateAsOption = "all" + REMOVE_PRIVATE_AS_OPTION_REPLACE RemovePrivateAsOption = "replace" +) + +var RemovePrivateAsOptionToIntMap = map[RemovePrivateAsOption]int{ + REMOVE_PRIVATE_AS_OPTION_ALL: 0, + REMOVE_PRIVATE_AS_OPTION_REPLACE: 1, +} + +var IntToRemovePrivateAsOptionMap = map[int]RemovePrivateAsOption{ + 0: REMOVE_PRIVATE_AS_OPTION_ALL, + 1: REMOVE_PRIVATE_AS_OPTION_REPLACE, +} + +func (v RemovePrivateAsOption) Validate() error { + if _, ok := RemovePrivateAsOptionToIntMap[v]; !ok { + return fmt.Errorf("invalid RemovePrivateAsOption: %s", v) + } + return nil +} + +func (v RemovePrivateAsOption) ToInt() int { + i, ok := RemovePrivateAsOptionToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for typedef bgp-types:bgp-community-regexp-type. +type BgpCommunityRegexpType StdRegexp + +// typedef for identity bgp-types:community-type. +// type describing variations of community attributes: +// STANDARD: standard BGP community [rfc1997] +// EXTENDED: extended BGP community [rfc4360] +// BOTH: both standard and extended community. +type CommunityType string + +const ( + COMMUNITY_TYPE_STANDARD CommunityType = "standard" + COMMUNITY_TYPE_EXTENDED CommunityType = "extended" + COMMUNITY_TYPE_BOTH CommunityType = "both" + COMMUNITY_TYPE_NONE CommunityType = "none" +) + +var CommunityTypeToIntMap = map[CommunityType]int{ + COMMUNITY_TYPE_STANDARD: 0, + COMMUNITY_TYPE_EXTENDED: 1, + COMMUNITY_TYPE_BOTH: 2, + COMMUNITY_TYPE_NONE: 3, +} + +var IntToCommunityTypeMap = map[int]CommunityType{ + 0: COMMUNITY_TYPE_STANDARD, + 1: COMMUNITY_TYPE_EXTENDED, + 2: COMMUNITY_TYPE_BOTH, + 3: COMMUNITY_TYPE_NONE, +} + +func (v CommunityType) Validate() error { + if _, ok := CommunityTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid CommunityType: %s", v) + } + return nil +} + +func (v CommunityType) ToInt() int { + i, ok := CommunityTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for typedef bgp-types:bgp-ext-community-type. +type BgpExtCommunityType string + +// typedef for typedef bgp-types:bgp-std-community-type. +type BgpStdCommunityType string + +// typedef for identity bgp-types:peer-type. +// labels a peer or peer group as explicitly internal or +// external. +type PeerType string + +const ( + PEER_TYPE_INTERNAL PeerType = "internal" + PEER_TYPE_EXTERNAL PeerType = "external" +) + +var PeerTypeToIntMap = map[PeerType]int{ + PEER_TYPE_INTERNAL: 0, + PEER_TYPE_EXTERNAL: 1, +} + +var IntToPeerTypeMap = map[int]PeerType{ + 0: PEER_TYPE_INTERNAL, + 1: PEER_TYPE_EXTERNAL, +} + +func (v PeerType) Validate() error { + if _, ok := PeerTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid PeerType: %s", v) + } + return nil +} + +func (v PeerType) ToInt() int { + i, ok := PeerTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp-types:bgp-session-direction. +// Type to describe the direction of NLRI transmission. +type BgpSessionDirection string + +const ( + BGP_SESSION_DIRECTION_INBOUND BgpSessionDirection = "inbound" + BGP_SESSION_DIRECTION_OUTBOUND BgpSessionDirection = "outbound" +) + +var BgpSessionDirectionToIntMap = map[BgpSessionDirection]int{ + BGP_SESSION_DIRECTION_INBOUND: 0, + BGP_SESSION_DIRECTION_OUTBOUND: 1, +} + +var IntToBgpSessionDirectionMap = map[int]BgpSessionDirection{ + 0: BGP_SESSION_DIRECTION_INBOUND, + 1: BGP_SESSION_DIRECTION_OUTBOUND, +} + +func (v BgpSessionDirection) Validate() error { + if _, ok := BgpSessionDirectionToIntMap[v]; !ok { + return fmt.Errorf("invalid BgpSessionDirection: %s", v) + } + return nil +} + +func (v BgpSessionDirection) ToInt() int { + i, ok := BgpSessionDirectionToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp-types:bgp-origin-attr-type. +// Type definition for standard BGP origin attribute. +type BgpOriginAttrType string + +const ( + BGP_ORIGIN_ATTR_TYPE_IGP BgpOriginAttrType = "igp" + BGP_ORIGIN_ATTR_TYPE_EGP BgpOriginAttrType = "egp" + BGP_ORIGIN_ATTR_TYPE_INCOMPLETE BgpOriginAttrType = "incomplete" +) + +var BgpOriginAttrTypeToIntMap = map[BgpOriginAttrType]int{ + BGP_ORIGIN_ATTR_TYPE_IGP: 0, + BGP_ORIGIN_ATTR_TYPE_EGP: 1, + BGP_ORIGIN_ATTR_TYPE_INCOMPLETE: 2, +} + +var IntToBgpOriginAttrTypeMap = map[int]BgpOriginAttrType{ + 0: BGP_ORIGIN_ATTR_TYPE_IGP, + 1: BGP_ORIGIN_ATTR_TYPE_EGP, + 2: BGP_ORIGIN_ATTR_TYPE_INCOMPLETE, +} + +func (v BgpOriginAttrType) Validate() error { + if _, ok := BgpOriginAttrTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid BgpOriginAttrType: %s", v) + } + return nil +} + +func (v BgpOriginAttrType) ToInt() int { + i, ok := BgpOriginAttrTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp-types:afi-safi-type. +// Base identity type for AFI,SAFI tuples for BGP-4. +type AfiSafiType string + +const ( + AFI_SAFI_TYPE_IPV4_UNICAST AfiSafiType = "ipv4-unicast" + AFI_SAFI_TYPE_IPV6_UNICAST AfiSafiType = "ipv6-unicast" + AFI_SAFI_TYPE_IPV4_LABELLED_UNICAST AfiSafiType = "ipv4-labelled-unicast" + AFI_SAFI_TYPE_IPV6_LABELLED_UNICAST AfiSafiType = "ipv6-labelled-unicast" + AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST AfiSafiType = "l3vpn-ipv4-unicast" + AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST AfiSafiType = "l3vpn-ipv6-unicast" + AFI_SAFI_TYPE_L3VPN_IPV4_MULTICAST AfiSafiType = "l3vpn-ipv4-multicast" + AFI_SAFI_TYPE_L3VPN_IPV6_MULTICAST AfiSafiType = "l3vpn-ipv6-multicast" + AFI_SAFI_TYPE_L2VPN_VPLS AfiSafiType = "l2vpn-vpls" + AFI_SAFI_TYPE_L2VPN_EVPN AfiSafiType = "l2vpn-evpn" + AFI_SAFI_TYPE_IPV4_MULTICAST AfiSafiType = "ipv4-multicast" + AFI_SAFI_TYPE_IPV6_MULTICAST AfiSafiType = "ipv6-multicast" + AFI_SAFI_TYPE_RTC AfiSafiType = "rtc" + AFI_SAFI_TYPE_IPV4_ENCAP AfiSafiType = "ipv4-encap" + AFI_SAFI_TYPE_IPV6_ENCAP AfiSafiType = "ipv6-encap" + AFI_SAFI_TYPE_IPV4_FLOWSPEC AfiSafiType = "ipv4-flowspec" + AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC AfiSafiType = "l3vpn-ipv4-flowspec" + AFI_SAFI_TYPE_IPV6_FLOWSPEC AfiSafiType = "ipv6-flowspec" + AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC AfiSafiType = "l3vpn-ipv6-flowspec" + AFI_SAFI_TYPE_L2VPN_FLOWSPEC AfiSafiType = "l2vpn-flowspec" + AFI_SAFI_TYPE_IPV4_SRPOLICY AfiSafiType = "ipv4-srpolicy" + AFI_SAFI_TYPE_IPV6_SRPOLICY AfiSafiType = "ipv6-srpolicy" + AFI_SAFI_TYPE_OPAQUE AfiSafiType = "opaque" + AFI_SAFI_TYPE_LS AfiSafiType = "ls" + AFI_SAFI_TYPE_IPV4_MUP AfiSafiType = "ipv4-mup" + AFI_SAFI_TYPE_IPV6_MUP AfiSafiType = "ipv6-mup" +) + +var AfiSafiTypeToIntMap = map[AfiSafiType]int{ + AFI_SAFI_TYPE_IPV4_UNICAST: 0, + AFI_SAFI_TYPE_IPV6_UNICAST: 1, + AFI_SAFI_TYPE_IPV4_LABELLED_UNICAST: 2, + AFI_SAFI_TYPE_IPV6_LABELLED_UNICAST: 3, + AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST: 4, + AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST: 5, + AFI_SAFI_TYPE_L3VPN_IPV4_MULTICAST: 6, + AFI_SAFI_TYPE_L3VPN_IPV6_MULTICAST: 7, + AFI_SAFI_TYPE_L2VPN_VPLS: 8, + AFI_SAFI_TYPE_L2VPN_EVPN: 9, + AFI_SAFI_TYPE_IPV4_MULTICAST: 10, + AFI_SAFI_TYPE_IPV6_MULTICAST: 11, + AFI_SAFI_TYPE_RTC: 12, + AFI_SAFI_TYPE_IPV4_ENCAP: 13, + AFI_SAFI_TYPE_IPV6_ENCAP: 14, + AFI_SAFI_TYPE_IPV4_FLOWSPEC: 15, + AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC: 16, + AFI_SAFI_TYPE_IPV6_FLOWSPEC: 17, + AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC: 18, + AFI_SAFI_TYPE_L2VPN_FLOWSPEC: 19, + AFI_SAFI_TYPE_IPV4_SRPOLICY: 20, + AFI_SAFI_TYPE_IPV6_SRPOLICY: 21, + AFI_SAFI_TYPE_OPAQUE: 22, + AFI_SAFI_TYPE_LS: 23, + AFI_SAFI_TYPE_IPV4_MUP: 24, + AFI_SAFI_TYPE_IPV6_MUP: 25, +} + +var IntToAfiSafiTypeMap = map[int]AfiSafiType{ + 0: AFI_SAFI_TYPE_IPV4_UNICAST, + 1: AFI_SAFI_TYPE_IPV6_UNICAST, + 2: AFI_SAFI_TYPE_IPV4_LABELLED_UNICAST, + 3: AFI_SAFI_TYPE_IPV6_LABELLED_UNICAST, + 4: AFI_SAFI_TYPE_L3VPN_IPV4_UNICAST, + 5: AFI_SAFI_TYPE_L3VPN_IPV6_UNICAST, + 6: AFI_SAFI_TYPE_L3VPN_IPV4_MULTICAST, + 7: AFI_SAFI_TYPE_L3VPN_IPV6_MULTICAST, + 8: AFI_SAFI_TYPE_L2VPN_VPLS, + 9: AFI_SAFI_TYPE_L2VPN_EVPN, + 10: AFI_SAFI_TYPE_IPV4_MULTICAST, + 11: AFI_SAFI_TYPE_IPV6_MULTICAST, + 12: AFI_SAFI_TYPE_RTC, + 13: AFI_SAFI_TYPE_IPV4_ENCAP, + 14: AFI_SAFI_TYPE_IPV6_ENCAP, + 15: AFI_SAFI_TYPE_IPV4_FLOWSPEC, + 16: AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC, + 17: AFI_SAFI_TYPE_IPV6_FLOWSPEC, + 18: AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC, + 19: AFI_SAFI_TYPE_L2VPN_FLOWSPEC, + 20: AFI_SAFI_TYPE_IPV4_SRPOLICY, + 21: AFI_SAFI_TYPE_IPV6_SRPOLICY, + 22: AFI_SAFI_TYPE_OPAQUE, + 23: AFI_SAFI_TYPE_LS, + 24: AFI_SAFI_TYPE_IPV4_MUP, + 25: AFI_SAFI_TYPE_IPV6_MUP, +} + +func (v AfiSafiType) Validate() error { + if _, ok := AfiSafiTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid AfiSafiType: %s", v) + } + return nil +} + +func (v AfiSafiType) ToInt() int { + i, ok := AfiSafiTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp-types:bgp-capability. +// Base identity for a BGP capability. +type BgpCapability string + +const ( + BGP_CAPABILITY_MPBGP BgpCapability = "mpbgp" + BGP_CAPABILITY_ROUTE_REFRESH BgpCapability = "route-refresh" + BGP_CAPABILITY_ASN32 BgpCapability = "asn32" + BGP_CAPABILITY_GRACEFUL_RESTART BgpCapability = "graceful-restart" + BGP_CAPABILITY_ADD_PATHS BgpCapability = "add-paths" +) + +var BgpCapabilityToIntMap = map[BgpCapability]int{ + BGP_CAPABILITY_MPBGP: 0, + BGP_CAPABILITY_ROUTE_REFRESH: 1, + BGP_CAPABILITY_ASN32: 2, + BGP_CAPABILITY_GRACEFUL_RESTART: 3, + BGP_CAPABILITY_ADD_PATHS: 4, +} + +var IntToBgpCapabilityMap = map[int]BgpCapability{ + 0: BGP_CAPABILITY_MPBGP, + 1: BGP_CAPABILITY_ROUTE_REFRESH, + 2: BGP_CAPABILITY_ASN32, + 3: BGP_CAPABILITY_GRACEFUL_RESTART, + 4: BGP_CAPABILITY_ADD_PATHS, +} + +func (v BgpCapability) Validate() error { + if _, ok := BgpCapabilityToIntMap[v]; !ok { + return fmt.Errorf("invalid BgpCapability: %s", v) + } + return nil +} + +func (v BgpCapability) ToInt() int { + i, ok := BgpCapabilityToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp-types:bgp-well-known-std-community. +// Reserved communities within the standard community space +// defined by RFC1997. These communities must fall within the +// range 0x00000000 to 0xFFFFFFFF. +type BgpWellKnownStdCommunity string + +const ( + BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT BgpWellKnownStdCommunity = "no_export" + BGP_WELL_KNOWN_STD_COMMUNITY_NO_ADVERTISE BgpWellKnownStdCommunity = "no_advertise" + BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT_SUBCONFED BgpWellKnownStdCommunity = "no_export_subconfed" + BGP_WELL_KNOWN_STD_COMMUNITY_NOPEER BgpWellKnownStdCommunity = "nopeer" +) + +var BgpWellKnownStdCommunityToIntMap = map[BgpWellKnownStdCommunity]int{ + BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT: 0, + BGP_WELL_KNOWN_STD_COMMUNITY_NO_ADVERTISE: 1, + BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT_SUBCONFED: 2, + BGP_WELL_KNOWN_STD_COMMUNITY_NOPEER: 3, +} + +var IntToBgpWellKnownStdCommunityMap = map[int]BgpWellKnownStdCommunity{ + 0: BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT, + 1: BGP_WELL_KNOWN_STD_COMMUNITY_NO_ADVERTISE, + 2: BGP_WELL_KNOWN_STD_COMMUNITY_NO_EXPORT_SUBCONFED, + 3: BGP_WELL_KNOWN_STD_COMMUNITY_NOPEER, +} + +func (v BgpWellKnownStdCommunity) Validate() error { + if _, ok := BgpWellKnownStdCommunityToIntMap[v]; !ok { + return fmt.Errorf("invalid BgpWellKnownStdCommunity: %s", v) + } + return nil +} + +func (v BgpWellKnownStdCommunity) ToInt() int { + i, ok := BgpWellKnownStdCommunityToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity ptypes:match-set-options-restricted-type. +// Options that govern the behavior of a match statement. The +// default behavior is ANY, i.e., the given value matches any +// of the members of the defined set. Note this type is a +// restricted version of the match-set-options-type. +type MatchSetOptionsRestrictedType string + +const ( + MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY MatchSetOptionsRestrictedType = "any" + MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT MatchSetOptionsRestrictedType = "invert" +) + +var MatchSetOptionsRestrictedTypeToIntMap = map[MatchSetOptionsRestrictedType]int{ + MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY: 0, + MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT: 1, +} + +var IntToMatchSetOptionsRestrictedTypeMap = map[int]MatchSetOptionsRestrictedType{ + 0: MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY, + 1: MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT, +} + +func (v MatchSetOptionsRestrictedType) Validate() error { + if _, ok := MatchSetOptionsRestrictedTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid MatchSetOptionsRestrictedType: %s", v) + } + return nil +} + +func (v MatchSetOptionsRestrictedType) Default() MatchSetOptionsRestrictedType { + return MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY +} + +func (v MatchSetOptionsRestrictedType) DefaultAsNeeded() MatchSetOptionsRestrictedType { + if string(v) == "" { + return v.Default() + } + return v +} +func (v MatchSetOptionsRestrictedType) ToInt() int { + _v := v.DefaultAsNeeded() + i, ok := MatchSetOptionsRestrictedTypeToIntMap[_v] + if !ok { + return -1 + } + return i +} + +// typedef for identity ptypes:match-set-options-type. +// Options that govern the behavior of a match statement. The +// default behavior is ANY, i.e., the given value matches any +// of the members of the defined set. +type MatchSetOptionsType string + +const ( + MATCH_SET_OPTIONS_TYPE_ANY MatchSetOptionsType = "any" + MATCH_SET_OPTIONS_TYPE_ALL MatchSetOptionsType = "all" + MATCH_SET_OPTIONS_TYPE_INVERT MatchSetOptionsType = "invert" +) + +var MatchSetOptionsTypeToIntMap = map[MatchSetOptionsType]int{ + MATCH_SET_OPTIONS_TYPE_ANY: 0, + MATCH_SET_OPTIONS_TYPE_ALL: 1, + MATCH_SET_OPTIONS_TYPE_INVERT: 2, +} + +var IntToMatchSetOptionsTypeMap = map[int]MatchSetOptionsType{ + 0: MATCH_SET_OPTIONS_TYPE_ANY, + 1: MATCH_SET_OPTIONS_TYPE_ALL, + 2: MATCH_SET_OPTIONS_TYPE_INVERT, +} + +func (v MatchSetOptionsType) Validate() error { + if _, ok := MatchSetOptionsTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid MatchSetOptionsType: %s", v) + } + return nil +} + +func (v MatchSetOptionsType) Default() MatchSetOptionsType { + return MATCH_SET_OPTIONS_TYPE_ANY +} + +func (v MatchSetOptionsType) DefaultAsNeeded() MatchSetOptionsType { + if string(v) == "" { + return v.Default() + } + return v +} +func (v MatchSetOptionsType) ToInt() int { + _v := v.DefaultAsNeeded() + i, ok := MatchSetOptionsTypeToIntMap[_v] + if !ok { + return -1 + } + return i +} + +// typedef for typedef ptypes:tag-type. +type TagType string + +// typedef for identity ptypes:install-protocol-type. +// Base type for protocols which can install prefixes into the +// RIB. +type InstallProtocolType string + +const ( + INSTALL_PROTOCOL_TYPE_BGP InstallProtocolType = "bgp" + INSTALL_PROTOCOL_TYPE_ISIS InstallProtocolType = "isis" + INSTALL_PROTOCOL_TYPE_OSPF InstallProtocolType = "ospf" + INSTALL_PROTOCOL_TYPE_OSPF3 InstallProtocolType = "ospf3" + INSTALL_PROTOCOL_TYPE_STATIC InstallProtocolType = "static" + INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED InstallProtocolType = "directly-connected" + INSTALL_PROTOCOL_TYPE_LOCAL_AGGREGATE InstallProtocolType = "local-aggregate" +) + +var InstallProtocolTypeToIntMap = map[InstallProtocolType]int{ + INSTALL_PROTOCOL_TYPE_BGP: 0, + INSTALL_PROTOCOL_TYPE_ISIS: 1, + INSTALL_PROTOCOL_TYPE_OSPF: 2, + INSTALL_PROTOCOL_TYPE_OSPF3: 3, + INSTALL_PROTOCOL_TYPE_STATIC: 4, + INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED: 5, + INSTALL_PROTOCOL_TYPE_LOCAL_AGGREGATE: 6, +} + +var IntToInstallProtocolTypeMap = map[int]InstallProtocolType{ + 0: INSTALL_PROTOCOL_TYPE_BGP, + 1: INSTALL_PROTOCOL_TYPE_ISIS, + 2: INSTALL_PROTOCOL_TYPE_OSPF, + 3: INSTALL_PROTOCOL_TYPE_OSPF3, + 4: INSTALL_PROTOCOL_TYPE_STATIC, + 5: INSTALL_PROTOCOL_TYPE_DIRECTLY_CONNECTED, + 6: INSTALL_PROTOCOL_TYPE_LOCAL_AGGREGATE, +} + +func (v InstallProtocolType) Validate() error { + if _, ok := InstallProtocolTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid InstallProtocolType: %s", v) + } + return nil +} + +func (v InstallProtocolType) ToInt() int { + i, ok := InstallProtocolTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity ptypes:attribute-comparison. +// base type for supported comparison operators on route +// attributes. +type AttributeComparison string + +const ( + ATTRIBUTE_COMPARISON_ATTRIBUTE_EQ AttributeComparison = "attribute-eq" + ATTRIBUTE_COMPARISON_ATTRIBUTE_GE AttributeComparison = "attribute-ge" + ATTRIBUTE_COMPARISON_ATTRIBUTE_LE AttributeComparison = "attribute-le" + ATTRIBUTE_COMPARISON_EQ AttributeComparison = "eq" + ATTRIBUTE_COMPARISON_GE AttributeComparison = "ge" + ATTRIBUTE_COMPARISON_LE AttributeComparison = "le" +) + +var AttributeComparisonToIntMap = map[AttributeComparison]int{ + ATTRIBUTE_COMPARISON_ATTRIBUTE_EQ: 0, + ATTRIBUTE_COMPARISON_ATTRIBUTE_GE: 1, + ATTRIBUTE_COMPARISON_ATTRIBUTE_LE: 2, + ATTRIBUTE_COMPARISON_EQ: 3, + ATTRIBUTE_COMPARISON_GE: 4, + ATTRIBUTE_COMPARISON_LE: 5, +} + +var IntToAttributeComparisonMap = map[int]AttributeComparison{ + 0: ATTRIBUTE_COMPARISON_ATTRIBUTE_EQ, + 1: ATTRIBUTE_COMPARISON_ATTRIBUTE_GE, + 2: ATTRIBUTE_COMPARISON_ATTRIBUTE_LE, + 3: ATTRIBUTE_COMPARISON_EQ, + 4: ATTRIBUTE_COMPARISON_GE, + 5: ATTRIBUTE_COMPARISON_LE, +} + +func (v AttributeComparison) Validate() error { + if _, ok := AttributeComparisonToIntMap[v]; !ok { + return fmt.Errorf("invalid AttributeComparison: %s", v) + } + return nil +} + +func (v AttributeComparison) ToInt() int { + i, ok := AttributeComparisonToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity rpol:route-disposition. +// Select the final disposition for the route, either +// accept or reject. +type RouteDisposition string + +const ( + ROUTE_DISPOSITION_NONE RouteDisposition = "none" + ROUTE_DISPOSITION_ACCEPT_ROUTE RouteDisposition = "accept-route" + ROUTE_DISPOSITION_REJECT_ROUTE RouteDisposition = "reject-route" +) + +var RouteDispositionToIntMap = map[RouteDisposition]int{ + ROUTE_DISPOSITION_NONE: 0, + ROUTE_DISPOSITION_ACCEPT_ROUTE: 1, + ROUTE_DISPOSITION_REJECT_ROUTE: 2, +} + +var IntToRouteDispositionMap = map[int]RouteDisposition{ + 0: ROUTE_DISPOSITION_NONE, + 1: ROUTE_DISPOSITION_ACCEPT_ROUTE, + 2: ROUTE_DISPOSITION_REJECT_ROUTE, +} + +func (v RouteDisposition) Validate() error { + if _, ok := RouteDispositionToIntMap[v]; !ok { + return fmt.Errorf("invalid RouteDisposition: %s", v) + } + return nil +} + +func (v RouteDisposition) ToInt() int { + i, ok := RouteDispositionToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity rpol:route-type. +// Condition to check the route type in the route update. +type RouteType string + +const ( + ROUTE_TYPE_NONE RouteType = "none" + ROUTE_TYPE_INTERNAL RouteType = "internal" + ROUTE_TYPE_EXTERNAL RouteType = "external" + ROUTE_TYPE_LOCAL RouteType = "local" +) + +var RouteTypeToIntMap = map[RouteType]int{ + ROUTE_TYPE_NONE: 0, + ROUTE_TYPE_INTERNAL: 1, + ROUTE_TYPE_EXTERNAL: 2, + ROUTE_TYPE_LOCAL: 3, +} + +var IntToRouteTypeMap = map[int]RouteType{ + 0: ROUTE_TYPE_NONE, + 1: ROUTE_TYPE_INTERNAL, + 2: ROUTE_TYPE_EXTERNAL, + 3: ROUTE_TYPE_LOCAL, +} + +func (v RouteType) Validate() error { + if _, ok := RouteTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid RouteType: %s", v) + } + return nil +} + +func (v RouteType) ToInt() int { + i, ok := RouteTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity rpol:default-policy-type. +// type used to specify default route disposition in +// a policy chain. +type DefaultPolicyType string + +const ( + DEFAULT_POLICY_TYPE_ACCEPT_ROUTE DefaultPolicyType = "accept-route" + DEFAULT_POLICY_TYPE_REJECT_ROUTE DefaultPolicyType = "reject-route" +) + +var DefaultPolicyTypeToIntMap = map[DefaultPolicyType]int{ + DEFAULT_POLICY_TYPE_ACCEPT_ROUTE: 0, + DEFAULT_POLICY_TYPE_REJECT_ROUTE: 1, +} + +var IntToDefaultPolicyTypeMap = map[int]DefaultPolicyType{ + 0: DEFAULT_POLICY_TYPE_ACCEPT_ROUTE, + 1: DEFAULT_POLICY_TYPE_REJECT_ROUTE, +} + +func (v DefaultPolicyType) Validate() error { + if _, ok := DefaultPolicyTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid DefaultPolicyType: %s", v) + } + return nil +} + +func (v DefaultPolicyType) ToInt() int { + i, ok := DefaultPolicyTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp:session-state. +// Operational state of the BGP peer. +type SessionState string + +const ( + SESSION_STATE_IDLE SessionState = "idle" + SESSION_STATE_CONNECT SessionState = "connect" + SESSION_STATE_ACTIVE SessionState = "active" + SESSION_STATE_OPENSENT SessionState = "opensent" + SESSION_STATE_OPENCONFIRM SessionState = "openconfirm" + SESSION_STATE_ESTABLISHED SessionState = "established" +) + +var SessionStateToIntMap = map[SessionState]int{ + SESSION_STATE_IDLE: 0, + SESSION_STATE_CONNECT: 1, + SESSION_STATE_ACTIVE: 2, + SESSION_STATE_OPENSENT: 3, + SESSION_STATE_OPENCONFIRM: 4, + SESSION_STATE_ESTABLISHED: 5, +} + +var IntToSessionStateMap = map[int]SessionState{ + 0: SESSION_STATE_IDLE, + 1: SESSION_STATE_CONNECT, + 2: SESSION_STATE_ACTIVE, + 3: SESSION_STATE_OPENSENT, + 4: SESSION_STATE_OPENCONFIRM, + 5: SESSION_STATE_ESTABLISHED, +} + +func (v SessionState) Validate() error { + if _, ok := SessionStateToIntMap[v]; !ok { + return fmt.Errorf("invalid SessionState: %s", v) + } + return nil +} + +func (v SessionState) ToInt() int { + i, ok := SessionStateToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp:admin-state. +type AdminState string + +const ( + ADMIN_STATE_UP AdminState = "up" + ADMIN_STATE_DOWN AdminState = "down" + ADMIN_STATE_PFX_CT AdminState = "pfx_ct" +) + +var AdminStateToIntMap = map[AdminState]int{ + ADMIN_STATE_UP: 0, + ADMIN_STATE_DOWN: 1, + ADMIN_STATE_PFX_CT: 2, +} + +var IntToAdminStateMap = map[int]AdminState{ + 0: ADMIN_STATE_UP, + 1: ADMIN_STATE_DOWN, + 2: ADMIN_STATE_PFX_CT, +} + +func (v AdminState) Validate() error { + if _, ok := AdminStateToIntMap[v]; !ok { + return fmt.Errorf("invalid AdminState: %s", v) + } + return nil +} + +func (v AdminState) ToInt() int { + i, ok := AdminStateToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity bgp:mode. +// Ths leaf indicates the mode of operation of BGP graceful +// restart with the peer. +type Mode string + +const ( + MODE_HELPER_ONLY Mode = "helper-only" + MODE_BILATERAL Mode = "bilateral" + MODE_REMOTE_HELPER Mode = "remote-helper" +) + +var ModeToIntMap = map[Mode]int{ + MODE_HELPER_ONLY: 0, + MODE_BILATERAL: 1, + MODE_REMOTE_HELPER: 2, +} + +var IntToModeMap = map[int]Mode{ + 0: MODE_HELPER_ONLY, + 1: MODE_BILATERAL, + 2: MODE_REMOTE_HELPER, +} + +func (v Mode) Validate() error { + if _, ok := ModeToIntMap[v]; !ok { + return fmt.Errorf("invalid Mode: %s", v) + } + return nil +} + +func (v Mode) ToInt() int { + i, ok := ModeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for typedef bgp-pol:bgp-next-hop-type. +type BgpNextHopType string + +// typedef for typedef bgp-pol:bgp-as-path-prepend-repeat. +type BgpAsPathPrependRepeat uint8 + +// typedef for typedef bgp-pol:bgp-set-med-type. +type BgpSetMedType string + +// typedef for identity bgp-pol:bgp-set-community-option-type. +// Type definition for options when setting the community +// attribute in a policy action. +type BgpSetCommunityOptionType string + +const ( + BGP_SET_COMMUNITY_OPTION_TYPE_ADD BgpSetCommunityOptionType = "add" + BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE BgpSetCommunityOptionType = "remove" + BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE BgpSetCommunityOptionType = "replace" +) + +var BgpSetCommunityOptionTypeToIntMap = map[BgpSetCommunityOptionType]int{ + BGP_SET_COMMUNITY_OPTION_TYPE_ADD: 0, + BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: 1, + BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: 2, +} + +var IntToBgpSetCommunityOptionTypeMap = map[int]BgpSetCommunityOptionType{ + 0: BGP_SET_COMMUNITY_OPTION_TYPE_ADD, + 1: BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE, + 2: BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE, +} + +func (v BgpSetCommunityOptionType) Validate() error { + if _, ok := BgpSetCommunityOptionTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid BgpSetCommunityOptionType: %s", v) + } + return nil +} + +func (v BgpSetCommunityOptionType) ToInt() int { + i, ok := BgpSetCommunityOptionTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity gobgp:bmp-route-monitoring-policy-type. +type BmpRouteMonitoringPolicyType string + +const ( + BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY BmpRouteMonitoringPolicyType = "pre-policy" + BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY BmpRouteMonitoringPolicyType = "post-policy" + BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH BmpRouteMonitoringPolicyType = "both" + BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB BmpRouteMonitoringPolicyType = "local-rib" + BMP_ROUTE_MONITORING_POLICY_TYPE_ALL BmpRouteMonitoringPolicyType = "all" +) + +var BmpRouteMonitoringPolicyTypeToIntMap = map[BmpRouteMonitoringPolicyType]int{ + BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY: 0, + BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY: 1, + BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH: 2, + BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB: 3, + BMP_ROUTE_MONITORING_POLICY_TYPE_ALL: 4, +} + +var IntToBmpRouteMonitoringPolicyTypeMap = map[int]BmpRouteMonitoringPolicyType{ + 0: BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY, + 1: BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY, + 2: BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH, + 3: BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB, + 4: BMP_ROUTE_MONITORING_POLICY_TYPE_ALL, +} + +func (v BmpRouteMonitoringPolicyType) Validate() error { + if _, ok := BmpRouteMonitoringPolicyTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid BmpRouteMonitoringPolicyType: %s", v) + } + return nil +} + +func (v BmpRouteMonitoringPolicyType) ToInt() int { + i, ok := BmpRouteMonitoringPolicyTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity gobgp:mrt-type. +type MrtType string + +const ( + MRT_TYPE_UPDATES MrtType = "updates" + MRT_TYPE_TABLE MrtType = "table" +) + +var MrtTypeToIntMap = map[MrtType]int{ + MRT_TYPE_UPDATES: 0, + MRT_TYPE_TABLE: 1, +} + +var IntToMrtTypeMap = map[int]MrtType{ + 0: MRT_TYPE_UPDATES, + 1: MRT_TYPE_TABLE, +} + +func (v MrtType) Validate() error { + if _, ok := MrtTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid MrtType: %s", v) + } + return nil +} + +func (v MrtType) ToInt() int { + i, ok := MrtTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// typedef for identity gobgp:rpki-validation-result-type. +// indicate the validation result of RPKI based on ROA. +type RpkiValidationResultType string + +const ( + RPKI_VALIDATION_RESULT_TYPE_NONE RpkiValidationResultType = "none" + RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND RpkiValidationResultType = "not-found" + RPKI_VALIDATION_RESULT_TYPE_VALID RpkiValidationResultType = "valid" + RPKI_VALIDATION_RESULT_TYPE_INVALID RpkiValidationResultType = "invalid" +) + +var RpkiValidationResultTypeToIntMap = map[RpkiValidationResultType]int{ + RPKI_VALIDATION_RESULT_TYPE_NONE: 0, + RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND: 1, + RPKI_VALIDATION_RESULT_TYPE_VALID: 2, + RPKI_VALIDATION_RESULT_TYPE_INVALID: 3, +} + +var IntToRpkiValidationResultTypeMap = map[int]RpkiValidationResultType{ + 0: RPKI_VALIDATION_RESULT_TYPE_NONE, + 1: RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, + 2: RPKI_VALIDATION_RESULT_TYPE_VALID, + 3: RPKI_VALIDATION_RESULT_TYPE_INVALID, +} + +func (v RpkiValidationResultType) Validate() error { + if _, ok := RpkiValidationResultTypeToIntMap[v]; !ok { + return fmt.Errorf("invalid RpkiValidationResultType: %s", v) + } + return nil +} + +func (v RpkiValidationResultType) ToInt() int { + i, ok := RpkiValidationResultTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +// struct for container gobgp:state. +type DynamicNeighborState struct { + // original -> gobgp:prefix + Prefix string `mapstructure:"prefix" json:"prefix,omitempty"` + // original -> gobgp:peer-group + PeerGroup string `mapstructure:"peer-group" json:"peer-group,omitempty"` +} + +// struct for container gobgp:config. +type DynamicNeighborConfig struct { + // original -> gobgp:prefix + Prefix string `mapstructure:"prefix" json:"prefix,omitempty"` + // original -> gobgp:peer-group + PeerGroup string `mapstructure:"peer-group" json:"peer-group,omitempty"` +} + +func (lhs *DynamicNeighborConfig) Equal(rhs *DynamicNeighborConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Prefix != rhs.Prefix { + return false + } + if lhs.PeerGroup != rhs.PeerGroup { + return false + } + return true +} + +// struct for container gobgp:dynamic-neighbor. +type DynamicNeighbor struct { + // original -> gobgp:prefix + // original -> gobgp:dynamic-neighbor-config + Config DynamicNeighborConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:dynamic-neighbor-state + State DynamicNeighborState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *DynamicNeighbor) Equal(rhs *DynamicNeighbor) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +type CollectorState struct { + // original -> gobgp:url + Url string `mapstructure:"url" json:"url,omitempty"` + // original -> gobgp:db-name + DbName string `mapstructure:"db-name" json:"db-name,omitempty"` + // original -> gobgp:table-dump-interval + TableDumpInterval uint64 `mapstructure:"table-dump-interval" json:"table-dump-interval,omitempty"` +} + +// struct for container gobgp:config. +type CollectorConfig struct { + // original -> gobgp:url + Url string `mapstructure:"url" json:"url,omitempty"` + // original -> gobgp:db-name + DbName string `mapstructure:"db-name" json:"db-name,omitempty"` + // original -> gobgp:table-dump-interval + TableDumpInterval uint64 `mapstructure:"table-dump-interval" json:"table-dump-interval,omitempty"` +} + +func (lhs *CollectorConfig) Equal(rhs *CollectorConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Url != rhs.Url { + return false + } + if lhs.DbName != rhs.DbName { + return false + } + if lhs.TableDumpInterval != rhs.TableDumpInterval { + return false + } + return true +} + +// struct for container gobgp:collector. +type Collector struct { + // original -> gobgp:collector-config + Config CollectorConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:collector-state + State CollectorState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Collector) Equal(rhs *Collector) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +type ZebraState struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + // Configure enabling to connect to zebra. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:url + // Configure url for zebra. + Url string `mapstructure:"url" json:"url,omitempty"` + // original -> gobgp:redistribute-route-type + RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"` + // original -> gobgp:version + // Configure version of zebra protocol. Default is 2. + // Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting. + Version uint8 `mapstructure:"version" json:"version,omitempty"` + // original -> gobgp:nexthop-trigger-enable + // gobgp:nexthop-trigger-enable's original type is boolean. + NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"` + // original -> gobgp:nexthop-trigger-delay + NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"` + // original -> gobgp:mpls-label-range-size + // Configure MPLS label range size which will be requested to + // FRR/Zebra. + MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` + // original -> gobgp:software-name + // Configure zebra software name. + // frr4, cumulus, frr6, frr7, frr7.2 and frr7.3 can be used. + SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` +} + +// struct for container gobgp:config. +type ZebraConfig struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + // Configure enabling to connect to zebra. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:url + // Configure url for zebra. + Url string `mapstructure:"url" json:"url,omitempty"` + // original -> gobgp:redistribute-route-type + RedistributeRouteTypeList []string `mapstructure:"redistribute-route-type-list" json:"redistribute-route-type-list,omitempty"` + // original -> gobgp:version + // Configure version of zebra protocol. Default is 2. + // Supported version are 2 or 3 for Quagga and 4, 5 or 6 for FRRouting. + Version uint8 `mapstructure:"version" json:"version,omitempty"` + // original -> gobgp:nexthop-trigger-enable + // gobgp:nexthop-trigger-enable's original type is boolean. + NexthopTriggerEnable bool `mapstructure:"nexthop-trigger-enable" json:"nexthop-trigger-enable,omitempty"` + // original -> gobgp:nexthop-trigger-delay + NexthopTriggerDelay uint8 `mapstructure:"nexthop-trigger-delay" json:"nexthop-trigger-delay,omitempty"` + // original -> gobgp:mpls-label-range-size + // Configure MPLS label range size which will be requested to + // FRR/Zebra. + MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` + // original -> gobgp:software-name + // Configure zebra software name. + // frr4, cumulus, frr6, frr7, frr7.2 and frr7.3 can be used. + SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` +} + +func (lhs *ZebraConfig) Equal(rhs *ZebraConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.Url != rhs.Url { + return false + } + if len(lhs.RedistributeRouteTypeList) != len(rhs.RedistributeRouteTypeList) { + return false + } + for idx, l := range lhs.RedistributeRouteTypeList { + if l != rhs.RedistributeRouteTypeList[idx] { + return false + } + } + if lhs.Version != rhs.Version { + return false + } + if lhs.NexthopTriggerEnable != rhs.NexthopTriggerEnable { + return false + } + if lhs.NexthopTriggerDelay != rhs.NexthopTriggerDelay { + return false + } + if lhs.MplsLabelRangeSize != rhs.MplsLabelRangeSize { + return false + } + if lhs.SoftwareName != rhs.SoftwareName { + return false + } + return true +} + +// struct for container gobgp:zebra. +type Zebra struct { + // original -> gobgp:zebra-config + Config ZebraConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:zebra-state + State ZebraState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Zebra) Equal(rhs *Zebra) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:config. +type MrtConfig struct { + // original -> gobgp:dump-type + DumpType MrtType `mapstructure:"dump-type" json:"dump-type,omitempty"` + // original -> gobgp:file-name + // Configures a file name to be written. + FileName string `mapstructure:"file-name" json:"file-name,omitempty"` + // original -> gobgp:table-name + // specify the table name with route server setup. + TableName string `mapstructure:"table-name" json:"table-name,omitempty"` + // original -> gobgp:dump-interval + DumpInterval uint64 `mapstructure:"dump-interval" json:"dump-interval,omitempty"` + // original -> gobgp:rotation-interval + RotationInterval uint64 `mapstructure:"rotation-interval" json:"rotation-interval,omitempty"` +} + +func (lhs *MrtConfig) Equal(rhs *MrtConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.DumpType != rhs.DumpType { + return false + } + if lhs.FileName != rhs.FileName { + return false + } + if lhs.TableName != rhs.TableName { + return false + } + if lhs.DumpInterval != rhs.DumpInterval { + return false + } + if lhs.RotationInterval != rhs.RotationInterval { + return false + } + return true +} + +// struct for container gobgp:mrt. +type Mrt struct { + // original -> gobgp:file-name + // original -> gobgp:mrt-config + Config MrtConfig `mapstructure:"config" json:"config,omitempty"` +} + +func (lhs *Mrt) Equal(rhs *Mrt) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +// Configured states of VRF. +type VrfState struct { + // original -> gobgp:name + // Unique name among all VRF instances. + Name string `mapstructure:"name" json:"name,omitempty"` + // original -> gobgp:id + // Unique identifier among all VRF instances. + Id uint32 `mapstructure:"id" json:"id,omitempty"` + // original -> gobgp:rd + // Route Distinguisher for this VRF. + Rd string `mapstructure:"rd" json:"rd,omitempty"` + // original -> gobgp:import-rt + // List of import Route Targets for this VRF. + ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"` + // original -> gobgp:export-rt + // List of export Route Targets for this VRF. + ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"` +} + +// struct for container gobgp:config. +// Configuration parameters for VRF. +type VrfConfig struct { + // original -> gobgp:name + // Unique name among all VRF instances. + Name string `mapstructure:"name" json:"name,omitempty"` + // original -> gobgp:id + // Unique identifier among all VRF instances. + Id uint32 `mapstructure:"id" json:"id,omitempty"` + // original -> gobgp:rd + // Route Distinguisher for this VRF. + Rd string `mapstructure:"rd" json:"rd,omitempty"` + // original -> gobgp:import-rt + // List of import Route Targets for this VRF. + ImportRtList []string `mapstructure:"import-rt-list" json:"import-rt-list,omitempty"` + // original -> gobgp:export-rt + // List of export Route Targets for this VRF. + ExportRtList []string `mapstructure:"export-rt-list" json:"export-rt-list,omitempty"` + // original -> gobgp:both-rt + // List of both import and export Route Targets for this VRF. Each + // configuration for import and export Route Targets will be preferred. + BothRtList []string `mapstructure:"both-rt-list" json:"both-rt-list,omitempty"` +} + +func (lhs *VrfConfig) Equal(rhs *VrfConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Name != rhs.Name { + return false + } + if lhs.Id != rhs.Id { + return false + } + if lhs.Rd != rhs.Rd { + return false + } + if len(lhs.ImportRtList) != len(rhs.ImportRtList) { + return false + } + for idx, l := range lhs.ImportRtList { + if l != rhs.ImportRtList[idx] { + return false + } + } + if len(lhs.ExportRtList) != len(rhs.ExportRtList) { + return false + } + for idx, l := range lhs.ExportRtList { + if l != rhs.ExportRtList[idx] { + return false + } + } + if len(lhs.BothRtList) != len(rhs.BothRtList) { + return false + } + for idx, l := range lhs.BothRtList { + if l != rhs.BothRtList[idx] { + return false + } + } + return true +} + +// struct for container gobgp:vrf. +// VRF instance configurations on the local system. +type Vrf struct { + // original -> gobgp:name + // original -> gobgp:vrf-config + // Configuration parameters for VRF. + Config VrfConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:vrf-state + // Configured states of VRF. + State VrfState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Vrf) Equal(rhs *Vrf) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +// Configuration parameters relating to BMP server. +type BmpServerState struct { + // original -> gobgp:address + // gobgp:address's original type is inet:ip-address. + // Reference to the address of the BMP server used as + // a key in the BMP server list. + Address string `mapstructure:"address" json:"address,omitempty"` + // original -> gobgp:port + // Reference to the port of the BMP server. + Port uint32 `mapstructure:"port" json:"port,omitempty"` + // original -> gobgp:route-monitoring-policy + RouteMonitoringPolicy BmpRouteMonitoringPolicyType `mapstructure:"route-monitoring-policy" json:"route-monitoring-policy,omitempty"` + // original -> gobgp:statistics-timeout + // Interval seconds of statistics messages sent to BMP server. + StatisticsTimeout uint16 `mapstructure:"statistics-timeout" json:"statistics-timeout,omitempty"` + // original -> gobgp:route-mirroring-enabled + // gobgp:route-mirroring-enabled's original type is boolean. + // Enable feature for mirroring of received BGP messages + // mainly for debugging purpose. + RouteMirroringEnabled bool `mapstructure:"route-mirroring-enabled" json:"route-mirroring-enabled,omitempty"` + // original -> gobgp:sys-name + // Reference to the SysName of the BMP server. + SysName string `mapstructure:"sys-name" json:"sys-name,omitempty"` + // original -> gobgp:sys-descr + // Reference to the SysDescr of the BMP server. + SysDescr string `mapstructure:"sys-descr" json:"sys-descr,omitempty"` +} + +// struct for container gobgp:config. +// Configuration parameters relating to BMP server. +type BmpServerConfig struct { + // original -> gobgp:address + // gobgp:address's original type is inet:ip-address. + // Reference to the address of the BMP server used as + // a key in the BMP server list. + Address string `mapstructure:"address" json:"address,omitempty"` + // original -> gobgp:port + // Reference to the port of the BMP server. + Port uint32 `mapstructure:"port" json:"port,omitempty"` + // original -> gobgp:route-monitoring-policy + RouteMonitoringPolicy BmpRouteMonitoringPolicyType `mapstructure:"route-monitoring-policy" json:"route-monitoring-policy,omitempty"` + // original -> gobgp:statistics-timeout + // Interval seconds of statistics messages sent to BMP server. + StatisticsTimeout uint16 `mapstructure:"statistics-timeout" json:"statistics-timeout,omitempty"` + // original -> gobgp:route-mirroring-enabled + // gobgp:route-mirroring-enabled's original type is boolean. + // Enable feature for mirroring of received BGP messages + // mainly for debugging purpose. + RouteMirroringEnabled bool `mapstructure:"route-mirroring-enabled" json:"route-mirroring-enabled,omitempty"` + // original -> gobgp:sys-name + // Reference to the SysName of the BMP server. + SysName string `mapstructure:"sys-name" json:"sys-name,omitempty"` + // original -> gobgp:sys-descr + // Reference to the SysDescr of the BMP server. + SysDescr string `mapstructure:"sys-descr" json:"sys-descr,omitempty"` +} + +func (lhs *BmpServerConfig) Equal(rhs *BmpServerConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Address != rhs.Address { + return false + } + if lhs.Port != rhs.Port { + return false + } + if lhs.RouteMonitoringPolicy != rhs.RouteMonitoringPolicy { + return false + } + if lhs.StatisticsTimeout != rhs.StatisticsTimeout { + return false + } + if lhs.RouteMirroringEnabled != rhs.RouteMirroringEnabled { + return false + } + if lhs.SysName != rhs.SysName { + return false + } + if lhs.SysDescr != rhs.SysDescr { + return false + } + return true +} + +// struct for container gobgp:bmp-server. +// List of BMP servers configured on the local system. +type BmpServer struct { + // original -> gobgp:address + // original -> gobgp:bmp-server-config + // Configuration parameters relating to BMP server. + Config BmpServerConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:bmp-server-state + // Configuration parameters relating to BMP server. + State BmpServerState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *BmpServer) Equal(rhs *BmpServer) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:rpki-received. +// Counters for reception RPKI Message types. +type RpkiReceived struct { + // original -> gobgp:serial-notify + // Number of serial notify message received from RPKI server. + SerialNotify int64 `mapstructure:"serial-notify" json:"serial-notify,omitempty"` + // original -> gobgp:cache-reset + // Number of cache reset message received from RPKI server. + CacheReset int64 `mapstructure:"cache-reset" json:"cache-reset,omitempty"` + // original -> gobgp:cache-response + // Number of cache response message received from RPKI server. + CacheResponse int64 `mapstructure:"cache-response" json:"cache-response,omitempty"` + // original -> gobgp:ipv4-prefix + // Number of ipv4 prefix message received from RPKI server. + Ipv4Prefix int64 `mapstructure:"ipv4-prefix" json:"ipv4-prefix,omitempty"` + // original -> gobgp:ipv6-prefix + // Number of ipv6 prefix message received from RPKI server. + Ipv6Prefix int64 `mapstructure:"ipv6-prefix" json:"ipv6-prefix,omitempty"` + // original -> gobgp:end-of-data + // Number of end of data message received from RPKI server. + EndOfData int64 `mapstructure:"end-of-data" json:"end-of-data,omitempty"` + // original -> gobgp:error + // Number of error message received from RPKI server. + Error int64 `mapstructure:"error" json:"error,omitempty"` +} + +func (lhs *RpkiReceived) Equal(rhs *RpkiReceived) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.SerialNotify != rhs.SerialNotify { + return false + } + if lhs.CacheReset != rhs.CacheReset { + return false + } + if lhs.CacheResponse != rhs.CacheResponse { + return false + } + if lhs.Ipv4Prefix != rhs.Ipv4Prefix { + return false + } + if lhs.Ipv6Prefix != rhs.Ipv6Prefix { + return false + } + if lhs.EndOfData != rhs.EndOfData { + return false + } + if lhs.Error != rhs.Error { + return false + } + return true +} + +// struct for container gobgp:rpki-sent. +// Counters for transmission RPKI Message types. +type RpkiSent struct { + // original -> gobgp:serial-query + // Number of serial query message sent to RPKI server. + SerialQuery int64 `mapstructure:"serial-query" json:"serial-query,omitempty"` + // original -> gobgp:reset-query + // Number of reset query message sent to RPKI server. + ResetQuery int64 `mapstructure:"reset-query" json:"reset-query,omitempty"` + // original -> gobgp:error + // Number of error message sent to RPKI server. + Error int64 `mapstructure:"error" json:"error,omitempty"` +} + +func (lhs *RpkiSent) Equal(rhs *RpkiSent) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.SerialQuery != rhs.SerialQuery { + return false + } + if lhs.ResetQuery != rhs.ResetQuery { + return false + } + if lhs.Error != rhs.Error { + return false + } + return true +} + +// struct for container gobgp:rpki-messages. +// Counters for transmission and reception RPKI Message types. +type RpkiMessages struct { + // original -> gobgp:rpki-sent + // Counters for transmission RPKI Message types. + RpkiSent RpkiSent `mapstructure:"rpki-sent" json:"rpki-sent,omitempty"` + // original -> gobgp:rpki-received + // Counters for reception RPKI Message types. + RpkiReceived RpkiReceived `mapstructure:"rpki-received" json:"rpki-received,omitempty"` +} + +func (lhs *RpkiMessages) Equal(rhs *RpkiMessages) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.RpkiSent.Equal(&(rhs.RpkiSent)) { + return false + } + if !lhs.RpkiReceived.Equal(&(rhs.RpkiReceived)) { + return false + } + return true +} + +// struct for container gobgp:state. +// State information relating to RPKI server. +type RpkiServerState struct { + // original -> gobgp:up + // gobgp:up's original type is boolean. + Up bool `mapstructure:"up" json:"up,omitempty"` + // original -> gobgp:serial-number + SerialNumber uint32 `mapstructure:"serial-number" json:"serial-number,omitempty"` + // original -> gobgp:records-v4 + RecordsV4 uint32 `mapstructure:"records-v4" json:"records-v4,omitempty"` + // original -> gobgp:records-v6 + RecordsV6 uint32 `mapstructure:"records-v6" json:"records-v6,omitempty"` + // original -> gobgp:prefixes-v4 + PrefixesV4 uint32 `mapstructure:"prefixes-v4" json:"prefixes-v4,omitempty"` + // original -> gobgp:prefixes-v6 + PrefixesV6 uint32 `mapstructure:"prefixes-v6" json:"prefixes-v6,omitempty"` + // original -> gobgp:uptime + // This timer determines the amount of time since the + // RPKI last transitioned in of the Established state. + Uptime int64 `mapstructure:"uptime" json:"uptime,omitempty"` + // original -> gobgp:downtime + // This timer determines the amount of time since the + // RPKI last transitioned out of the Established state. + Downtime int64 `mapstructure:"downtime" json:"downtime,omitempty"` + // original -> gobgp:last-pdu-recv-time + // last time the received an pdu message from RPKI server. + LastPduRecvTime int64 `mapstructure:"last-pdu-recv-time" json:"last-pdu-recv-time,omitempty"` + // original -> gobgp:rpki-messages + // Counters for transmission and reception RPKI Message types. + RpkiMessages RpkiMessages `mapstructure:"rpki-messages" json:"rpki-messages,omitempty"` +} + +// struct for container gobgp:config. +// Configuration parameters relating to RPKI server. +type RpkiServerConfig struct { + // original -> gobgp:address + // gobgp:address's original type is inet:ip-address. + // Reference to the address of the RPKI server used as + // a key in the RPKI server list. + Address string `mapstructure:"address" json:"address,omitempty"` + // original -> gobgp:port + // Reference to the port of the RPKI server. + Port uint32 `mapstructure:"port" json:"port,omitempty"` + // original -> gobgp:refresh-time + // Check interval for a configured RPKI server. + RefreshTime int64 `mapstructure:"refresh-time" json:"refresh-time,omitempty"` + // original -> gobgp:hold-time + // Specify the length of time in seconds that the session between + // the router and RPKI server is to be considered operational + // without any activity. + HoldTime int64 `mapstructure:"hold-time" json:"hold-time,omitempty"` + // original -> gobgp:record-lifetime + // Indicate the expiration date of the route validation recode + // received from RPKI server. + RecordLifetime int64 `mapstructure:"record-lifetime" json:"record-lifetime,omitempty"` + // original -> gobgp:preference + // RPKI server has a static preference. + // Higher the preference values indicates a higher priority RPKI server. + Preference uint8 `mapstructure:"preference" json:"preference,omitempty"` +} + +func (lhs *RpkiServerConfig) Equal(rhs *RpkiServerConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Address != rhs.Address { + return false + } + if lhs.Port != rhs.Port { + return false + } + if lhs.RefreshTime != rhs.RefreshTime { + return false + } + if lhs.HoldTime != rhs.HoldTime { + return false + } + if lhs.RecordLifetime != rhs.RecordLifetime { + return false + } + if lhs.Preference != rhs.Preference { + return false + } + return true +} + +// struct for container gobgp:rpki-server. +// List of RPKI servers configured on the local system. +type RpkiServer struct { + // original -> gobgp:address + // original -> gobgp:rpki-server-config + // Configuration parameters relating to RPKI server. + Config RpkiServerConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:rpki-server-state + // State information relating to RPKI server. + State RpkiServerState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *RpkiServer) Equal(rhs *RpkiServer) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the BGP neighbor or group. +type PeerGroupState struct { + // original -> bgp:peer-as + // bgp:peer-as's original type is inet:as-number. + // AS number of the peer. + PeerAs uint32 `mapstructure:"peer-as" json:"peer-as,omitempty"` + // original -> bgp:local-as + // bgp:local-as's original type is inet:as-number. + // The local autonomous system number that is to be used + // when establishing sessions with the remote peer or peer + // group, if this differs from the global BGP router + // autonomous system number. + LocalAs uint32 `mapstructure:"local-as" json:"local-as,omitempty"` + // original -> bgp:peer-type + // Explicitly designate the peer or peer group as internal + // (iBGP) or external (eBGP). + PeerType PeerType `mapstructure:"peer-type" json:"peer-type,omitempty"` + // original -> bgp:auth-password + // Configures an MD5 authentication password for use with + // neighboring devices. + AuthPassword string `mapstructure:"auth-password" json:"auth-password,omitempty"` + // original -> bgp:remove-private-as + // Remove private AS numbers from updates sent to peers. + RemovePrivateAs RemovePrivateAsOption `mapstructure:"remove-private-as" json:"remove-private-as,omitempty"` + // original -> bgp:route-flap-damping + // bgp:route-flap-damping's original type is boolean. + // Enable route flap damping. + RouteFlapDamping bool `mapstructure:"route-flap-damping" json:"route-flap-damping,omitempty"` + // original -> bgp:send-community + // Specify which types of community should be sent to the + // neighbor or group. The default is to not send the + // community attribute. + SendCommunity CommunityType `mapstructure:"send-community" json:"send-community,omitempty"` + // original -> bgp:description + // An optional textual description (intended primarily for use + // with a peer or group. + Description string `mapstructure:"description" json:"description,omitempty"` + // original -> bgp:peer-group-name + // Name of the BGP peer-group. + PeerGroupName string `mapstructure:"peer-group-name" json:"peer-group-name,omitempty"` + // original -> bgp-op:total-paths + // Total number of BGP paths within the context. + TotalPaths uint32 `mapstructure:"total-paths" json:"total-paths,omitempty"` + // original -> bgp-op:total-prefixes + // . + TotalPrefixes uint32 `mapstructure:"total-prefixes" json:"total-prefixes,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to the BGP neighbor or +// group. +type PeerGroupConfig struct { + // original -> bgp:peer-as + // bgp:peer-as's original type is inet:as-number. + // AS number of the peer. + PeerAs uint32 `mapstructure:"peer-as" json:"peer-as,omitempty"` + // original -> bgp:local-as + // bgp:local-as's original type is inet:as-number. + // The local autonomous system number that is to be used + // when establishing sessions with the remote peer or peer + // group, if this differs from the global BGP router + // autonomous system number. + LocalAs uint32 `mapstructure:"local-as" json:"local-as,omitempty"` + // original -> bgp:peer-type + // Explicitly designate the peer or peer group as internal + // (iBGP) or external (eBGP). + PeerType PeerType `mapstructure:"peer-type" json:"peer-type,omitempty"` + // original -> bgp:auth-password + // Configures an MD5 authentication password for use with + // neighboring devices. + AuthPassword string `mapstructure:"auth-password" json:"auth-password,omitempty"` + // original -> bgp:remove-private-as + // Remove private AS numbers from updates sent to peers. + RemovePrivateAs RemovePrivateAsOption `mapstructure:"remove-private-as" json:"remove-private-as,omitempty"` + // original -> bgp:route-flap-damping + // bgp:route-flap-damping's original type is boolean. + // Enable route flap damping. + RouteFlapDamping bool `mapstructure:"route-flap-damping" json:"route-flap-damping,omitempty"` + // original -> bgp:send-community + // Specify which types of community should be sent to the + // neighbor or group. The default is to not send the + // community attribute. + SendCommunity CommunityType `mapstructure:"send-community" json:"send-community,omitempty"` + // original -> bgp:description + // An optional textual description (intended primarily for use + // with a peer or group. + Description string `mapstructure:"description" json:"description,omitempty"` + // original -> bgp:peer-group-name + // Name of the BGP peer-group. + PeerGroupName string `mapstructure:"peer-group-name" json:"peer-group-name,omitempty"` +} + +func (lhs *PeerGroupConfig) Equal(rhs *PeerGroupConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.PeerAs != rhs.PeerAs { + return false + } + if lhs.LocalAs != rhs.LocalAs { + return false + } + if lhs.PeerType != rhs.PeerType { + return false + } + if lhs.AuthPassword != rhs.AuthPassword { + return false + } + if lhs.RemovePrivateAs != rhs.RemovePrivateAs { + return false + } + if lhs.RouteFlapDamping != rhs.RouteFlapDamping { + return false + } + if lhs.SendCommunity != rhs.SendCommunity { + return false + } + if lhs.Description != rhs.Description { + return false + } + if lhs.PeerGroupName != rhs.PeerGroupName { + return false + } + return true +} + +// struct for container bgp:peer-group. +// List of BGP peer-groups configured on the local system - +// uniquely identified by peer-group name. +type PeerGroup struct { + // original -> bgp:peer-group-name + // original -> bgp:peer-group-config + // Configuration parameters relating to the BGP neighbor or + // group. + Config PeerGroupConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:peer-group-state + // State information relating to the BGP neighbor or group. + State PeerGroupState `mapstructure:"state" json:"state,omitempty"` + // original -> bgp:timers + // Timers related to a BGP neighbor or group. + Timers Timers `mapstructure:"timers" json:"timers,omitempty"` + // original -> bgp:transport + // Transport session parameters for the BGP neighbor or group. + Transport Transport `mapstructure:"transport" json:"transport,omitempty"` + // original -> bgp:error-handling + // Error handling parameters used for the BGP neighbor or + // group. + ErrorHandling ErrorHandling `mapstructure:"error-handling" json:"error-handling,omitempty"` + // original -> bgp:logging-options + // Logging options for events related to the BGP neighbor or + // group. + LoggingOptions LoggingOptions `mapstructure:"logging-options" json:"logging-options,omitempty"` + // original -> bgp:ebgp-multihop + // eBGP multi-hop parameters for the BGP neighbor or group. + EbgpMultihop EbgpMultihop `mapstructure:"ebgp-multihop" json:"ebgp-multihop,omitempty"` + // original -> bgp:route-reflector + // Route reflector parameters for the BGP neighbor or group. + RouteReflector RouteReflector `mapstructure:"route-reflector" json:"route-reflector,omitempty"` + // original -> bgp:as-path-options + // AS_PATH manipulation parameters for the BGP neighbor or + // group. + AsPathOptions AsPathOptions `mapstructure:"as-path-options" json:"as-path-options,omitempty"` + // original -> bgp:add-paths + // Parameters relating to the advertisement and receipt of + // multiple paths for a single NLRI (add-paths). + AddPaths AddPaths `mapstructure:"add-paths" json:"add-paths,omitempty"` + // original -> bgp:afi-safis + // Per-address-family configuration parameters associated with + // the neighbor or group. + AfiSafis []AfiSafi `mapstructure:"afi-safis" json:"afi-safis,omitempty"` + // original -> bgp:graceful-restart + // Parameters relating the graceful restart mechanism for BGP. + GracefulRestart GracefulRestart `mapstructure:"graceful-restart" json:"graceful-restart,omitempty"` + // original -> rpol:apply-policy + // Anchor point for routing policies in the model. + // Import and export policies are with respect to the local + // routing table, i.e., export (send) and import (receive), + // depending on the context. + ApplyPolicy ApplyPolicy `mapstructure:"apply-policy" json:"apply-policy,omitempty"` + // original -> bgp-mp:use-multiple-paths + // Parameters related to the use of multiple paths for the + // same NLRI. + UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` + // original -> gobgp:route-server + // Configure the local router as a route server. + RouteServer RouteServer `mapstructure:"route-server" json:"route-server,omitempty"` + // original -> gobgp:ttl-security + // Configure TTL Security feature. + TtlSecurity TtlSecurity `mapstructure:"ttl-security" json:"ttl-security,omitempty"` +} + +func (lhs *PeerGroup) Equal(rhs *PeerGroup) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + if !lhs.Timers.Equal(&(rhs.Timers)) { + return false + } + if !lhs.Transport.Equal(&(rhs.Transport)) { + return false + } + if !lhs.ErrorHandling.Equal(&(rhs.ErrorHandling)) { + return false + } + if !lhs.LoggingOptions.Equal(&(rhs.LoggingOptions)) { + return false + } + if !lhs.EbgpMultihop.Equal(&(rhs.EbgpMultihop)) { + return false + } + if !lhs.RouteReflector.Equal(&(rhs.RouteReflector)) { + return false + } + if !lhs.AsPathOptions.Equal(&(rhs.AsPathOptions)) { + return false + } + if !lhs.AddPaths.Equal(&(rhs.AddPaths)) { + return false + } + if len(lhs.AfiSafis) != len(rhs.AfiSafis) { + return false + } + { + lmap := make(map[string]*AfiSafi) + for i, l := range lhs.AfiSafis { + lmap[mapkey(i, string(l.Config.AfiSafiName))] = &lhs.AfiSafis[i] + } + for i, r := range rhs.AfiSafis { + if l, y := lmap[mapkey(i, string(r.Config.AfiSafiName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if !lhs.GracefulRestart.Equal(&(rhs.GracefulRestart)) { + return false + } + if !lhs.ApplyPolicy.Equal(&(rhs.ApplyPolicy)) { + return false + } + if !lhs.UseMultiplePaths.Equal(&(rhs.UseMultiplePaths)) { + return false + } + if !lhs.RouteServer.Equal(&(rhs.RouteServer)) { + return false + } + if !lhs.TtlSecurity.Equal(&(rhs.TtlSecurity)) { + return false + } + return true +} + +// struct for container gobgp:state. +// State information for TTL Security. +type TtlSecurityState struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + // Enable features for TTL Security. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:ttl-min + // Reference to the port of the BMP server. + TtlMin uint8 `mapstructure:"ttl-min" json:"ttl-min,omitempty"` +} + +// struct for container gobgp:config. +// Configuration parameters for TTL Security. +type TtlSecurityConfig struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + // Enable features for TTL Security. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:ttl-min + // Reference to the port of the BMP server. + TtlMin uint8 `mapstructure:"ttl-min" json:"ttl-min,omitempty"` +} + +func (lhs *TtlSecurityConfig) Equal(rhs *TtlSecurityConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.TtlMin != rhs.TtlMin { + return false + } + return true +} + +// struct for container gobgp:ttl-security. +// Configure TTL Security feature. +type TtlSecurity struct { + // original -> gobgp:ttl-security-config + // Configuration parameters for TTL Security. + Config TtlSecurityConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:ttl-security-state + // State information for TTL Security. + State TtlSecurityState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *TtlSecurity) Equal(rhs *TtlSecurity) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +// State information relating to route server +// client(s) used for the BGP neighbor. +type RouteServerState struct { + // original -> gobgp:route-server-client + // gobgp:route-server-client's original type is boolean. + // Configure the neighbor as a route server client. + RouteServerClient bool `mapstructure:"route-server-client" json:"route-server-client,omitempty"` + // original -> gobgp:secondary-route + // gobgp:secondary-route's original type is boolean. + // if an export policy rejects a selected route, try the next route in + // order until one that is accepted is found or all routes for the peer + // are rejected. + SecondaryRoute bool `mapstructure:"secondary-route" json:"secondary-route,omitempty"` +} + +// struct for container gobgp:config. +// Configuration parameters relating to route server +// client(s) used for the BGP neighbor. +type RouteServerConfig struct { + // original -> gobgp:route-server-client + // gobgp:route-server-client's original type is boolean. + // Configure the neighbor as a route server client. + RouteServerClient bool `mapstructure:"route-server-client" json:"route-server-client,omitempty"` + // original -> gobgp:secondary-route + // gobgp:secondary-route's original type is boolean. + // if an export policy rejects a selected route, try the next route in + // order until one that is accepted is found or all routes for the peer + // are rejected. + SecondaryRoute bool `mapstructure:"secondary-route" json:"secondary-route,omitempty"` +} + +func (lhs *RouteServerConfig) Equal(rhs *RouteServerConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.RouteServerClient != rhs.RouteServerClient { + return false + } + if lhs.SecondaryRoute != rhs.SecondaryRoute { + return false + } + return true +} + +// struct for container gobgp:route-server. +// Configure the local router as a route server. +type RouteServer struct { + // original -> gobgp:route-server-config + // Configuration parameters relating to route server + // client(s) used for the BGP neighbor. + Config RouteServerConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:route-server-state + // State information relating to route server + // client(s) used for the BGP neighbor. + State RouteServerState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *RouteServer) Equal(rhs *RouteServer) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-op:prefixes. +// Prefix counters for the BGP session. +type Prefixes struct { + // original -> bgp-op:received + // The number of prefixes received from the neighbor. + Received uint32 `mapstructure:"received" json:"received,omitempty"` + // original -> bgp-op:sent + // The number of prefixes advertised to the neighbor. + Sent uint32 `mapstructure:"sent" json:"sent,omitempty"` + // original -> bgp-op:installed + // The number of advertised prefixes installed in the + // Loc-RIB. + Installed uint32 `mapstructure:"installed" json:"installed,omitempty"` +} + +func (lhs *Prefixes) Equal(rhs *Prefixes) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Received != rhs.Received { + return false + } + if lhs.Sent != rhs.Sent { + return false + } + if lhs.Installed != rhs.Installed { + return false + } + return true +} + +// struct for container bgp:state. +// State information associated with ADD_PATHS. +type AddPathsState struct { + // original -> bgp:receive + // bgp:receive's original type is boolean. + // Enable ability to receive multiple path advertisements + // for an NLRI from the neighbor or group. + Receive bool `mapstructure:"receive" json:"receive,omitempty"` + // original -> bgp:send-max + // The maximum number of paths to advertise to neighbors + // for a single NLRI. + SendMax uint8 `mapstructure:"send-max" json:"send-max,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to ADD_PATHS. +type AddPathsConfig struct { + // original -> bgp:receive + // bgp:receive's original type is boolean. + // Enable ability to receive multiple path advertisements + // for an NLRI from the neighbor or group. + Receive bool `mapstructure:"receive" json:"receive,omitempty"` + // original -> bgp:send-max + // The maximum number of paths to advertise to neighbors + // for a single NLRI. + SendMax uint8 `mapstructure:"send-max" json:"send-max,omitempty"` +} + +func (lhs *AddPathsConfig) Equal(rhs *AddPathsConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Receive != rhs.Receive { + return false + } + if lhs.SendMax != rhs.SendMax { + return false + } + return true +} + +// struct for container bgp:add-paths. +// Parameters relating to the advertisement and receipt of +// multiple paths for a single NLRI (add-paths). +type AddPaths struct { + // original -> bgp:add-paths-config + // Configuration parameters relating to ADD_PATHS. + Config AddPathsConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:add-paths-state + // State information associated with ADD_PATHS. + State AddPathsState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *AddPaths) Equal(rhs *AddPaths) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the AS_PATH manipulation +// mechanisms for the BGP peer or group. +type AsPathOptionsState struct { + // original -> bgp:allow-own-as + // Specify the number of occurrences of the local BGP speaker's + // AS that can occur within the AS_PATH before it is rejected. + AllowOwnAs uint8 `mapstructure:"allow-own-as" json:"allow-own-as,omitempty"` + // original -> bgp:replace-peer-as + // bgp:replace-peer-as's original type is boolean. + // Replace occurrences of the peer's AS in the AS_PATH + // with the local autonomous system number. + ReplacePeerAs bool `mapstructure:"replace-peer-as" json:"replace-peer-as,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to AS_PATH manipulation +// for the BGP peer or group. +type AsPathOptionsConfig struct { + // original -> bgp:allow-own-as + // Specify the number of occurrences of the local BGP speaker's + // AS that can occur within the AS_PATH before it is rejected. + AllowOwnAs uint8 `mapstructure:"allow-own-as" json:"allow-own-as,omitempty"` + // original -> bgp:replace-peer-as + // bgp:replace-peer-as's original type is boolean. + // Replace occurrences of the peer's AS in the AS_PATH + // with the local autonomous system number. + ReplacePeerAs bool `mapstructure:"replace-peer-as" json:"replace-peer-as,omitempty"` +} + +func (lhs *AsPathOptionsConfig) Equal(rhs *AsPathOptionsConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AllowOwnAs != rhs.AllowOwnAs { + return false + } + if lhs.ReplacePeerAs != rhs.ReplacePeerAs { + return false + } + return true +} + +// struct for container bgp:as-path-options. +// AS_PATH manipulation parameters for the BGP neighbor or +// group. +type AsPathOptions struct { + // original -> bgp:as-path-options-config + // Configuration parameters relating to AS_PATH manipulation + // for the BGP peer or group. + Config AsPathOptionsConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:as-path-options-state + // State information relating to the AS_PATH manipulation + // mechanisms for the BGP peer or group. + State AsPathOptionsState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *AsPathOptions) Equal(rhs *AsPathOptions) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to route reflection for the +// BGP neighbor or group. +type RouteReflectorState struct { + // original -> bgp:route-reflector-cluster-id + // route-reflector cluster id to use when local router is + // configured as a route reflector. Commonly set at the group + // level, but allows a different cluster + // id to be set for each neighbor. + RouteReflectorClusterId RrClusterIdType `mapstructure:"route-reflector-cluster-id" json:"route-reflector-cluster-id,omitempty"` + // original -> bgp:route-reflector-client + // bgp:route-reflector-client's original type is boolean. + // Configure the neighbor as a route reflector client. + RouteReflectorClient bool `mapstructure:"route-reflector-client" json:"route-reflector-client,omitempty"` +} + +// struct for container bgp:config. +// Configuraton parameters relating to route reflection +// for the BGP neighbor or group. +type RouteReflectorConfig struct { + // original -> bgp:route-reflector-cluster-id + // route-reflector cluster id to use when local router is + // configured as a route reflector. Commonly set at the group + // level, but allows a different cluster + // id to be set for each neighbor. + RouteReflectorClusterId RrClusterIdType `mapstructure:"route-reflector-cluster-id" json:"route-reflector-cluster-id,omitempty"` + // original -> bgp:route-reflector-client + // bgp:route-reflector-client's original type is boolean. + // Configure the neighbor as a route reflector client. + RouteReflectorClient bool `mapstructure:"route-reflector-client" json:"route-reflector-client,omitempty"` +} + +func (lhs *RouteReflectorConfig) Equal(rhs *RouteReflectorConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.RouteReflectorClusterId != rhs.RouteReflectorClusterId { + return false + } + if lhs.RouteReflectorClient != rhs.RouteReflectorClient { + return false + } + return true +} + +// struct for container bgp:route-reflector. +// Route reflector parameters for the BGP neighbor or group. +type RouteReflector struct { + // original -> bgp:route-reflector-config + // Configuraton parameters relating to route reflection + // for the BGP neighbor or group. + Config RouteReflectorConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:route-reflector-state + // State information relating to route reflection for the + // BGP neighbor or group. + State RouteReflectorState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *RouteReflector) Equal(rhs *RouteReflector) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information for eBGP multihop, for the BGP neighbor +// or group. +type EbgpMultihopState struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // When enabled the referenced group or neighbors are permitted + // to be indirectly connected - including cases where the TTL + // can be decremented between the BGP peers. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:multihop-ttl + // Time-to-live value to use when packets are sent to the + // referenced group or neighbors and ebgp-multihop is enabled. + MultihopTtl uint8 `mapstructure:"multihop-ttl" json:"multihop-ttl,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to eBGP multihop for the +// BGP neighbor or group. +type EbgpMultihopConfig struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // When enabled the referenced group or neighbors are permitted + // to be indirectly connected - including cases where the TTL + // can be decremented between the BGP peers. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:multihop-ttl + // Time-to-live value to use when packets are sent to the + // referenced group or neighbors and ebgp-multihop is enabled. + MultihopTtl uint8 `mapstructure:"multihop-ttl" json:"multihop-ttl,omitempty"` +} + +func (lhs *EbgpMultihopConfig) Equal(rhs *EbgpMultihopConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.MultihopTtl != rhs.MultihopTtl { + return false + } + return true +} + +// struct for container bgp:ebgp-multihop. +// eBGP multi-hop parameters for the BGP neighbor or group. +type EbgpMultihop struct { + // original -> bgp:ebgp-multihop-config + // Configuration parameters relating to eBGP multihop for the + // BGP neighbor or group. + Config EbgpMultihopConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:ebgp-multihop-state + // State information for eBGP multihop, for the BGP neighbor + // or group. + State EbgpMultihopState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *EbgpMultihop) Equal(rhs *EbgpMultihop) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to logging for the BGP neighbor +// or group. +type LoggingOptionsState struct { + // original -> bgp:log-neighbor-state-changes + // bgp:log-neighbor-state-changes's original type is boolean. + // Configure logging of peer state changes. Default is + // to enable logging of peer state changes. + LogNeighborStateChanges bool `mapstructure:"log-neighbor-state-changes" json:"log-neighbor-state-changes,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters enabling or modifying logging +// for events relating to the BGP neighbor or group. +type LoggingOptionsConfig struct { + // original -> bgp:log-neighbor-state-changes + // bgp:log-neighbor-state-changes's original type is boolean. + // Configure logging of peer state changes. Default is + // to enable logging of peer state changes. + LogNeighborStateChanges bool `mapstructure:"log-neighbor-state-changes" json:"log-neighbor-state-changes,omitempty"` +} + +func (lhs *LoggingOptionsConfig) Equal(rhs *LoggingOptionsConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.LogNeighborStateChanges != rhs.LogNeighborStateChanges { + return false + } + return true +} + +// struct for container bgp:logging-options. +// Logging options for events related to the BGP neighbor or +// group. +type LoggingOptions struct { + // original -> bgp:logging-options-config + // Configuration parameters enabling or modifying logging + // for events relating to the BGP neighbor or group. + Config LoggingOptionsConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:logging-options-state + // State information relating to logging for the BGP neighbor + // or group. + State LoggingOptionsState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *LoggingOptions) Equal(rhs *LoggingOptions) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to enhanced error handling +// mechanisms for the BGP neighbor or group. +type ErrorHandlingState struct { + // original -> bgp:treat-as-withdraw + // bgp:treat-as-withdraw's original type is boolean. + // Specify whether erroneous UPDATE messages for which the + // NLRI can be extracted are reated as though the NLRI is + // withdrawn - avoiding session reset. + TreatAsWithdraw bool `mapstructure:"treat-as-withdraw" json:"treat-as-withdraw,omitempty"` + // original -> bgp-op:erroneous-update-messages + // The number of BGP UPDATE messages for which the + // treat-as-withdraw mechanism has been applied based + // on erroneous message contents. + ErroneousUpdateMessages uint32 `mapstructure:"erroneous-update-messages" json:"erroneous-update-messages,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters enabling or modifying the +// behavior or enhanced error handling mechanisms for the BGP +// neighbor or group. +type ErrorHandlingConfig struct { + // original -> bgp:treat-as-withdraw + // bgp:treat-as-withdraw's original type is boolean. + // Specify whether erroneous UPDATE messages for which the + // NLRI can be extracted are reated as though the NLRI is + // withdrawn - avoiding session reset. + TreatAsWithdraw bool `mapstructure:"treat-as-withdraw" json:"treat-as-withdraw,omitempty"` +} + +func (lhs *ErrorHandlingConfig) Equal(rhs *ErrorHandlingConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.TreatAsWithdraw != rhs.TreatAsWithdraw { + return false + } + return true +} + +// struct for container bgp:error-handling. +// Error handling parameters used for the BGP neighbor or +// group. +type ErrorHandling struct { + // original -> bgp:error-handling-config + // Configuration parameters enabling or modifying the + // behavior or enhanced error handling mechanisms for the BGP + // neighbor or group. + Config ErrorHandlingConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:error-handling-state + // State information relating to enhanced error handling + // mechanisms for the BGP neighbor or group. + State ErrorHandlingState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *ErrorHandling) Equal(rhs *ErrorHandling) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the transport session(s) +// used for the BGP neighbor or group. +type TransportState struct { + // original -> bgp:tcp-mss + // Sets the max segment size for BGP TCP sessions. + TcpMss uint16 `mapstructure:"tcp-mss" json:"tcp-mss,omitempty"` + // original -> bgp:mtu-discovery + // bgp:mtu-discovery's original type is boolean. + // Turns path mtu discovery for BGP TCP sessions on (true) + // or off (false). + MtuDiscovery bool `mapstructure:"mtu-discovery" json:"mtu-discovery,omitempty"` + // original -> bgp:passive-mode + // bgp:passive-mode's original type is boolean. + // Wait for peers to issue requests to open a BGP session, + // rather than initiating sessions from the local router. + PassiveMode bool `mapstructure:"passive-mode" json:"passive-mode,omitempty"` + // original -> bgp:local-address + // bgp:local-address's original type is union. + // Set the local IP (either IPv4 or IPv6) address to use + // for the session when sending BGP update messages. This + // may be expressed as either an IP address or reference + // to the name of an interface. + LocalAddress string `mapstructure:"local-address" json:"local-address,omitempty"` + // original -> bgp-op:local-port + // bgp-op:local-port's original type is inet:port-number. + // Local TCP port being used for the TCP session supporting + // the BGP session. + LocalPort uint16 `mapstructure:"local-port" json:"local-port,omitempty"` + // original -> bgp-op:remote-address + // bgp-op:remote-address's original type is inet:ip-address. + // Remote address to which the BGP session has been + // established. + RemoteAddress string `mapstructure:"remote-address" json:"remote-address,omitempty"` + // original -> bgp-op:remote-port + // bgp-op:remote-port's original type is inet:port-number. + // Remote port being used by the peer for the TCP session + // supporting the BGP session. + RemotePort uint16 `mapstructure:"remote-port" json:"remote-port,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to the transport +// session(s) used for the BGP neighbor or group. +type TransportConfig struct { + // original -> bgp:tcp-mss + // Sets the max segment size for BGP TCP sessions. + TcpMss uint16 `mapstructure:"tcp-mss" json:"tcp-mss,omitempty"` + // original -> bgp:mtu-discovery + // bgp:mtu-discovery's original type is boolean. + // Turns path mtu discovery for BGP TCP sessions on (true) + // or off (false). + MtuDiscovery bool `mapstructure:"mtu-discovery" json:"mtu-discovery,omitempty"` + // original -> bgp:passive-mode + // bgp:passive-mode's original type is boolean. + // Wait for peers to issue requests to open a BGP session, + // rather than initiating sessions from the local router. + PassiveMode bool `mapstructure:"passive-mode" json:"passive-mode,omitempty"` + // original -> bgp:local-address + // bgp:local-address's original type is union. + // Set the local IP (either IPv4 or IPv6) address to use + // for the session when sending BGP update messages. This + // may be expressed as either an IP address or reference + // to the name of an interface. + LocalAddress string `mapstructure:"local-address" json:"local-address,omitempty"` + // original -> gobgp:local-port + // gobgp:local-port's original type is inet:port-number. + // Set the local port (if available) to use for the session. + LocalPort uint16 `mapstructure:"local-port" json:"local-port,omitempty"` + // original -> gobgp:remote-port + // gobgp:remote-port's original type is inet:port-number. + RemotePort uint16 `mapstructure:"remote-port" json:"remote-port,omitempty"` + // original -> gobgp:ttl + // TTL value for BGP packets. + Ttl uint8 `mapstructure:"ttl" json:"ttl,omitempty"` + // original -> gobgp:bind-interface + // Interface name for binding. + BindInterface string `mapstructure:"bind-interface" json:"bind-interface,omitempty"` +} + +func (lhs *TransportConfig) Equal(rhs *TransportConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.TcpMss != rhs.TcpMss { + return false + } + if lhs.MtuDiscovery != rhs.MtuDiscovery { + return false + } + if lhs.PassiveMode != rhs.PassiveMode { + return false + } + if lhs.LocalAddress != rhs.LocalAddress { + return false + } + if lhs.LocalPort != rhs.LocalPort { + return false + } + if lhs.RemotePort != rhs.RemotePort { + return false + } + if lhs.Ttl != rhs.Ttl { + return false + } + if lhs.BindInterface != rhs.BindInterface { + return false + } + return true +} + +// struct for container bgp:transport. +// Transport session parameters for the BGP neighbor or group. +type Transport struct { + // original -> bgp:transport-config + // Configuration parameters relating to the transport + // session(s) used for the BGP neighbor or group. + Config TransportConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:transport-state + // State information relating to the transport session(s) + // used for the BGP neighbor or group. + State TransportState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Transport) Equal(rhs *Transport) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the timers used for the BGP +// neighbor or group. +type TimersState struct { + // original -> bgp:connect-retry + // bgp:connect-retry's original type is decimal64. + // Time interval in seconds between attempts to establish a + // session with the peer. + ConnectRetry float64 `mapstructure:"connect-retry" json:"connect-retry,omitempty"` + // original -> bgp:hold-time + // bgp:hold-time's original type is decimal64. + // Time interval in seconds that a BGP session will be + // considered active in the absence of keepalive or other + // messages from the peer. The hold-time is typically + // set to 3x the keepalive-interval. + HoldTime float64 `mapstructure:"hold-time" json:"hold-time,omitempty"` + // original -> bgp:keepalive-interval + // bgp:keepalive-interval's original type is decimal64. + // Time interval in seconds between transmission of keepalive + // messages to the neighbor. Typically set to 1/3 the + // hold-time. + KeepaliveInterval float64 `mapstructure:"keepalive-interval" json:"keepalive-interval,omitempty"` + // original -> bgp:minimum-advertisement-interval + // bgp:minimum-advertisement-interval's original type is decimal64. + // Minimum time which must elapse between subsequent UPDATE + // messages relating to a common set of NLRI being transmitted + // to a peer. This timer is referred to as + // MinRouteAdvertisementIntervalTimer by RFC 4721 and serves to + // reduce the number of UPDATE messages transmitted when a + // particular set of NLRI exhibit instability. + MinimumAdvertisementInterval float64 `mapstructure:"minimum-advertisement-interval" json:"minimum-advertisement-interval,omitempty"` + // original -> bgp-op:uptime + // bgp-op:uptime's original type is yang:timeticks. + // This timer determines the amount of time since the + // BGP last transitioned in or out of the Established + // state. + Uptime int64 `mapstructure:"uptime" json:"uptime,omitempty"` + // original -> bgp-op:negotiated-hold-time + // bgp-op:negotiated-hold-time's original type is decimal64. + // The negotiated hold-time for the BGP session. + NegotiatedHoldTime float64 `mapstructure:"negotiated-hold-time" json:"negotiated-hold-time,omitempty"` + // original -> gobgp:idle-hold-time-after-reset + // gobgp:idle-hold-time-after-reset's original type is decimal64. + // Time interval in seconds that a BGP session will be + // in idle state after neighbor reset operation. + IdleHoldTimeAfterReset float64 `mapstructure:"idle-hold-time-after-reset" json:"idle-hold-time-after-reset,omitempty"` + // original -> gobgp:downtime + // gobgp:downtime's original type is yang:timeticks. + // This timer determines the amount of time since the + // BGP last transitioned out of the Established state. + Downtime int64 `mapstructure:"downtime" json:"downtime,omitempty"` + // original -> gobgp:update-recv-time + // The number of seconds elapsed since January 1, 1970 UTC + // last time the BGP session received an UPDATE message. + UpdateRecvTime int64 `mapstructure:"update-recv-time" json:"update-recv-time,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to timers used for the +// BGP neighbor or group. +type TimersConfig struct { + // original -> bgp:connect-retry + // bgp:connect-retry's original type is decimal64. + // Time interval in seconds between attempts to establish a + // session with the peer. + ConnectRetry float64 `mapstructure:"connect-retry" json:"connect-retry,omitempty"` + // original -> bgp:hold-time + // bgp:hold-time's original type is decimal64. + // Time interval in seconds that a BGP session will be + // considered active in the absence of keepalive or other + // messages from the peer. The hold-time is typically + // set to 3x the keepalive-interval. + HoldTime float64 `mapstructure:"hold-time" json:"hold-time,omitempty"` + // original -> bgp:keepalive-interval + // bgp:keepalive-interval's original type is decimal64. + // Time interval in seconds between transmission of keepalive + // messages to the neighbor. Typically set to 1/3 the + // hold-time. + KeepaliveInterval float64 `mapstructure:"keepalive-interval" json:"keepalive-interval,omitempty"` + // original -> bgp:minimum-advertisement-interval + // bgp:minimum-advertisement-interval's original type is decimal64. + // Minimum time which must elapse between subsequent UPDATE + // messages relating to a common set of NLRI being transmitted + // to a peer. This timer is referred to as + // MinRouteAdvertisementIntervalTimer by RFC 4721 and serves to + // reduce the number of UPDATE messages transmitted when a + // particular set of NLRI exhibit instability. + MinimumAdvertisementInterval float64 `mapstructure:"minimum-advertisement-interval" json:"minimum-advertisement-interval,omitempty"` + // original -> gobgp:idle-hold-time-after-reset + // gobgp:idle-hold-time-after-reset's original type is decimal64. + // Time interval in seconds that a BGP session will be + // in idle state after neighbor reset operation. + IdleHoldTimeAfterReset float64 `mapstructure:"idle-hold-time-after-reset" json:"idle-hold-time-after-reset,omitempty"` +} + +func (lhs *TimersConfig) Equal(rhs *TimersConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.ConnectRetry != rhs.ConnectRetry { + return false + } + if lhs.HoldTime != rhs.HoldTime { + return false + } + if lhs.KeepaliveInterval != rhs.KeepaliveInterval { + return false + } + if lhs.MinimumAdvertisementInterval != rhs.MinimumAdvertisementInterval { + return false + } + if lhs.IdleHoldTimeAfterReset != rhs.IdleHoldTimeAfterReset { + return false + } + return true +} + +// struct for container bgp:timers. +// Timers related to a BGP neighbor or group. +type Timers struct { + // original -> bgp:timers-config + // Configuration parameters relating to timers used for the + // BGP neighbor or group. + Config TimersConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:timers-state + // State information relating to the timers used for the BGP + // neighbor or group. + State TimersState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Timers) Equal(rhs *Timers) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:adj-table. +type AdjTable struct { + // original -> gobgp:ADVERTISED + Advertised uint32 `mapstructure:"advertised" json:"advertised,omitempty"` + // original -> gobgp:FILTERED + Filtered uint32 `mapstructure:"filtered" json:"filtered,omitempty"` + // original -> gobgp:RECEIVED + Received uint32 `mapstructure:"received" json:"received,omitempty"` + // original -> gobgp:ACCEPTED + Accepted uint32 `mapstructure:"accepted" json:"accepted,omitempty"` +} + +func (lhs *AdjTable) Equal(rhs *AdjTable) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Advertised != rhs.Advertised { + return false + } + if lhs.Filtered != rhs.Filtered { + return false + } + if lhs.Received != rhs.Received { + return false + } + if lhs.Accepted != rhs.Accepted { + return false + } + return true +} + +// struct for container bgp:queues. +// Counters related to queued messages associated with the +// BGP neighbor. +type Queues struct { + // original -> bgp-op:input + // The number of messages received from the peer currently + // queued. + Input uint32 `mapstructure:"input" json:"input,omitempty"` + // original -> bgp-op:output + // The number of messages queued to be sent to the peer. + Output uint32 `mapstructure:"output" json:"output,omitempty"` +} + +func (lhs *Queues) Equal(rhs *Queues) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Input != rhs.Input { + return false + } + if lhs.Output != rhs.Output { + return false + } + return true +} + +// struct for container bgp:received. +// Counters for BGP messages received from the neighbor. +type Received struct { + // original -> bgp-op:UPDATE + // Number of BGP UPDATE messages announcing, withdrawing + // or modifying paths exchanged. + Update uint64 `mapstructure:"update" json:"update,omitempty"` + // original -> bgp-op:NOTIFICATION + // Number of BGP NOTIFICATION messages indicating an + // error condition has occurred exchanged. + Notification uint64 `mapstructure:"notification" json:"notification,omitempty"` + // original -> gobgp:OPEN + // Number of BGP open messages announcing, withdrawing + // or modifying paths exchanged. + Open uint64 `mapstructure:"open" json:"open,omitempty"` + // original -> gobgp:REFRESH + // Number of BGP Route-Refresh messages indicating an + // error condition has occurred exchanged. + Refresh uint64 `mapstructure:"refresh" json:"refresh,omitempty"` + // original -> gobgp:KEEPALIVE + // Number of BGP Keepalive messages indicating an + // error condition has occurred exchanged. + Keepalive uint64 `mapstructure:"keepalive" json:"keepalive,omitempty"` + // original -> gobgp:DYNAMIC-CAP + // Number of BGP dynamic-cap messages indicating an + // error condition has occurred exchanged. + DynamicCap uint64 `mapstructure:"dynamic-cap" json:"dynamic-cap,omitempty"` + // original -> gobgp:WITHDRAW-UPDATE + // Number of updates subjected to treat-as-withdraw treatment. + WithdrawUpdate uint32 `mapstructure:"withdraw-update" json:"withdraw-update,omitempty"` + // original -> gobgp:WITHDRAW-PREFIX + // Number of prefixes subjected to treat-as-withdraw treatment. + WithdrawPrefix uint32 `mapstructure:"withdraw-prefix" json:"withdraw-prefix,omitempty"` + // original -> gobgp:DISCARDED + // Number of discarded messages indicating an + // error condition has occurred exchanged. + Discarded uint64 `mapstructure:"discarded" json:"discarded,omitempty"` + // original -> gobgp:TOTAL + // Number of total messages indicating an + // error condition has occurred exchanged. + Total uint64 `mapstructure:"total" json:"total,omitempty"` +} + +func (lhs *Received) Equal(rhs *Received) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Update != rhs.Update { + return false + } + if lhs.Notification != rhs.Notification { + return false + } + if lhs.Open != rhs.Open { + return false + } + if lhs.Refresh != rhs.Refresh { + return false + } + if lhs.Keepalive != rhs.Keepalive { + return false + } + if lhs.DynamicCap != rhs.DynamicCap { + return false + } + if lhs.WithdrawUpdate != rhs.WithdrawUpdate { + return false + } + if lhs.WithdrawPrefix != rhs.WithdrawPrefix { + return false + } + if lhs.Discarded != rhs.Discarded { + return false + } + if lhs.Total != rhs.Total { + return false + } + return true +} + +// struct for container bgp:sent. +// Counters relating to BGP messages sent to the neighbor. +type Sent struct { + // original -> bgp-op:UPDATE + // Number of BGP UPDATE messages announcing, withdrawing + // or modifying paths exchanged. + Update uint64 `mapstructure:"update" json:"update,omitempty"` + // original -> bgp-op:NOTIFICATION + // Number of BGP NOTIFICATION messages indicating an + // error condition has occurred exchanged. + Notification uint64 `mapstructure:"notification" json:"notification,omitempty"` + // original -> gobgp:OPEN + // Number of BGP open messages announcing, withdrawing + // or modifying paths exchanged. + Open uint64 `mapstructure:"open" json:"open,omitempty"` + // original -> gobgp:REFRESH + // Number of BGP Route-Refresh messages indicating an + // error condition has occurred exchanged. + Refresh uint64 `mapstructure:"refresh" json:"refresh,omitempty"` + // original -> gobgp:KEEPALIVE + // Number of BGP Keepalive messages indicating an + // error condition has occurred exchanged. + Keepalive uint64 `mapstructure:"keepalive" json:"keepalive,omitempty"` + // original -> gobgp:DYNAMIC-CAP + // Number of BGP dynamic-cap messages indicating an + // error condition has occurred exchanged. + DynamicCap uint64 `mapstructure:"dynamic-cap" json:"dynamic-cap,omitempty"` + // original -> gobgp:WITHDRAW-UPDATE + // Number of updates subjected to treat-as-withdraw treatment. + WithdrawUpdate uint32 `mapstructure:"withdraw-update" json:"withdraw-update,omitempty"` + // original -> gobgp:WITHDRAW-PREFIX + // Number of prefixes subjected to treat-as-withdraw treatment. + WithdrawPrefix uint32 `mapstructure:"withdraw-prefix" json:"withdraw-prefix,omitempty"` + // original -> gobgp:DISCARDED + // Number of discarded messages indicating an + // error condition has occurred exchanged. + Discarded uint64 `mapstructure:"discarded" json:"discarded,omitempty"` + // original -> gobgp:TOTAL + // Number of total messages indicating an + // error condition has occurred exchanged. + Total uint64 `mapstructure:"total" json:"total,omitempty"` +} + +func (lhs *Sent) Equal(rhs *Sent) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Update != rhs.Update { + return false + } + if lhs.Notification != rhs.Notification { + return false + } + if lhs.Open != rhs.Open { + return false + } + if lhs.Refresh != rhs.Refresh { + return false + } + if lhs.Keepalive != rhs.Keepalive { + return false + } + if lhs.DynamicCap != rhs.DynamicCap { + return false + } + if lhs.WithdrawUpdate != rhs.WithdrawUpdate { + return false + } + if lhs.WithdrawPrefix != rhs.WithdrawPrefix { + return false + } + if lhs.Discarded != rhs.Discarded { + return false + } + if lhs.Total != rhs.Total { + return false + } + return true +} + +// struct for container bgp:messages. +// Counters for BGP messages sent and received from the +// neighbor. +type Messages struct { + // original -> bgp:sent + // Counters relating to BGP messages sent to the neighbor. + Sent Sent `mapstructure:"sent" json:"sent,omitempty"` + // original -> bgp:received + // Counters for BGP messages received from the neighbor. + Received Received `mapstructure:"received" json:"received,omitempty"` +} + +func (lhs *Messages) Equal(rhs *Messages) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Sent.Equal(&(rhs.Sent)) { + return false + } + if !lhs.Received.Equal(&(rhs.Received)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the BGP neighbor or group. +type NeighborState struct { + // original -> bgp:peer-as + // bgp:peer-as's original type is inet:as-number. + // AS number of the peer. + PeerAs uint32 `mapstructure:"peer-as" json:"peer-as,omitempty"` + // original -> bgp:local-as + // bgp:local-as's original type is inet:as-number. + // The local autonomous system number that is to be used + // when establishing sessions with the remote peer or peer + // group, if this differs from the global BGP router + // autonomous system number. + LocalAs uint32 `mapstructure:"local-as" json:"local-as,omitempty"` + // original -> bgp:peer-type + // Explicitly designate the peer or peer group as internal + // (iBGP) or external (eBGP). + PeerType PeerType `mapstructure:"peer-type" json:"peer-type,omitempty"` + // original -> bgp:auth-password + // Configures an MD5 authentication password for use with + // neighboring devices. + AuthPassword string `mapstructure:"auth-password" json:"auth-password,omitempty"` + // original -> bgp:remove-private-as + // Remove private AS numbers from updates sent to peers. + RemovePrivateAs RemovePrivateAsOption `mapstructure:"remove-private-as" json:"remove-private-as,omitempty"` + // original -> bgp:route-flap-damping + // bgp:route-flap-damping's original type is boolean. + // Enable route flap damping. + RouteFlapDamping bool `mapstructure:"route-flap-damping" json:"route-flap-damping,omitempty"` + // original -> bgp:send-community + // Specify which types of community should be sent to the + // neighbor or group. The default is to not send the + // community attribute. + SendCommunity CommunityType `mapstructure:"send-community" json:"send-community,omitempty"` + // original -> bgp:description + // An optional textual description (intended primarily for use + // with a peer or group. + Description string `mapstructure:"description" json:"description,omitempty"` + // original -> bgp:peer-group + // The peer-group with which this neighbor is associated. + PeerGroup string `mapstructure:"peer-group" json:"peer-group,omitempty"` + // original -> bgp:neighbor-address + // bgp:neighbor-address's original type is inet:ip-address. + // Address of the BGP peer, either in IPv4 or IPv6. + NeighborAddress string `mapstructure:"neighbor-address" json:"neighbor-address,omitempty"` + // original -> bgp-op:session-state + // Operational state of the BGP peer. + SessionState SessionState `mapstructure:"session-state" json:"session-state,omitempty"` + // original -> bgp-op:supported-capabilities + // BGP capabilities negotiated as supported with the peer. + SupportedCapabilitiesList []BgpCapability `mapstructure:"supported-capabilities-list" json:"supported-capabilities-list,omitempty"` + // original -> bgp:messages + // Counters for BGP messages sent and received from the + // neighbor. + Messages Messages `mapstructure:"messages" json:"messages,omitempty"` + // original -> bgp:queues + // Counters related to queued messages associated with the + // BGP neighbor. + Queues Queues `mapstructure:"queues" json:"queues,omitempty"` + // original -> gobgp:adj-table + AdjTable AdjTable `mapstructure:"adj-table" json:"adj-table,omitempty"` + // original -> gobgp:remote-capability + // original type is list of bgp-capability + RemoteCapabilityList []bgp.ParameterCapabilityInterface `mapstructure:"remote-capability-list" json:"remote-capability-list,omitempty"` + // original -> gobgp:local-capability + // original type is list of bgp-capability + LocalCapabilityList []bgp.ParameterCapabilityInterface `mapstructure:"local-capability-list" json:"local-capability-list,omitempty"` + // original -> gobgp:received-open-message + // gobgp:received-open-message's original type is bgp-open-message. + ReceivedOpenMessage *bgp.BGPMessage `mapstructure:"received-open-message" json:"received-open-message,omitempty"` + // original -> gobgp:admin-down + // gobgp:admin-down's original type is boolean. + // The state of administrative operation. If the state is true, it indicates the neighbor is disabled by the administrator. + AdminDown bool `mapstructure:"admin-down" json:"admin-down,omitempty"` + // original -> gobgp:admin-state + AdminState AdminState `mapstructure:"admin-state" json:"admin-state,omitempty"` + // original -> gobgp:established-count + // The number of how many the peer became established state. + EstablishedCount uint32 `mapstructure:"established-count" json:"established-count,omitempty"` + // original -> gobgp:flops + // The number of flip-flops. + Flops uint32 `mapstructure:"flops" json:"flops,omitempty"` + // original -> gobgp:neighbor-interface + NeighborInterface string `mapstructure:"neighbor-interface" json:"neighbor-interface,omitempty"` + // original -> gobgp:vrf + Vrf string `mapstructure:"vrf" json:"vrf,omitempty"` + // original -> gobgp:remote-router-id + RemoteRouterId string `mapstructure:"remote-router-id" json:"remote-router-id,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to the BGP neighbor or +// group. +type NeighborConfig struct { + // original -> bgp:peer-as + // bgp:peer-as's original type is inet:as-number. + // AS number of the peer. + PeerAs uint32 `mapstructure:"peer-as" json:"peer-as,omitempty"` + // original -> bgp:local-as + // bgp:local-as's original type is inet:as-number. + // The local autonomous system number that is to be used + // when establishing sessions with the remote peer or peer + // group, if this differs from the global BGP router + // autonomous system number. + LocalAs uint32 `mapstructure:"local-as" json:"local-as,omitempty"` + // original -> bgp:peer-type + // Explicitly designate the peer or peer group as internal + // (iBGP) or external (eBGP). + PeerType PeerType `mapstructure:"peer-type" json:"peer-type,omitempty"` + // original -> bgp:auth-password + // Configures an MD5 authentication password for use with + // neighboring devices. + AuthPassword string `mapstructure:"auth-password" json:"auth-password,omitempty"` + // original -> bgp:remove-private-as + // Remove private AS numbers from updates sent to peers. + RemovePrivateAs RemovePrivateAsOption `mapstructure:"remove-private-as" json:"remove-private-as,omitempty"` + // original -> bgp:route-flap-damping + // bgp:route-flap-damping's original type is boolean. + // Enable route flap damping. + RouteFlapDamping bool `mapstructure:"route-flap-damping" json:"route-flap-damping,omitempty"` + // original -> bgp:send-community + // Specify which types of community should be sent to the + // neighbor or group. The default is to not send the + // community attribute. + SendCommunity CommunityType `mapstructure:"send-community" json:"send-community,omitempty"` + // original -> bgp:description + // An optional textual description (intended primarily for use + // with a peer or group. + Description string `mapstructure:"description" json:"description,omitempty"` + // original -> bgp:peer-group + // The peer-group with which this neighbor is associated. + PeerGroup string `mapstructure:"peer-group" json:"peer-group,omitempty"` + // original -> bgp:neighbor-address + // bgp:neighbor-address's original type is inet:ip-address. + // Address of the BGP peer, either in IPv4 or IPv6. + NeighborAddress string `mapstructure:"neighbor-address" json:"neighbor-address,omitempty"` + // original -> gobgp:admin-down + // gobgp:admin-down's original type is boolean. + // The config of administrative operation. If state, indicates the neighbor is disabled by the administrator. + AdminDown bool `mapstructure:"admin-down" json:"admin-down,omitempty"` + // original -> gobgp:neighbor-interface + NeighborInterface string `mapstructure:"neighbor-interface" json:"neighbor-interface,omitempty"` + // original -> gobgp:vrf + Vrf string `mapstructure:"vrf" json:"vrf,omitempty"` +} + +func (lhs *NeighborConfig) Equal(rhs *NeighborConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.PeerAs != rhs.PeerAs { + return false + } + if lhs.LocalAs != rhs.LocalAs { + return false + } + if lhs.PeerType != rhs.PeerType { + return false + } + if lhs.AuthPassword != rhs.AuthPassword { + return false + } + if lhs.RemovePrivateAs != rhs.RemovePrivateAs { + return false + } + if lhs.RouteFlapDamping != rhs.RouteFlapDamping { + return false + } + if lhs.SendCommunity != rhs.SendCommunity { + return false + } + if lhs.Description != rhs.Description { + return false + } + if lhs.PeerGroup != rhs.PeerGroup { + return false + } + if lhs.NeighborAddress != rhs.NeighborAddress { + return false + } + if lhs.AdminDown != rhs.AdminDown { + return false + } + if lhs.NeighborInterface != rhs.NeighborInterface { + return false + } + if lhs.Vrf != rhs.Vrf { + return false + } + return true +} + +// struct for container bgp:neighbor. +// List of BGP neighbors configured on the local system, +// uniquely identified by peer IPv[46] address. +type Neighbor struct { + // original -> bgp:neighbor-address + // original -> bgp:neighbor-config + // Configuration parameters relating to the BGP neighbor or + // group. + Config NeighborConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:neighbor-state + // State information relating to the BGP neighbor or group. + State NeighborState `mapstructure:"state" json:"state,omitempty"` + // original -> bgp:timers + // Timers related to a BGP neighbor or group. + Timers Timers `mapstructure:"timers" json:"timers,omitempty"` + // original -> bgp:transport + // Transport session parameters for the BGP neighbor or group. + Transport Transport `mapstructure:"transport" json:"transport,omitempty"` + // original -> bgp:error-handling + // Error handling parameters used for the BGP neighbor or + // group. + ErrorHandling ErrorHandling `mapstructure:"error-handling" json:"error-handling,omitempty"` + // original -> bgp:logging-options + // Logging options for events related to the BGP neighbor or + // group. + LoggingOptions LoggingOptions `mapstructure:"logging-options" json:"logging-options,omitempty"` + // original -> bgp:ebgp-multihop + // eBGP multi-hop parameters for the BGP neighbor or group. + EbgpMultihop EbgpMultihop `mapstructure:"ebgp-multihop" json:"ebgp-multihop,omitempty"` + // original -> bgp:route-reflector + // Route reflector parameters for the BGP neighbor or group. + RouteReflector RouteReflector `mapstructure:"route-reflector" json:"route-reflector,omitempty"` + // original -> bgp:as-path-options + // AS_PATH manipulation parameters for the BGP neighbor or + // group. + AsPathOptions AsPathOptions `mapstructure:"as-path-options" json:"as-path-options,omitempty"` + // original -> bgp:add-paths + // Parameters relating to the advertisement and receipt of + // multiple paths for a single NLRI (add-paths). + AddPaths AddPaths `mapstructure:"add-paths" json:"add-paths,omitempty"` + // original -> bgp:afi-safis + // Per-address-family configuration parameters associated with + // the neighbor or group. + AfiSafis []AfiSafi `mapstructure:"afi-safis" json:"afi-safis,omitempty"` + // original -> bgp:graceful-restart + // Parameters relating the graceful restart mechanism for BGP. + GracefulRestart GracefulRestart `mapstructure:"graceful-restart" json:"graceful-restart,omitempty"` + // original -> rpol:apply-policy + // Anchor point for routing policies in the model. + // Import and export policies are with respect to the local + // routing table, i.e., export (send) and import (receive), + // depending on the context. + ApplyPolicy ApplyPolicy `mapstructure:"apply-policy" json:"apply-policy,omitempty"` + // original -> bgp-mp:use-multiple-paths + // Parameters related to the use of multiple-paths for the same + // NLRI when they are received only from this neighbor. + UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` + // original -> gobgp:route-server + // Configure the local router as a route server. + RouteServer RouteServer `mapstructure:"route-server" json:"route-server,omitempty"` + // original -> gobgp:ttl-security + // Configure TTL Security feature. + TtlSecurity TtlSecurity `mapstructure:"ttl-security" json:"ttl-security,omitempty"` +} + +func (lhs *Neighbor) Equal(rhs *Neighbor) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + if !lhs.Timers.Equal(&(rhs.Timers)) { + return false + } + if !lhs.Transport.Equal(&(rhs.Transport)) { + return false + } + if !lhs.ErrorHandling.Equal(&(rhs.ErrorHandling)) { + return false + } + if !lhs.LoggingOptions.Equal(&(rhs.LoggingOptions)) { + return false + } + if !lhs.EbgpMultihop.Equal(&(rhs.EbgpMultihop)) { + return false + } + if !lhs.RouteReflector.Equal(&(rhs.RouteReflector)) { + return false + } + if !lhs.AsPathOptions.Equal(&(rhs.AsPathOptions)) { + return false + } + if !lhs.AddPaths.Equal(&(rhs.AddPaths)) { + return false + } + if len(lhs.AfiSafis) != len(rhs.AfiSafis) { + return false + } + { + lmap := make(map[string]*AfiSafi) + for i, l := range lhs.AfiSafis { + lmap[mapkey(i, string(l.Config.AfiSafiName))] = &lhs.AfiSafis[i] + } + for i, r := range rhs.AfiSafis { + if l, y := lmap[mapkey(i, string(r.Config.AfiSafiName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if !lhs.GracefulRestart.Equal(&(rhs.GracefulRestart)) { + return false + } + if !lhs.ApplyPolicy.Equal(&(rhs.ApplyPolicy)) { + return false + } + if !lhs.UseMultiplePaths.Equal(&(rhs.UseMultiplePaths)) { + return false + } + if !lhs.RouteServer.Equal(&(rhs.RouteServer)) { + return false + } + if !lhs.TtlSecurity.Equal(&(rhs.TtlSecurity)) { + return false + } + return true +} + +// struct for container gobgp:state. +type LongLivedGracefulRestartState struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:received + // gobgp:received's original type is boolean. + Received bool `mapstructure:"received" json:"received,omitempty"` + // original -> gobgp:advertised + // gobgp:advertised's original type is boolean. + Advertised bool `mapstructure:"advertised" json:"advertised,omitempty"` + // original -> gobgp:peer-restart-time + PeerRestartTime uint32 `mapstructure:"peer-restart-time" json:"peer-restart-time,omitempty"` + // original -> gobgp:peer-restart-timer-expired + // gobgp:peer-restart-timer-expired's original type is boolean. + PeerRestartTimerExpired bool `mapstructure:"peer-restart-timer-expired" json:"peer-restart-timer-expired,omitempty"` +} + +// struct for container gobgp:config. +type LongLivedGracefulRestartConfig struct { + // original -> gobgp:enabled + // gobgp:enabled's original type is boolean. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> gobgp:restart-time + RestartTime uint32 `mapstructure:"restart-time" json:"restart-time,omitempty"` +} + +func (lhs *LongLivedGracefulRestartConfig) Equal(rhs *LongLivedGracefulRestartConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.RestartTime != rhs.RestartTime { + return false + } + return true +} + +// struct for container gobgp:long-lived-graceful-restart. +type LongLivedGracefulRestart struct { + // original -> gobgp:long-lived-graceful-restart-config + Config LongLivedGracefulRestartConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:long-lived-graceful-restart-state + State LongLivedGracefulRestartState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *LongLivedGracefulRestart) Equal(rhs *LongLivedGracefulRestart) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container gobgp:state. +type RouteTargetMembershipState struct { + // original -> gobgp:deferral-time + DeferralTime uint16 `mapstructure:"deferral-time" json:"deferral-time,omitempty"` +} + +// struct for container gobgp:config. +type RouteTargetMembershipConfig struct { + // original -> gobgp:deferral-time + DeferralTime uint16 `mapstructure:"deferral-time" json:"deferral-time,omitempty"` +} + +func (lhs *RouteTargetMembershipConfig) Equal(rhs *RouteTargetMembershipConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.DeferralTime != rhs.DeferralTime { + return false + } + return true +} + +// struct for container gobgp:route-target-membership. +type RouteTargetMembership struct { + // original -> gobgp:route-target-membership-config + Config RouteTargetMembershipConfig `mapstructure:"config" json:"config,omitempty"` + // original -> gobgp:route-target-membership-state + State RouteTargetMembershipState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *RouteTargetMembership) Equal(rhs *RouteTargetMembership) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:l2vpn-evpn. +// BGP EVPN configuration options. +type L2vpnEvpn struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L2vpnEvpn) Equal(rhs *L2vpnEvpn) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:l2vpn-vpls. +// BGP-signalled VPLS configuration options. +type L2vpnVpls struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L2vpnVpls) Equal(rhs *L2vpnVpls) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:l3vpn-ipv6-multicast. +// Multicast IPv6 L3VPN configuration options. +type L3vpnIpv6Multicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L3vpnIpv6Multicast) Equal(rhs *L3vpnIpv6Multicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:l3vpn-ipv4-multicast. +// Multicast IPv4 L3VPN configuration options. +type L3vpnIpv4Multicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L3vpnIpv4Multicast) Equal(rhs *L3vpnIpv4Multicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:l3vpn-ipv6-unicast. +// Unicast IPv6 L3VPN configuration options. +type L3vpnIpv6Unicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L3vpnIpv6Unicast) Equal(rhs *L3vpnIpv6Unicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:l3vpn-ipv4-unicast. +// Unicast IPv4 L3VPN configuration options. +type L3vpnIpv4Unicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *L3vpnIpv4Unicast) Equal(rhs *L3vpnIpv4Unicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:ipv6-labelled-unicast. +// IPv6 Labelled Unicast configuration options. +type Ipv6LabelledUnicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *Ipv6LabelledUnicast) Equal(rhs *Ipv6LabelledUnicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:ipv4-labelled-unicast. +// IPv4 Labelled Unicast configuration options. +type Ipv4LabelledUnicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` +} + +func (lhs *Ipv4LabelledUnicast) Equal(rhs *Ipv4LabelledUnicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information for common IPv4 and IPv6 unicast +// parameters. +type Ipv6UnicastState struct { + // original -> bgp-mp:send-default-route + // bgp-mp:send-default-route's original type is boolean. + // If set to true, send the default-route to the neighbour(s). + SendDefaultRoute bool `mapstructure:"send-default-route" json:"send-default-route,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters for common IPv4 and IPv6 unicast +// AFI-SAFI options. +type Ipv6UnicastConfig struct { + // original -> bgp-mp:send-default-route + // bgp-mp:send-default-route's original type is boolean. + // If set to true, send the default-route to the neighbour(s). + SendDefaultRoute bool `mapstructure:"send-default-route" json:"send-default-route,omitempty"` +} + +func (lhs *Ipv6UnicastConfig) Equal(rhs *Ipv6UnicastConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.SendDefaultRoute != rhs.SendDefaultRoute { + return false + } + return true +} + +// struct for container bgp-mp:ipv6-unicast. +// IPv6 unicast configuration options. +type Ipv6Unicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` + // original -> bgp-mp:ipv6-unicast-config + // Configuration parameters for common IPv4 and IPv6 unicast + // AFI-SAFI options. + Config Ipv6UnicastConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:ipv6-unicast-state + // State information for common IPv4 and IPv6 unicast + // parameters. + State Ipv6UnicastState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Ipv6Unicast) Equal(rhs *Ipv6Unicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information for common IPv4 and IPv6 unicast +// parameters. +type Ipv4UnicastState struct { + // original -> bgp-mp:send-default-route + // bgp-mp:send-default-route's original type is boolean. + // If set to true, send the default-route to the neighbour(s). + SendDefaultRoute bool `mapstructure:"send-default-route" json:"send-default-route,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters for common IPv4 and IPv6 unicast +// AFI-SAFI options. +type Ipv4UnicastConfig struct { + // original -> bgp-mp:send-default-route + // bgp-mp:send-default-route's original type is boolean. + // If set to true, send the default-route to the neighbour(s). + SendDefaultRoute bool `mapstructure:"send-default-route" json:"send-default-route,omitempty"` +} + +func (lhs *Ipv4UnicastConfig) Equal(rhs *Ipv4UnicastConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.SendDefaultRoute != rhs.SendDefaultRoute { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information relating to the prefix-limit for the +// AFI-SAFI. +type PrefixLimitState struct { + // original -> bgp-mp:max-prefixes + // Maximum number of prefixes that will be accepted + // from the neighbour. + MaxPrefixes uint32 `mapstructure:"max-prefixes" json:"max-prefixes,omitempty"` + // original -> bgp-mp:shutdown-threshold-pct + // Threshold on number of prefixes that can be received + // from a neighbour before generation of warning messages + // or log entries. Expressed as a percentage of + // max-prefixes. + ShutdownThresholdPct Percentage `mapstructure:"shutdown-threshold-pct" json:"shutdown-threshold-pct,omitempty"` + // original -> bgp-mp:restart-timer + // bgp-mp:restart-timer's original type is decimal64. + // Time interval in seconds after which the BGP session + // is re-established after being torn down due to exceeding + // the max-prefix limit. + RestartTimer float64 `mapstructure:"restart-timer" json:"restart-timer,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters relating to the prefix +// limit for the AFI-SAFI. +type PrefixLimitConfig struct { + // original -> bgp-mp:max-prefixes + // Maximum number of prefixes that will be accepted + // from the neighbour. + MaxPrefixes uint32 `mapstructure:"max-prefixes" json:"max-prefixes,omitempty"` + // original -> bgp-mp:shutdown-threshold-pct + // Threshold on number of prefixes that can be received + // from a neighbour before generation of warning messages + // or log entries. Expressed as a percentage of + // max-prefixes. + ShutdownThresholdPct Percentage `mapstructure:"shutdown-threshold-pct" json:"shutdown-threshold-pct,omitempty"` + // original -> bgp-mp:restart-timer + // bgp-mp:restart-timer's original type is decimal64. + // Time interval in seconds after which the BGP session + // is re-established after being torn down due to exceeding + // the max-prefix limit. + RestartTimer float64 `mapstructure:"restart-timer" json:"restart-timer,omitempty"` +} + +func (lhs *PrefixLimitConfig) Equal(rhs *PrefixLimitConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.MaxPrefixes != rhs.MaxPrefixes { + return false + } + if lhs.ShutdownThresholdPct != rhs.ShutdownThresholdPct { + return false + } + if lhs.RestartTimer != rhs.RestartTimer { + return false + } + return true +} + +// struct for container bgp-mp:prefix-limit. +// Configure the maximum number of prefixes that will be +// accepted from a peer. +type PrefixLimit struct { + // original -> bgp-mp:prefix-limit-config + // Configuration parameters relating to the prefix + // limit for the AFI-SAFI. + Config PrefixLimitConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:prefix-limit-state + // State information relating to the prefix-limit for the + // AFI-SAFI. + State PrefixLimitState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *PrefixLimit) Equal(rhs *PrefixLimit) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:ipv4-unicast. +// IPv4 unicast configuration options. +type Ipv4Unicast struct { + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` + // original -> bgp-mp:ipv4-unicast-config + // Configuration parameters for common IPv4 and IPv6 unicast + // AFI-SAFI options. + Config Ipv4UnicastConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:ipv4-unicast-state + // State information for common IPv4 and IPv6 unicast + // parameters. + State Ipv4UnicastState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Ipv4Unicast) Equal(rhs *Ipv4Unicast) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container rpol:state. +// Operational state for routing policy. +type ApplyPolicyState struct { + // original -> rpol:import-policy + // list of policy names in sequence to be applied on + // receiving a routing update in the current context, e.g., + // for the current peer group, neighbor, address family, + // etc. + ImportPolicyList []string `mapstructure:"import-policy-list" json:"import-policy-list,omitempty"` + // original -> rpol:default-import-policy + // explicitly set a default policy if no policy definition + // in the import policy chain is satisfied. + DefaultImportPolicy DefaultPolicyType `mapstructure:"default-import-policy" json:"default-import-policy,omitempty"` + // original -> rpol:export-policy + // list of policy names in sequence to be applied on + // sending a routing update in the current context, e.g., + // for the current peer group, neighbor, address family, + // etc. + ExportPolicyList []string `mapstructure:"export-policy-list" json:"export-policy-list,omitempty"` + // original -> rpol:default-export-policy + // explicitly set a default policy if no policy definition + // in the export policy chain is satisfied. + DefaultExportPolicy DefaultPolicyType `mapstructure:"default-export-policy" json:"default-export-policy,omitempty"` + // original -> gobgp:in-policy + // list of policy names in sequence to be applied on + // sending a routing update in the current context, e.g., + // for the current other route server clients. + InPolicyList []string `mapstructure:"in-policy-list" json:"in-policy-list,omitempty"` + // original -> gobgp:default-in-policy + // explicitly set a default policy if no policy definition + // in the in-policy chain is satisfied. + DefaultInPolicy DefaultPolicyType `mapstructure:"default-in-policy" json:"default-in-policy,omitempty"` +} + +// struct for container rpol:config. +// Policy configuration data. +type ApplyPolicyConfig struct { + // original -> rpol:import-policy + // list of policy names in sequence to be applied on + // receiving a routing update in the current context, e.g., + // for the current peer group, neighbor, address family, + // etc. + ImportPolicyList []string `mapstructure:"import-policy-list" json:"import-policy-list,omitempty"` + // original -> rpol:default-import-policy + // explicitly set a default policy if no policy definition + // in the import policy chain is satisfied. + DefaultImportPolicy DefaultPolicyType `mapstructure:"default-import-policy" json:"default-import-policy,omitempty"` + // original -> rpol:export-policy + // list of policy names in sequence to be applied on + // sending a routing update in the current context, e.g., + // for the current peer group, neighbor, address family, + // etc. + ExportPolicyList []string `mapstructure:"export-policy-list" json:"export-policy-list,omitempty"` + // original -> rpol:default-export-policy + // explicitly set a default policy if no policy definition + // in the export policy chain is satisfied. + DefaultExportPolicy DefaultPolicyType `mapstructure:"default-export-policy" json:"default-export-policy,omitempty"` + // original -> gobgp:in-policy + // list of policy names in sequence to be applied on + // sending a routing update in the current context, e.g., + // for the current other route server clients. + InPolicyList []string `mapstructure:"in-policy-list" json:"in-policy-list,omitempty"` + // original -> gobgp:default-in-policy + // explicitly set a default policy if no policy definition + // in the in-policy chain is satisfied. + DefaultInPolicy DefaultPolicyType `mapstructure:"default-in-policy" json:"default-in-policy,omitempty"` +} + +func (lhs *ApplyPolicyConfig) Equal(rhs *ApplyPolicyConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.ImportPolicyList) != len(rhs.ImportPolicyList) { + return false + } + for idx, l := range lhs.ImportPolicyList { + if l != rhs.ImportPolicyList[idx] { + return false + } + } + if lhs.DefaultImportPolicy != rhs.DefaultImportPolicy { + return false + } + if len(lhs.ExportPolicyList) != len(rhs.ExportPolicyList) { + return false + } + for idx, l := range lhs.ExportPolicyList { + if l != rhs.ExportPolicyList[idx] { + return false + } + } + if lhs.DefaultExportPolicy != rhs.DefaultExportPolicy { + return false + } + if len(lhs.InPolicyList) != len(rhs.InPolicyList) { + return false + } + for idx, l := range lhs.InPolicyList { + if l != rhs.InPolicyList[idx] { + return false + } + } + if lhs.DefaultInPolicy != rhs.DefaultInPolicy { + return false + } + return true +} + +// struct for container rpol:apply-policy. +// Anchor point for routing policies in the model. +// Import and export policies are with respect to the local +// routing table, i.e., export (send) and import (receive), +// depending on the context. +type ApplyPolicy struct { + // original -> rpol:apply-policy-config + // Policy configuration data. + Config ApplyPolicyConfig `mapstructure:"config" json:"config,omitempty"` + // original -> rpol:apply-policy-state + // Operational state for routing policy. + State ApplyPolicyState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *ApplyPolicy) Equal(rhs *ApplyPolicy) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information relating to the AFI-SAFI. +type AfiSafiState struct { + // original -> bgp-mp:afi-safi-name + // AFI,SAFI. + AfiSafiName AfiSafiType `mapstructure:"afi-safi-name" json:"afi-safi-name,omitempty"` + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // This leaf indicates whether the IPv4 Unicast AFI,SAFI is + // enabled for the neighbour or group. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp-op:total-paths + // Total number of BGP paths within the context. + TotalPaths uint32 `mapstructure:"total-paths" json:"total-paths,omitempty"` + // original -> bgp-op:total-prefixes + // . + TotalPrefixes uint32 `mapstructure:"total-prefixes" json:"total-prefixes,omitempty"` + // original -> gobgp:family + // gobgp:family's original type is route-family. + // Address family value of AFI-SAFI pair translated from afi-safi-name. + Family bgp.RouteFamily `mapstructure:"family" json:"family,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters for the AFI-SAFI. +type AfiSafiConfig struct { + // original -> bgp-mp:afi-safi-name + // AFI,SAFI. + AfiSafiName AfiSafiType `mapstructure:"afi-safi-name" json:"afi-safi-name,omitempty"` + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // This leaf indicates whether the IPv4 Unicast AFI,SAFI is + // enabled for the neighbour or group. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` +} + +func (lhs *AfiSafiConfig) Equal(rhs *AfiSafiConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AfiSafiName != rhs.AfiSafiName { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information for BGP graceful-restart. +type MpGracefulRestartState struct { + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // This leaf indicates whether graceful-restart is enabled for + // this AFI-SAFI. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp-op:received + // bgp-op:received's original type is boolean. + // This leaf indicates whether the neighbor advertised the + // ability to support graceful-restart for this AFI-SAFI. + Received bool `mapstructure:"received" json:"received,omitempty"` + // original -> bgp-op:advertised + // bgp-op:advertised's original type is boolean. + // This leaf indicates whether the ability to support + // graceful-restart has been advertised to the peer. + Advertised bool `mapstructure:"advertised" json:"advertised,omitempty"` + // original -> gobgp:end-of-rib-received + // gobgp:end-of-rib-received's original type is boolean. + EndOfRibReceived bool `mapstructure:"end-of-rib-received" json:"end-of-rib-received,omitempty"` + // original -> gobgp:end-of-rib-sent + // gobgp:end-of-rib-sent's original type is boolean. + EndOfRibSent bool `mapstructure:"end-of-rib-sent" json:"end-of-rib-sent,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration options for BGP graceful-restart. +type MpGracefulRestartConfig struct { + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // This leaf indicates whether graceful-restart is enabled for + // this AFI-SAFI. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` +} + +func (lhs *MpGracefulRestartConfig) Equal(rhs *MpGracefulRestartConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + return true +} + +// struct for container bgp-mp:graceful-restart. +// Parameters relating to BGP graceful-restart. +type MpGracefulRestart struct { + // original -> bgp-mp:mp-graceful-restart-config + // Configuration options for BGP graceful-restart. + Config MpGracefulRestartConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:mp-graceful-restart-state + // State information for BGP graceful-restart. + State MpGracefulRestartState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *MpGracefulRestart) Equal(rhs *MpGracefulRestart) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:afi-safi. +// AFI,SAFI configuration available for the +// neighbour or group. +type AfiSafi struct { + // original -> bgp-mp:afi-safi-name + // original -> bgp-mp:mp-graceful-restart + // Parameters relating to BGP graceful-restart. + MpGracefulRestart MpGracefulRestart `mapstructure:"mp-graceful-restart" json:"mp-graceful-restart,omitempty"` + // original -> bgp-mp:afi-safi-config + // Configuration parameters for the AFI-SAFI. + Config AfiSafiConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:afi-safi-state + // State information relating to the AFI-SAFI. + State AfiSafiState `mapstructure:"state" json:"state,omitempty"` + // original -> rpol:apply-policy + // Anchor point for routing policies in the model. + // Import and export policies are with respect to the local + // routing table, i.e., export (send) and import (receive), + // depending on the context. + ApplyPolicy ApplyPolicy `mapstructure:"apply-policy" json:"apply-policy,omitempty"` + // original -> bgp-mp:ipv4-unicast + // IPv4 unicast configuration options. + Ipv4Unicast Ipv4Unicast `mapstructure:"ipv4-unicast" json:"ipv4-unicast,omitempty"` + // original -> bgp-mp:ipv6-unicast + // IPv6 unicast configuration options. + Ipv6Unicast Ipv6Unicast `mapstructure:"ipv6-unicast" json:"ipv6-unicast,omitempty"` + // original -> bgp-mp:ipv4-labelled-unicast + // IPv4 Labelled Unicast configuration options. + Ipv4LabelledUnicast Ipv4LabelledUnicast `mapstructure:"ipv4-labelled-unicast" json:"ipv4-labelled-unicast,omitempty"` + // original -> bgp-mp:ipv6-labelled-unicast + // IPv6 Labelled Unicast configuration options. + Ipv6LabelledUnicast Ipv6LabelledUnicast `mapstructure:"ipv6-labelled-unicast" json:"ipv6-labelled-unicast,omitempty"` + // original -> bgp-mp:l3vpn-ipv4-unicast + // Unicast IPv4 L3VPN configuration options. + L3vpnIpv4Unicast L3vpnIpv4Unicast `mapstructure:"l3vpn-ipv4-unicast" json:"l3vpn-ipv4-unicast,omitempty"` + // original -> bgp-mp:l3vpn-ipv6-unicast + // Unicast IPv6 L3VPN configuration options. + L3vpnIpv6Unicast L3vpnIpv6Unicast `mapstructure:"l3vpn-ipv6-unicast" json:"l3vpn-ipv6-unicast,omitempty"` + // original -> bgp-mp:l3vpn-ipv4-multicast + // Multicast IPv4 L3VPN configuration options. + L3vpnIpv4Multicast L3vpnIpv4Multicast `mapstructure:"l3vpn-ipv4-multicast" json:"l3vpn-ipv4-multicast,omitempty"` + // original -> bgp-mp:l3vpn-ipv6-multicast + // Multicast IPv6 L3VPN configuration options. + L3vpnIpv6Multicast L3vpnIpv6Multicast `mapstructure:"l3vpn-ipv6-multicast" json:"l3vpn-ipv6-multicast,omitempty"` + // original -> bgp-mp:l2vpn-vpls + // BGP-signalled VPLS configuration options. + L2vpnVpls L2vpnVpls `mapstructure:"l2vpn-vpls" json:"l2vpn-vpls,omitempty"` + // original -> bgp-mp:l2vpn-evpn + // BGP EVPN configuration options. + L2vpnEvpn L2vpnEvpn `mapstructure:"l2vpn-evpn" json:"l2vpn-evpn,omitempty"` + // original -> bgp-mp:route-selection-options + // Parameters relating to options for route selection. + RouteSelectionOptions RouteSelectionOptions `mapstructure:"route-selection-options" json:"route-selection-options,omitempty"` + // original -> bgp-mp:use-multiple-paths + // Parameters related to the use of multiple paths for the + // same NLRI. + UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` + // original -> bgp-mp:prefix-limit + // Configure the maximum number of prefixes that will be + // accepted from a peer. + PrefixLimit PrefixLimit `mapstructure:"prefix-limit" json:"prefix-limit,omitempty"` + // original -> gobgp:route-target-membership + RouteTargetMembership RouteTargetMembership `mapstructure:"route-target-membership" json:"route-target-membership,omitempty"` + // original -> gobgp:long-lived-graceful-restart + LongLivedGracefulRestart LongLivedGracefulRestart `mapstructure:"long-lived-graceful-restart" json:"long-lived-graceful-restart,omitempty"` + // original -> gobgp:add-paths + // add-paths configuration options related to a particular AFI-SAFI. + AddPaths AddPaths `mapstructure:"add-paths" json:"add-paths,omitempty"` + // original -> bgp-mp:ipv4-mup +} + +func (lhs *AfiSafi) Equal(rhs *AfiSafi) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.MpGracefulRestart.Equal(&(rhs.MpGracefulRestart)) { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + if !lhs.ApplyPolicy.Equal(&(rhs.ApplyPolicy)) { + return false + } + if !lhs.Ipv4Unicast.Equal(&(rhs.Ipv4Unicast)) { + return false + } + if !lhs.Ipv6Unicast.Equal(&(rhs.Ipv6Unicast)) { + return false + } + if !lhs.Ipv4LabelledUnicast.Equal(&(rhs.Ipv4LabelledUnicast)) { + return false + } + if !lhs.Ipv6LabelledUnicast.Equal(&(rhs.Ipv6LabelledUnicast)) { + return false + } + if !lhs.L3vpnIpv4Unicast.Equal(&(rhs.L3vpnIpv4Unicast)) { + return false + } + if !lhs.L3vpnIpv6Unicast.Equal(&(rhs.L3vpnIpv6Unicast)) { + return false + } + if !lhs.L3vpnIpv4Multicast.Equal(&(rhs.L3vpnIpv4Multicast)) { + return false + } + if !lhs.L3vpnIpv6Multicast.Equal(&(rhs.L3vpnIpv6Multicast)) { + return false + } + if !lhs.L2vpnVpls.Equal(&(rhs.L2vpnVpls)) { + return false + } + if !lhs.L2vpnEvpn.Equal(&(rhs.L2vpnEvpn)) { + return false + } + if !lhs.RouteSelectionOptions.Equal(&(rhs.RouteSelectionOptions)) { + return false + } + if !lhs.UseMultiplePaths.Equal(&(rhs.UseMultiplePaths)) { + return false + } + if !lhs.PrefixLimit.Equal(&(rhs.PrefixLimit)) { + return false + } + if !lhs.RouteTargetMembership.Equal(&(rhs.RouteTargetMembership)) { + return false + } + if !lhs.LongLivedGracefulRestart.Equal(&(rhs.LongLivedGracefulRestart)) { + return false + } + if !lhs.AddPaths.Equal(&(rhs.AddPaths)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information associated with graceful-restart. +type GracefulRestartState struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // Enable or disable the graceful-restart capability. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:restart-time + // Estimated time (in seconds) for the local BGP speaker to + // restart a session. This value is advertise in the graceful + // restart BGP capability. This is a 12-bit value, referred to + // as Restart Time in RFC4724. Per RFC4724, the suggested + // default value is <= the hold-time value. + RestartTime uint16 `mapstructure:"restart-time" json:"restart-time,omitempty"` + // original -> bgp:stale-routes-time + // bgp:stale-routes-time's original type is decimal64. + // An upper-bound on the time thate stale routes will be + // retained by a router after a session is restarted. If an + // End-of-RIB (EOR) marker is received prior to this timer + // expiring stale-routes will be flushed upon its receipt - if + // no EOR is received, then when this timer expires stale paths + // will be purged. This timer is referred to as the + // Selection_Deferral_Timer in RFC4724. + StaleRoutesTime float64 `mapstructure:"stale-routes-time" json:"stale-routes-time,omitempty"` + // original -> bgp:helper-only + // bgp:helper-only's original type is boolean. + // Enable graceful-restart in helper mode only. When this + // leaf is set, the local system does not retain forwarding + // its own state during a restart, but supports procedures + // for the receiving speaker, as defined in RFC4724. + HelperOnly bool `mapstructure:"helper-only" json:"helper-only,omitempty"` + // original -> bgp-op:peer-restart-time + // The period of time (advertised by the peer) that + // the peer expects a restart of a BGP session to + // take. + PeerRestartTime uint16 `mapstructure:"peer-restart-time" json:"peer-restart-time,omitempty"` + // original -> bgp-op:peer-restarting + // bgp-op:peer-restarting's original type is boolean. + // This flag indicates whether the remote neighbor is currently + // in the process of restarting, and hence received routes are + // currently stale. + PeerRestarting bool `mapstructure:"peer-restarting" json:"peer-restarting,omitempty"` + // original -> bgp-op:local-restarting + // bgp-op:local-restarting's original type is boolean. + // This flag indicates whether the local neighbor is currently + // restarting. The flag is unset after all NLRI have been + // advertised to the peer, and the End-of-RIB (EOR) marker has + // been unset. + LocalRestarting bool `mapstructure:"local-restarting" json:"local-restarting,omitempty"` + // original -> bgp-op:mode + // Ths leaf indicates the mode of operation of BGP graceful + // restart with the peer. + Mode Mode `mapstructure:"mode" json:"mode,omitempty"` + // original -> gobgp:deferral-time + DeferralTime uint16 `mapstructure:"deferral-time" json:"deferral-time,omitempty"` + // original -> gobgp:notification-enabled + // gobgp:notification-enabled's original type is boolean. + NotificationEnabled bool `mapstructure:"notification-enabled" json:"notification-enabled,omitempty"` + // original -> gobgp:long-lived-enabled + // gobgp:long-lived-enabled's original type is boolean. + LongLivedEnabled bool `mapstructure:"long-lived-enabled" json:"long-lived-enabled,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to graceful-restart. +type GracefulRestartConfig struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // Enable or disable the graceful-restart capability. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:restart-time + // Estimated time (in seconds) for the local BGP speaker to + // restart a session. This value is advertise in the graceful + // restart BGP capability. This is a 12-bit value, referred to + // as Restart Time in RFC4724. Per RFC4724, the suggested + // default value is <= the hold-time value. + RestartTime uint16 `mapstructure:"restart-time" json:"restart-time,omitempty"` + // original -> bgp:stale-routes-time + // bgp:stale-routes-time's original type is decimal64. + // An upper-bound on the time thate stale routes will be + // retained by a router after a session is restarted. If an + // End-of-RIB (EOR) marker is received prior to this timer + // expiring stale-routes will be flushed upon its receipt - if + // no EOR is received, then when this timer expires stale paths + // will be purged. This timer is referred to as the + // Selection_Deferral_Timer in RFC4724. + StaleRoutesTime float64 `mapstructure:"stale-routes-time" json:"stale-routes-time,omitempty"` + // original -> bgp:helper-only + // bgp:helper-only's original type is boolean. + // Enable graceful-restart in helper mode only. When this + // leaf is set, the local system does not retain forwarding + // its own state during a restart, but supports procedures + // for the receiving speaker, as defined in RFC4724. + HelperOnly bool `mapstructure:"helper-only" json:"helper-only,omitempty"` + // original -> gobgp:deferral-time + DeferralTime uint16 `mapstructure:"deferral-time" json:"deferral-time,omitempty"` + // original -> gobgp:notification-enabled + // gobgp:notification-enabled's original type is boolean. + NotificationEnabled bool `mapstructure:"notification-enabled" json:"notification-enabled,omitempty"` + // original -> gobgp:long-lived-enabled + // gobgp:long-lived-enabled's original type is boolean. + LongLivedEnabled bool `mapstructure:"long-lived-enabled" json:"long-lived-enabled,omitempty"` +} + +func (lhs *GracefulRestartConfig) Equal(rhs *GracefulRestartConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.RestartTime != rhs.RestartTime { + return false + } + if lhs.StaleRoutesTime != rhs.StaleRoutesTime { + return false + } + if lhs.HelperOnly != rhs.HelperOnly { + return false + } + if lhs.DeferralTime != rhs.DeferralTime { + return false + } + if lhs.NotificationEnabled != rhs.NotificationEnabled { + return false + } + if lhs.LongLivedEnabled != rhs.LongLivedEnabled { + return false + } + return true +} + +// struct for container bgp:graceful-restart. +// Parameters relating the graceful restart mechanism for BGP. +type GracefulRestart struct { + // original -> bgp:graceful-restart-config + // Configuration parameters relating to graceful-restart. + Config GracefulRestartConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:graceful-restart-state + // State information associated with graceful-restart. + State GracefulRestartState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *GracefulRestart) Equal(rhs *GracefulRestart) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information relating to iBGP multipath. +type IbgpState struct { + // original -> bgp-mp:maximum-paths + // Maximum number of parallel paths to consider when using + // iBGP multipath. The default is to use a single path. + MaximumPaths uint32 `mapstructure:"maximum-paths" json:"maximum-paths,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters relating to iBGP multipath. +type IbgpConfig struct { + // original -> bgp-mp:maximum-paths + // Maximum number of parallel paths to consider when using + // iBGP multipath. The default is to use a single path. + MaximumPaths uint32 `mapstructure:"maximum-paths" json:"maximum-paths,omitempty"` +} + +func (lhs *IbgpConfig) Equal(rhs *IbgpConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.MaximumPaths != rhs.MaximumPaths { + return false + } + return true +} + +// struct for container bgp-mp:ibgp. +// Multipath parameters for iBGP. +type Ibgp struct { + // original -> bgp-mp:ibgp-config + // Configuration parameters relating to iBGP multipath. + Config IbgpConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:ibgp-state + // State information relating to iBGP multipath. + State IbgpState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Ibgp) Equal(rhs *Ibgp) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information relating to eBGP multipath. +type EbgpState struct { + // original -> bgp-mp:allow-multiple-as + // bgp-mp:allow-multiple-as's original type is boolean. + // Allow multipath to use paths from different neighbouring + // ASes. The default is to only consider multiple paths from + // the same neighbouring AS. + AllowMultipleAs bool `mapstructure:"allow-multiple-as" json:"allow-multiple-as,omitempty"` + // original -> bgp-mp:maximum-paths + // Maximum number of parallel paths to consider when using + // BGP multipath. The default is use a single path. + MaximumPaths uint32 `mapstructure:"maximum-paths" json:"maximum-paths,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters relating to eBGP multipath. +type EbgpConfig struct { + // original -> bgp-mp:allow-multiple-as + // bgp-mp:allow-multiple-as's original type is boolean. + // Allow multipath to use paths from different neighbouring + // ASes. The default is to only consider multiple paths from + // the same neighbouring AS. + AllowMultipleAs bool `mapstructure:"allow-multiple-as" json:"allow-multiple-as,omitempty"` + // original -> bgp-mp:maximum-paths + // Maximum number of parallel paths to consider when using + // BGP multipath. The default is use a single path. + MaximumPaths uint32 `mapstructure:"maximum-paths" json:"maximum-paths,omitempty"` +} + +func (lhs *EbgpConfig) Equal(rhs *EbgpConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AllowMultipleAs != rhs.AllowMultipleAs { + return false + } + if lhs.MaximumPaths != rhs.MaximumPaths { + return false + } + return true +} + +// struct for container bgp-mp:ebgp. +// Multipath parameters for eBGP. +type Ebgp struct { + // original -> bgp-mp:ebgp-config + // Configuration parameters relating to eBGP multipath. + Config EbgpConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:ebgp-state + // State information relating to eBGP multipath. + State EbgpState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Ebgp) Equal(rhs *Ebgp) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State parameters relating to multipath. +type UseMultiplePathsState struct { + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // Whether the use of multiple paths for the same NLRI is + // enabled for the neighbor. This value is overridden by + // any more specific configuration value. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters relating to multipath. +type UseMultiplePathsConfig struct { + // original -> bgp-mp:enabled + // bgp-mp:enabled's original type is boolean. + // Whether the use of multiple paths for the same NLRI is + // enabled for the neighbor. This value is overridden by + // any more specific configuration value. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` +} + +func (lhs *UseMultiplePathsConfig) Equal(rhs *UseMultiplePathsConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + return true +} + +// struct for container bgp-mp:use-multiple-paths. +// Parameters related to the use of multiple paths for the +// same NLRI. +type UseMultiplePaths struct { + // original -> bgp-mp:use-multiple-paths-config + // Configuration parameters relating to multipath. + Config UseMultiplePathsConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:use-multiple-paths-state + // State parameters relating to multipath. + State UseMultiplePathsState `mapstructure:"state" json:"state,omitempty"` + // original -> bgp-mp:ebgp + // Multipath parameters for eBGP. + Ebgp Ebgp `mapstructure:"ebgp" json:"ebgp,omitempty"` + // original -> bgp-mp:ibgp + // Multipath parameters for iBGP. + Ibgp Ibgp `mapstructure:"ibgp" json:"ibgp,omitempty"` +} + +func (lhs *UseMultiplePaths) Equal(rhs *UseMultiplePaths) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + if !lhs.Ebgp.Equal(&(rhs.Ebgp)) { + return false + } + if !lhs.Ibgp.Equal(&(rhs.Ibgp)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the BGP confederations. +type ConfederationState struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // When this leaf is set to true it indicates that + // the local-AS is part of a BGP confederation. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:identifier + // bgp:identifier's original type is inet:as-number. + // Confederation identifier for the autonomous system. + Identifier uint32 `mapstructure:"identifier" json:"identifier,omitempty"` + // original -> bgp:member-as + // original type is list of inet:as-number + // Remote autonomous systems that are to be treated + // as part of the local confederation. + MemberAsList []uint32 `mapstructure:"member-as-list" json:"member-as-list,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to BGP confederations. +type ConfederationConfig struct { + // original -> bgp:enabled + // bgp:enabled's original type is boolean. + // When this leaf is set to true it indicates that + // the local-AS is part of a BGP confederation. + Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` + // original -> bgp:identifier + // bgp:identifier's original type is inet:as-number. + // Confederation identifier for the autonomous system. + Identifier uint32 `mapstructure:"identifier" json:"identifier,omitempty"` + // original -> bgp:member-as + // original type is list of inet:as-number + // Remote autonomous systems that are to be treated + // as part of the local confederation. + MemberAsList []uint32 `mapstructure:"member-as-list" json:"member-as-list,omitempty"` +} + +func (lhs *ConfederationConfig) Equal(rhs *ConfederationConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Enabled != rhs.Enabled { + return false + } + if lhs.Identifier != rhs.Identifier { + return false + } + if len(lhs.MemberAsList) != len(rhs.MemberAsList) { + return false + } + for idx, l := range lhs.MemberAsList { + if l != rhs.MemberAsList[idx] { + return false + } + } + return true +} + +// struct for container bgp:confederation. +// Parameters indicating whether the local system acts as part +// of a BGP confederation. +type Confederation struct { + // original -> bgp:confederation-config + // Configuration parameters relating to BGP confederations. + Config ConfederationConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:confederation-state + // State information relating to the BGP confederations. + State ConfederationState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *Confederation) Equal(rhs *Confederation) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the default route distance. +type DefaultRouteDistanceState struct { + // original -> bgp:external-route-distance + // Administrative distance for routes learned from external + // BGP (eBGP). + ExternalRouteDistance uint8 `mapstructure:"external-route-distance" json:"external-route-distance,omitempty"` + // original -> bgp:internal-route-distance + // Administrative distance for routes learned from internal + // BGP (iBGP). + InternalRouteDistance uint8 `mapstructure:"internal-route-distance" json:"internal-route-distance,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to the default route +// distance. +type DefaultRouteDistanceConfig struct { + // original -> bgp:external-route-distance + // Administrative distance for routes learned from external + // BGP (eBGP). + ExternalRouteDistance uint8 `mapstructure:"external-route-distance" json:"external-route-distance,omitempty"` + // original -> bgp:internal-route-distance + // Administrative distance for routes learned from internal + // BGP (iBGP). + InternalRouteDistance uint8 `mapstructure:"internal-route-distance" json:"internal-route-distance,omitempty"` +} + +func (lhs *DefaultRouteDistanceConfig) Equal(rhs *DefaultRouteDistanceConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.ExternalRouteDistance != rhs.ExternalRouteDistance { + return false + } + if lhs.InternalRouteDistance != rhs.InternalRouteDistance { + return false + } + return true +} + +// struct for container bgp:default-route-distance. +// Administrative distance (or preference) assigned to +// routes received from different sources +// (external, internal, and local). +type DefaultRouteDistance struct { + // original -> bgp:default-route-distance-config + // Configuration parameters relating to the default route + // distance. + Config DefaultRouteDistanceConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:default-route-distance-state + // State information relating to the default route distance. + State DefaultRouteDistanceState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *DefaultRouteDistance) Equal(rhs *DefaultRouteDistance) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp-mp:state. +// State information for the route selection options. +type RouteSelectionOptionsState struct { + // original -> bgp-mp:always-compare-med + // bgp-mp:always-compare-med's original type is boolean. + // Compare multi-exit discriminator (MED) value from + // different ASes when selecting the best route. The + // default behavior is to only compare MEDs for paths + // received from the same AS. + AlwaysCompareMed bool `mapstructure:"always-compare-med" json:"always-compare-med,omitempty"` + // original -> bgp-mp:ignore-as-path-length + // bgp-mp:ignore-as-path-length's original type is boolean. + // Ignore the AS path length when selecting the best path. + // The default is to use the AS path length and prefer paths + // with shorter length. + IgnoreAsPathLength bool `mapstructure:"ignore-as-path-length" json:"ignore-as-path-length,omitempty"` + // original -> bgp-mp:external-compare-router-id + // bgp-mp:external-compare-router-id's original type is boolean. + // When comparing similar routes received from external + // BGP peers, use the router-id as a criterion to select + // the active path. + ExternalCompareRouterId bool `mapstructure:"external-compare-router-id" json:"external-compare-router-id,omitempty"` + // original -> bgp-mp:advertise-inactive-routes + // bgp-mp:advertise-inactive-routes's original type is boolean. + // Advertise inactive routes to external peers. The + // default is to only advertise active routes. + AdvertiseInactiveRoutes bool `mapstructure:"advertise-inactive-routes" json:"advertise-inactive-routes,omitempty"` + // original -> bgp-mp:enable-aigp + // bgp-mp:enable-aigp's original type is boolean. + // Flag to enable sending / receiving accumulated IGP + // attribute in routing updates. + EnableAigp bool `mapstructure:"enable-aigp" json:"enable-aigp,omitempty"` + // original -> bgp-mp:ignore-next-hop-igp-metric + // bgp-mp:ignore-next-hop-igp-metric's original type is boolean. + // Ignore the IGP metric to the next-hop when calculating + // BGP best-path. The default is to select the route for + // which the metric to the next-hop is lowest. + IgnoreNextHopIgpMetric bool `mapstructure:"ignore-next-hop-igp-metric" json:"ignore-next-hop-igp-metric,omitempty"` + // original -> gobgp:disable-best-path-selection + // gobgp:disable-best-path-selection's original type is boolean. + // Disables best path selection process. + DisableBestPathSelection bool `mapstructure:"disable-best-path-selection" json:"disable-best-path-selection,omitempty"` +} + +// struct for container bgp-mp:config. +// Configuration parameters relating to route selection +// options. +type RouteSelectionOptionsConfig struct { + // original -> bgp-mp:always-compare-med + // bgp-mp:always-compare-med's original type is boolean. + // Compare multi-exit discriminator (MED) value from + // different ASes when selecting the best route. The + // default behavior is to only compare MEDs for paths + // received from the same AS. + AlwaysCompareMed bool `mapstructure:"always-compare-med" json:"always-compare-med,omitempty"` + // original -> bgp-mp:ignore-as-path-length + // bgp-mp:ignore-as-path-length's original type is boolean. + // Ignore the AS path length when selecting the best path. + // The default is to use the AS path length and prefer paths + // with shorter length. + IgnoreAsPathLength bool `mapstructure:"ignore-as-path-length" json:"ignore-as-path-length,omitempty"` + // original -> bgp-mp:external-compare-router-id + // bgp-mp:external-compare-router-id's original type is boolean. + // When comparing similar routes received from external + // BGP peers, use the router-id as a criterion to select + // the active path. + ExternalCompareRouterId bool `mapstructure:"external-compare-router-id" json:"external-compare-router-id,omitempty"` + // original -> bgp-mp:advertise-inactive-routes + // bgp-mp:advertise-inactive-routes's original type is boolean. + // Advertise inactive routes to external peers. The + // default is to only advertise active routes. + AdvertiseInactiveRoutes bool `mapstructure:"advertise-inactive-routes" json:"advertise-inactive-routes,omitempty"` + // original -> bgp-mp:enable-aigp + // bgp-mp:enable-aigp's original type is boolean. + // Flag to enable sending / receiving accumulated IGP + // attribute in routing updates. + EnableAigp bool `mapstructure:"enable-aigp" json:"enable-aigp,omitempty"` + // original -> bgp-mp:ignore-next-hop-igp-metric + // bgp-mp:ignore-next-hop-igp-metric's original type is boolean. + // Ignore the IGP metric to the next-hop when calculating + // BGP best-path. The default is to select the route for + // which the metric to the next-hop is lowest. + IgnoreNextHopIgpMetric bool `mapstructure:"ignore-next-hop-igp-metric" json:"ignore-next-hop-igp-metric,omitempty"` + // original -> gobgp:disable-best-path-selection + // gobgp:disable-best-path-selection's original type is boolean. + // Disables best path selection process. + DisableBestPathSelection bool `mapstructure:"disable-best-path-selection" json:"disable-best-path-selection,omitempty"` +} + +func (lhs *RouteSelectionOptionsConfig) Equal(rhs *RouteSelectionOptionsConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AlwaysCompareMed != rhs.AlwaysCompareMed { + return false + } + if lhs.IgnoreAsPathLength != rhs.IgnoreAsPathLength { + return false + } + if lhs.ExternalCompareRouterId != rhs.ExternalCompareRouterId { + return false + } + if lhs.AdvertiseInactiveRoutes != rhs.AdvertiseInactiveRoutes { + return false + } + if lhs.EnableAigp != rhs.EnableAigp { + return false + } + if lhs.IgnoreNextHopIgpMetric != rhs.IgnoreNextHopIgpMetric { + return false + } + if lhs.DisableBestPathSelection != rhs.DisableBestPathSelection { + return false + } + return true +} + +// struct for container bgp-mp:route-selection-options. +// Parameters relating to options for route selection. +type RouteSelectionOptions struct { + // original -> bgp-mp:route-selection-options-config + // Configuration parameters relating to route selection + // options. + Config RouteSelectionOptionsConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp-mp:route-selection-options-state + // State information for the route selection options. + State RouteSelectionOptionsState `mapstructure:"state" json:"state,omitempty"` +} + +func (lhs *RouteSelectionOptions) Equal(rhs *RouteSelectionOptions) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + return true +} + +// struct for container bgp:state. +// State information relating to the global BGP router. +type GlobalState struct { + // original -> bgp:as + // bgp:as's original type is inet:as-number. + // Local autonomous system number of the router. Uses + // the 32-bit as-number type from the model in RFC 6991. + As uint32 `mapstructure:"as" json:"as,omitempty"` + // original -> bgp:router-id + // bgp:router-id's original type is inet:ipv4-address. + // Router id of the router, expressed as an + // 32-bit value, IPv4 address. + RouterId string `mapstructure:"router-id" json:"router-id,omitempty"` + // original -> bgp-op:total-paths + // Total number of BGP paths within the context. + TotalPaths uint32 `mapstructure:"total-paths" json:"total-paths,omitempty"` + // original -> bgp-op:total-prefixes + // . + TotalPrefixes uint32 `mapstructure:"total-prefixes" json:"total-prefixes,omitempty"` + // original -> gobgp:port + Port int32 `mapstructure:"port" json:"port,omitempty"` + // original -> gobgp:local-address + LocalAddressList []string `mapstructure:"local-address-list" json:"local-address-list,omitempty"` +} + +// struct for container bgp:config. +// Configuration parameters relating to the global BGP router. +type GlobalConfig struct { + // original -> bgp:as + // bgp:as's original type is inet:as-number. + // Local autonomous system number of the router. Uses + // the 32-bit as-number type from the model in RFC 6991. + As uint32 `mapstructure:"as" json:"as,omitempty"` + // original -> bgp:router-id + // bgp:router-id's original type is inet:ipv4-address. + // Router id of the router, expressed as an + // 32-bit value, IPv4 address. + RouterId string `mapstructure:"router-id" json:"router-id,omitempty"` + // original -> gobgp:port + Port int32 `mapstructure:"port" json:"port,omitempty"` + // original -> gobgp:local-address + LocalAddressList []string `mapstructure:"local-address-list" json:"local-address-list,omitempty"` +} + +func (lhs *GlobalConfig) Equal(rhs *GlobalConfig) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.As != rhs.As { + return false + } + if lhs.RouterId != rhs.RouterId { + return false + } + if lhs.Port != rhs.Port { + return false + } + if len(lhs.LocalAddressList) != len(rhs.LocalAddressList) { + return false + } + for idx, l := range lhs.LocalAddressList { + if l != rhs.LocalAddressList[idx] { + return false + } + } + return true +} + +// struct for container bgp:global. +// Global configuration for the BGP router. +type Global struct { + // original -> bgp:global-config + // Configuration parameters relating to the global BGP router. + Config GlobalConfig `mapstructure:"config" json:"config,omitempty"` + // original -> bgp:global-state + // State information relating to the global BGP router. + State GlobalState `mapstructure:"state" json:"state,omitempty"` + // original -> bgp-mp:route-selection-options + // Parameters relating to options for route selection. + RouteSelectionOptions RouteSelectionOptions `mapstructure:"route-selection-options" json:"route-selection-options,omitempty"` + // original -> bgp:default-route-distance + // Administrative distance (or preference) assigned to + // routes received from different sources + // (external, internal, and local). + DefaultRouteDistance DefaultRouteDistance `mapstructure:"default-route-distance" json:"default-route-distance,omitempty"` + // original -> bgp:confederation + // Parameters indicating whether the local system acts as part + // of a BGP confederation. + Confederation Confederation `mapstructure:"confederation" json:"confederation,omitempty"` + // original -> bgp-mp:use-multiple-paths + // Parameters related to the use of multiple paths for the + // same NLRI. + UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` + // original -> bgp:graceful-restart + // Parameters relating the graceful restart mechanism for BGP. + GracefulRestart GracefulRestart `mapstructure:"graceful-restart" json:"graceful-restart,omitempty"` + // original -> bgp:afi-safis + // Address family specific configuration. + AfiSafis []AfiSafi `mapstructure:"afi-safis" json:"afi-safis,omitempty"` + // original -> rpol:apply-policy + // Anchor point for routing policies in the model. + // Import and export policies are with respect to the local + // routing table, i.e., export (send) and import (receive), + // depending on the context. + ApplyPolicy ApplyPolicy `mapstructure:"apply-policy" json:"apply-policy,omitempty"` +} + +func (lhs *Global) Equal(rhs *Global) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Config.Equal(&(rhs.Config)) { + return false + } + if !lhs.RouteSelectionOptions.Equal(&(rhs.RouteSelectionOptions)) { + return false + } + if !lhs.DefaultRouteDistance.Equal(&(rhs.DefaultRouteDistance)) { + return false + } + if !lhs.Confederation.Equal(&(rhs.Confederation)) { + return false + } + if !lhs.UseMultiplePaths.Equal(&(rhs.UseMultiplePaths)) { + return false + } + if !lhs.GracefulRestart.Equal(&(rhs.GracefulRestart)) { + return false + } + if len(lhs.AfiSafis) != len(rhs.AfiSafis) { + return false + } + { + lmap := make(map[string]*AfiSafi) + for i, l := range lhs.AfiSafis { + lmap[mapkey(i, string(l.Config.AfiSafiName))] = &lhs.AfiSafis[i] + } + for i, r := range rhs.AfiSafis { + if l, y := lmap[mapkey(i, string(r.Config.AfiSafiName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if !lhs.ApplyPolicy.Equal(&(rhs.ApplyPolicy)) { + return false + } + return true +} + +// struct for container bgp:bgp. +// Top-level configuration and state for the BGP router. +type Bgp struct { + // original -> bgp:global + // Global configuration for the BGP router. + Global Global `mapstructure:"global" json:"global,omitempty"` + // original -> bgp:neighbors + // Configuration for BGP neighbors. + Neighbors []Neighbor `mapstructure:"neighbors" json:"neighbors,omitempty"` + // original -> bgp:peer-groups + // Configuration for BGP peer-groups. + PeerGroups []PeerGroup `mapstructure:"peer-groups" json:"peer-groups,omitempty"` + // original -> gobgp:rpki-servers + RpkiServers []RpkiServer `mapstructure:"rpki-servers" json:"rpki-servers,omitempty"` + // original -> gobgp:bmp-servers + BmpServers []BmpServer `mapstructure:"bmp-servers" json:"bmp-servers,omitempty"` + // original -> gobgp:vrfs + Vrfs []Vrf `mapstructure:"vrfs" json:"vrfs,omitempty"` + // original -> gobgp:mrt-dump + MrtDump []Mrt `mapstructure:"mrt-dump" json:"mrt-dump,omitempty"` + // original -> gobgp:zebra + Zebra Zebra `mapstructure:"zebra" json:"zebra,omitempty"` + // original -> gobgp:collector + Collector Collector `mapstructure:"collector" json:"collector,omitempty"` + // original -> gobgp:dynamic-neighbors + DynamicNeighbors []DynamicNeighbor `mapstructure:"dynamic-neighbors" json:"dynamic-neighbors,omitempty"` +} + +func (lhs *Bgp) Equal(rhs *Bgp) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.Global.Equal(&(rhs.Global)) { + return false + } + if len(lhs.Neighbors) != len(rhs.Neighbors) { + return false + } + { + lmap := make(map[string]*Neighbor) + for i, l := range lhs.Neighbors { + lmap[mapkey(i, string(l.Config.NeighborAddress))] = &lhs.Neighbors[i] + } + for i, r := range rhs.Neighbors { + if l, y := lmap[mapkey(i, string(r.Config.NeighborAddress))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.PeerGroups) != len(rhs.PeerGroups) { + return false + } + { + lmap := make(map[string]*PeerGroup) + for i, l := range lhs.PeerGroups { + lmap[mapkey(i, string(l.Config.PeerGroupName))] = &lhs.PeerGroups[i] + } + for i, r := range rhs.PeerGroups { + if l, y := lmap[mapkey(i, string(r.Config.PeerGroupName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.RpkiServers) != len(rhs.RpkiServers) { + return false + } + { + lmap := make(map[string]*RpkiServer) + for i, l := range lhs.RpkiServers { + lmap[mapkey(i, string(l.Config.Address))] = &lhs.RpkiServers[i] + } + for i, r := range rhs.RpkiServers { + if l, y := lmap[mapkey(i, string(r.Config.Address))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.BmpServers) != len(rhs.BmpServers) { + return false + } + { + lmap := make(map[string]*BmpServer) + for i, l := range lhs.BmpServers { + lmap[mapkey(i, string(l.Config.Address))] = &lhs.BmpServers[i] + } + for i, r := range rhs.BmpServers { + if l, y := lmap[mapkey(i, string(r.Config.Address))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.Vrfs) != len(rhs.Vrfs) { + return false + } + { + lmap := make(map[string]*Vrf) + for i, l := range lhs.Vrfs { + lmap[mapkey(i, string(l.Config.Name))] = &lhs.Vrfs[i] + } + for i, r := range rhs.Vrfs { + if l, y := lmap[mapkey(i, string(r.Config.Name))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.MrtDump) != len(rhs.MrtDump) { + return false + } + { + lmap := make(map[string]*Mrt) + for i, l := range lhs.MrtDump { + lmap[mapkey(i, string(l.Config.FileName))] = &lhs.MrtDump[i] + } + for i, r := range rhs.MrtDump { + if l, y := lmap[mapkey(i, string(r.Config.FileName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if !lhs.Zebra.Equal(&(rhs.Zebra)) { + return false + } + if !lhs.Collector.Equal(&(rhs.Collector)) { + return false + } + if len(lhs.DynamicNeighbors) != len(rhs.DynamicNeighbors) { + return false + } + { + lmap := make(map[string]*DynamicNeighbor) + for i, l := range lhs.DynamicNeighbors { + lmap[mapkey(i, string(l.Config.Prefix))] = &lhs.DynamicNeighbors[i] + } + for i, r := range rhs.DynamicNeighbors { + if l, y := lmap[mapkey(i, string(r.Config.Prefix))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} + +// struct for container gobgp:set-large-community-method. +type SetLargeCommunityMethod struct { + // original -> gobgp:communities + CommunitiesList []string `mapstructure:"communities-list" json:"communities-list,omitempty"` +} + +func (lhs *SetLargeCommunityMethod) Equal(rhs *SetLargeCommunityMethod) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.CommunitiesList) != len(rhs.CommunitiesList) { + return false + } + for idx, l := range lhs.CommunitiesList { + if l != rhs.CommunitiesList[idx] { + return false + } + } + return true +} + +// struct for container gobgp:set-large-community. +type SetLargeCommunity struct { + // original -> gobgp:set-large-community-method + SetLargeCommunityMethod SetLargeCommunityMethod `mapstructure:"set-large-community-method" json:"set-large-community-method,omitempty"` + // original -> gobgp:options + Options BgpSetCommunityOptionType `mapstructure:"options" json:"options,omitempty"` +} + +func (lhs *SetLargeCommunity) Equal(rhs *SetLargeCommunity) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.SetLargeCommunityMethod.Equal(&(rhs.SetLargeCommunityMethod)) { + return false + } + if lhs.Options != rhs.Options { + return false + } + return true +} + +// struct for container bgp-pol:set-ext-community-method. +// Option to set communities using an inline list or +// reference to an existing defined set. +type SetExtCommunityMethod struct { + // original -> bgp-pol:communities + // original type is list of union + // Set the community values for the update inline with + // a list. + CommunitiesList []string `mapstructure:"communities-list" json:"communities-list,omitempty"` + // original -> bgp-pol:ext-community-set-ref + // References a defined extended community set by + // name. + ExtCommunitySetRef string `mapstructure:"ext-community-set-ref" json:"ext-community-set-ref,omitempty"` +} + +func (lhs *SetExtCommunityMethod) Equal(rhs *SetExtCommunityMethod) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.CommunitiesList) != len(rhs.CommunitiesList) { + return false + } + for idx, l := range lhs.CommunitiesList { + if l != rhs.CommunitiesList[idx] { + return false + } + } + if lhs.ExtCommunitySetRef != rhs.ExtCommunitySetRef { + return false + } + return true +} + +// struct for container bgp-pol:set-ext-community. +// Action to set the extended community attributes of the +// route, along with options to modify how the community is +// modified. +type SetExtCommunity struct { + // original -> bgp-pol:set-ext-community-method + // Option to set communities using an inline list or + // reference to an existing defined set. + SetExtCommunityMethod SetExtCommunityMethod `mapstructure:"set-ext-community-method" json:"set-ext-community-method,omitempty"` + // original -> bgp-pol:options + // bgp-pol:options's original type is bgp-set-community-option-type. + // options for modifying the extended community + // attribute with the specified values. These options + // apply to both methods of setting the community + // attribute. + Options string `mapstructure:"options" json:"options,omitempty"` +} + +func (lhs *SetExtCommunity) Equal(rhs *SetExtCommunity) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.SetExtCommunityMethod.Equal(&(rhs.SetExtCommunityMethod)) { + return false + } + if lhs.Options != rhs.Options { + return false + } + return true +} + +// struct for container bgp-pol:set-community-method. +// Option to set communities using an inline list or +// reference to an existing defined set. +type SetCommunityMethod struct { + // original -> bgp-pol:communities + // original type is list of union + // Set the community values for the update inline with + // a list. + CommunitiesList []string `mapstructure:"communities-list" json:"communities-list,omitempty"` + // original -> bgp-pol:community-set-ref + // References a defined community set by name. + CommunitySetRef string `mapstructure:"community-set-ref" json:"community-set-ref,omitempty"` +} + +func (lhs *SetCommunityMethod) Equal(rhs *SetCommunityMethod) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.CommunitiesList) != len(rhs.CommunitiesList) { + return false + } + for idx, l := range lhs.CommunitiesList { + if l != rhs.CommunitiesList[idx] { + return false + } + } + if lhs.CommunitySetRef != rhs.CommunitySetRef { + return false + } + return true +} + +// struct for container bgp-pol:set-community. +// action to set the community attributes of the route, along +// with options to modify how the community is modified. +type SetCommunity struct { + // original -> bgp-pol:set-community-method + // Option to set communities using an inline list or + // reference to an existing defined set. + SetCommunityMethod SetCommunityMethod `mapstructure:"set-community-method" json:"set-community-method,omitempty"` + // original -> bgp-pol:options + // bgp-pol:options's original type is bgp-set-community-option-type. + // Options for modifying the community attribute with + // the specified values. These options apply to both + // methods of setting the community attribute. + Options string `mapstructure:"options" json:"options,omitempty"` +} + +func (lhs *SetCommunity) Equal(rhs *SetCommunity) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.SetCommunityMethod.Equal(&(rhs.SetCommunityMethod)) { + return false + } + if lhs.Options != rhs.Options { + return false + } + return true +} + +// struct for container bgp-pol:set-as-path-prepend. +// action to prepend local AS number to the AS-path a +// specified number of times. +type SetAsPathPrepend struct { + // original -> bgp-pol:repeat-n + // number of times to prepend the local AS + // number. + RepeatN uint8 `mapstructure:"repeat-n" json:"repeat-n,omitempty"` + // original -> gobgp:as + // gobgp:as's original type is union. + // autonomous system number or 'last-as' which means + // the leftmost as number in the AS-path to be prepended. + As string `mapstructure:"as" json:"as,omitempty"` +} + +func (lhs *SetAsPathPrepend) Equal(rhs *SetAsPathPrepend) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.RepeatN != rhs.RepeatN { + return false + } + if lhs.As != rhs.As { + return false + } + return true +} + +// struct for container bgp-pol:bgp-actions. +// Definitions for policy action statements that +// change BGP-specific attributes of the route. +type BgpActions struct { + // original -> bgp-pol:set-as-path-prepend + // action to prepend local AS number to the AS-path a + // specified number of times. + SetAsPathPrepend SetAsPathPrepend `mapstructure:"set-as-path-prepend" json:"set-as-path-prepend,omitempty"` + // original -> bgp-pol:set-community + // action to set the community attributes of the route, along + // with options to modify how the community is modified. + SetCommunity SetCommunity `mapstructure:"set-community" json:"set-community,omitempty"` + // original -> bgp-pol:set-ext-community + // Action to set the extended community attributes of the + // route, along with options to modify how the community is + // modified. + SetExtCommunity SetExtCommunity `mapstructure:"set-ext-community" json:"set-ext-community,omitempty"` + // original -> bgp-pol:set-route-origin + // set the origin attribute to the specified + // value. + SetRouteOrigin BgpOriginAttrType `mapstructure:"set-route-origin" json:"set-route-origin,omitempty"` + // original -> bgp-pol:set-local-pref + // set the local pref attribute on the route + // update. + SetLocalPref uint32 `mapstructure:"set-local-pref" json:"set-local-pref,omitempty"` + // original -> bgp-pol:set-next-hop + // set the next-hop attribute in the route update. + SetNextHop BgpNextHopType `mapstructure:"set-next-hop" json:"set-next-hop,omitempty"` + // original -> bgp-pol:set-med + // set the med metric attribute in the route + // update. + SetMed BgpSetMedType `mapstructure:"set-med" json:"set-med,omitempty"` + // original -> gobgp:set-large-community + SetLargeCommunity SetLargeCommunity `mapstructure:"set-large-community" json:"set-large-community,omitempty"` +} + +func (lhs *BgpActions) Equal(rhs *BgpActions) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.SetAsPathPrepend.Equal(&(rhs.SetAsPathPrepend)) { + return false + } + if !lhs.SetCommunity.Equal(&(rhs.SetCommunity)) { + return false + } + if !lhs.SetExtCommunity.Equal(&(rhs.SetExtCommunity)) { + return false + } + if lhs.SetRouteOrigin != rhs.SetRouteOrigin { + return false + } + if lhs.SetLocalPref != rhs.SetLocalPref { + return false + } + if lhs.SetNextHop != rhs.SetNextHop { + return false + } + if lhs.SetMed != rhs.SetMed { + return false + } + if !lhs.SetLargeCommunity.Equal(&(rhs.SetLargeCommunity)) { + return false + } + return true +} + +// struct for container rpol:igp-actions. +// Actions to set IGP route attributes; these actions +// apply to multiple IGPs. +type IgpActions struct { + // original -> rpol:set-tag + // Set the tag value for OSPF or IS-IS routes. + SetTag TagType `mapstructure:"set-tag" json:"set-tag,omitempty"` +} + +func (lhs *IgpActions) Equal(rhs *IgpActions) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.SetTag != rhs.SetTag { + return false + } + return true +} + +// struct for container rpol:actions. +// Action statements for this policy +// statement. +type Actions struct { + // original -> rpol:route-disposition + // Select the final disposition for the route, either + // accept or reject. + RouteDisposition RouteDisposition `mapstructure:"route-disposition" json:"route-disposition,omitempty"` + // original -> rpol:igp-actions + // Actions to set IGP route attributes; these actions + // apply to multiple IGPs. + IgpActions IgpActions `mapstructure:"igp-actions" json:"igp-actions,omitempty"` + // original -> bgp-pol:bgp-actions + // Definitions for policy action statements that + // change BGP-specific attributes of the route. + BgpActions BgpActions `mapstructure:"bgp-actions" json:"bgp-actions,omitempty"` +} + +func (lhs *Actions) Equal(rhs *Actions) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.RouteDisposition != rhs.RouteDisposition { + return false + } + if !lhs.IgpActions.Equal(&(rhs.IgpActions)) { + return false + } + if !lhs.BgpActions.Equal(&(rhs.BgpActions)) { + return false + } + return true +} + +// struct for container gobgp:match-large-community-set. +type MatchLargeCommunitySet struct { + // original -> gobgp:large-community-set + LargeCommunitySet string `mapstructure:"large-community-set" json:"large-community-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. + MatchSetOptions MatchSetOptionsType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchLargeCommunitySet) Equal(rhs *MatchLargeCommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.LargeCommunitySet != rhs.LargeCommunitySet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container bgp-pol:as-path-length. +// Value and comparison operations for conditions based on the +// length of the AS path in the route update. +type AsPathLength struct { + // original -> ptypes:operator + // type of comparison to be performed. + Operator AttributeComparison `mapstructure:"operator" json:"operator,omitempty"` + // original -> ptypes:value + // value to compare with the community count. + Value uint32 `mapstructure:"value" json:"value,omitempty"` +} + +func (lhs *AsPathLength) Equal(rhs *AsPathLength) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Operator != rhs.Operator { + return false + } + if lhs.Value != rhs.Value { + return false + } + return true +} + +// struct for container bgp-pol:community-count. +// Value and comparison operations for conditions based on the +// number of communities in the route update. +type CommunityCount struct { + // original -> ptypes:operator + // type of comparison to be performed. + Operator AttributeComparison `mapstructure:"operator" json:"operator,omitempty"` + // original -> ptypes:value + // value to compare with the community count. + Value uint32 `mapstructure:"value" json:"value,omitempty"` +} + +func (lhs *CommunityCount) Equal(rhs *CommunityCount) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Operator != rhs.Operator { + return false + } + if lhs.Value != rhs.Value { + return false + } + return true +} + +// struct for container bgp-pol:match-as-path-set. +// Match a referenced as-path set according to the logic +// defined in the match-set-options leaf. +type MatchAsPathSet struct { + // original -> bgp-pol:as-path-set + // References a defined AS path set. + AsPathSet string `mapstructure:"as-path-set" json:"as-path-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. + MatchSetOptions MatchSetOptionsType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchAsPathSet) Equal(rhs *MatchAsPathSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AsPathSet != rhs.AsPathSet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container bgp-pol:match-ext-community-set. +// Match a referenced extended community-set according to the +// logic defined in the match-set-options leaf. +type MatchExtCommunitySet struct { + // original -> bgp-pol:ext-community-set + // References a defined extended community set. + ExtCommunitySet string `mapstructure:"ext-community-set" json:"ext-community-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. + MatchSetOptions MatchSetOptionsType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchExtCommunitySet) Equal(rhs *MatchExtCommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.ExtCommunitySet != rhs.ExtCommunitySet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container bgp-pol:match-community-set. +// Match a referenced community-set according to the logic +// defined in the match-set-options leaf. +type MatchCommunitySet struct { + // original -> bgp-pol:community-set + // References a defined community set. + CommunitySet string `mapstructure:"community-set" json:"community-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. + MatchSetOptions MatchSetOptionsType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchCommunitySet) Equal(rhs *MatchCommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.CommunitySet != rhs.CommunitySet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container bgp-pol:bgp-conditions. +// Policy conditions for matching +// BGP-specific defined sets or comparing BGP-specific +// attributes. +type BgpConditions struct { + // original -> bgp-pol:match-community-set + // Match a referenced community-set according to the logic + // defined in the match-set-options leaf. + MatchCommunitySet MatchCommunitySet `mapstructure:"match-community-set" json:"match-community-set,omitempty"` + // original -> bgp-pol:match-ext-community-set + // Match a referenced extended community-set according to the + // logic defined in the match-set-options leaf. + MatchExtCommunitySet MatchExtCommunitySet `mapstructure:"match-ext-community-set" json:"match-ext-community-set,omitempty"` + // original -> bgp-pol:match-as-path-set + // Match a referenced as-path set according to the logic + // defined in the match-set-options leaf. + MatchAsPathSet MatchAsPathSet `mapstructure:"match-as-path-set" json:"match-as-path-set,omitempty"` + // original -> bgp-pol:med-eq + // Condition to check if the received MED value is equal to + // the specified value. + MedEq uint32 `mapstructure:"med-eq" json:"med-eq,omitempty"` + // original -> bgp-pol:origin-eq + // Condition to check if the route origin is equal to the + // specified value. + OriginEq BgpOriginAttrType `mapstructure:"origin-eq" json:"origin-eq,omitempty"` + // original -> bgp-pol:next-hop-in + // original type is list of inet:ip-address + // List of next hop addresses to check for in the route + // update. + NextHopInList []string `mapstructure:"next-hop-in-list" json:"next-hop-in-list,omitempty"` + // original -> bgp-pol:afi-safi-in + // List of address families which the NLRI may be + // within. + AfiSafiInList []AfiSafiType `mapstructure:"afi-safi-in-list" json:"afi-safi-in-list,omitempty"` + // original -> bgp-pol:local-pref-eq + // Condition to check if the local pref attribute is equal to + // the specified value. + LocalPrefEq uint32 `mapstructure:"local-pref-eq" json:"local-pref-eq,omitempty"` + // original -> bgp-pol:community-count + // Value and comparison operations for conditions based on the + // number of communities in the route update. + CommunityCount CommunityCount `mapstructure:"community-count" json:"community-count,omitempty"` + // original -> bgp-pol:as-path-length + // Value and comparison operations for conditions based on the + // length of the AS path in the route update. + AsPathLength AsPathLength `mapstructure:"as-path-length" json:"as-path-length,omitempty"` + // original -> bgp-pol:route-type + // Condition to check the route type in the route update. + RouteType RouteType `mapstructure:"route-type" json:"route-type,omitempty"` + // original -> gobgp:rpki-validation-result + // specify the validation result of RPKI based on ROA as conditions. + RpkiValidationResult RpkiValidationResultType `mapstructure:"rpki-validation-result" json:"rpki-validation-result,omitempty"` + // original -> gobgp:match-large-community-set + MatchLargeCommunitySet MatchLargeCommunitySet `mapstructure:"match-large-community-set" json:"match-large-community-set,omitempty"` +} + +func (lhs *BgpConditions) Equal(rhs *BgpConditions) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.MatchCommunitySet.Equal(&(rhs.MatchCommunitySet)) { + return false + } + if !lhs.MatchExtCommunitySet.Equal(&(rhs.MatchExtCommunitySet)) { + return false + } + if !lhs.MatchAsPathSet.Equal(&(rhs.MatchAsPathSet)) { + return false + } + if lhs.MedEq != rhs.MedEq { + return false + } + if lhs.OriginEq != rhs.OriginEq { + return false + } + if len(lhs.NextHopInList) != len(rhs.NextHopInList) { + return false + } + for idx, l := range lhs.NextHopInList { + if l != rhs.NextHopInList[idx] { + return false + } + } + if len(lhs.AfiSafiInList) != len(rhs.AfiSafiInList) { + return false + } + for idx, l := range lhs.AfiSafiInList { + if l != rhs.AfiSafiInList[idx] { + return false + } + } + if lhs.LocalPrefEq != rhs.LocalPrefEq { + return false + } + if !lhs.CommunityCount.Equal(&(rhs.CommunityCount)) { + return false + } + if !lhs.AsPathLength.Equal(&(rhs.AsPathLength)) { + return false + } + if lhs.RouteType != rhs.RouteType { + return false + } + if lhs.RpkiValidationResult != rhs.RpkiValidationResult { + return false + } + if !lhs.MatchLargeCommunitySet.Equal(&(rhs.MatchLargeCommunitySet)) { + return false + } + return true +} + +// struct for container rpol:igp-conditions. +// Policy conditions for IGP attributes. +type IgpConditions struct { +} + +func (lhs *IgpConditions) Equal(rhs *IgpConditions) bool { + if lhs == nil || rhs == nil { + return false + } + return true +} + +// struct for container rpol:match-tag-set. +// Match a referenced tag set according to the logic defined +// in the match-options-set leaf. +type MatchTagSet struct { + // original -> rpol:tag-set + // References a defined tag set. + TagSet string `mapstructure:"tag-set" json:"tag-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. This leaf only supports matching on ANY + // member of the set or inverting the match. Matching on ALL is + // not supported). + MatchSetOptions MatchSetOptionsRestrictedType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchTagSet) Equal(rhs *MatchTagSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.TagSet != rhs.TagSet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container rpol:match-neighbor-set. +// Match a referenced neighbor set according to the logic +// defined in the match-set-options-leaf. +type MatchNeighborSet struct { + // original -> rpol:neighbor-set + // References a defined neighbor set. + NeighborSet string `mapstructure:"neighbor-set" json:"neighbor-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. This leaf only supports matching on ANY + // member of the set or inverting the match. Matching on ALL is + // not supported). + MatchSetOptions MatchSetOptionsRestrictedType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchNeighborSet) Equal(rhs *MatchNeighborSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.NeighborSet != rhs.NeighborSet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container rpol:match-prefix-set. +// Match a referenced prefix-set according to the logic +// defined in the match-set-options leaf. +type MatchPrefixSet struct { + // original -> rpol:prefix-set + // References a defined prefix set. + PrefixSet string `mapstructure:"prefix-set" json:"prefix-set,omitempty"` + // original -> rpol:match-set-options + // Optional parameter that governs the behaviour of the + // match operation. This leaf only supports matching on ANY + // member of the set or inverting the match. Matching on ALL is + // not supported). + MatchSetOptions MatchSetOptionsRestrictedType `mapstructure:"match-set-options" json:"match-set-options,omitempty"` +} + +func (lhs *MatchPrefixSet) Equal(rhs *MatchPrefixSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.PrefixSet != rhs.PrefixSet { + return false + } + if lhs.MatchSetOptions != rhs.MatchSetOptions { + return false + } + return true +} + +// struct for container rpol:conditions. +// Condition statements for this +// policy statement. +type Conditions struct { + // original -> rpol:call-policy + // Applies the statements from the specified policy + // definition and then returns control the current + // policy statement. Note that the called policy may + // itself call other policies (subject to + // implementation limitations). This is intended to + // provide a policy 'subroutine' capability. The + // called policy should contain an explicit or a + // default route disposition that returns an + // effective true (accept-route) or false + // (reject-route), otherwise the behavior may be + // ambiguous and implementation dependent. + CallPolicy string `mapstructure:"call-policy" json:"call-policy,omitempty"` + // original -> rpol:match-prefix-set + // Match a referenced prefix-set according to the logic + // defined in the match-set-options leaf. + MatchPrefixSet MatchPrefixSet `mapstructure:"match-prefix-set" json:"match-prefix-set,omitempty"` + // original -> rpol:match-neighbor-set + // Match a referenced neighbor set according to the logic + // defined in the match-set-options-leaf. + MatchNeighborSet MatchNeighborSet `mapstructure:"match-neighbor-set" json:"match-neighbor-set,omitempty"` + // original -> rpol:match-tag-set + // Match a referenced tag set according to the logic defined + // in the match-options-set leaf. + MatchTagSet MatchTagSet `mapstructure:"match-tag-set" json:"match-tag-set,omitempty"` + // original -> rpol:install-protocol-eq + // Condition to check the protocol / method used to install + // which installed the route into the local routing table. + InstallProtocolEq InstallProtocolType `mapstructure:"install-protocol-eq" json:"install-protocol-eq,omitempty"` + // original -> rpol:igp-conditions + // Policy conditions for IGP attributes. + IgpConditions IgpConditions `mapstructure:"igp-conditions" json:"igp-conditions,omitempty"` + // original -> bgp-pol:bgp-conditions + // Policy conditions for matching + // BGP-specific defined sets or comparing BGP-specific + // attributes. + BgpConditions BgpConditions `mapstructure:"bgp-conditions" json:"bgp-conditions,omitempty"` +} + +func (lhs *Conditions) Equal(rhs *Conditions) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.CallPolicy != rhs.CallPolicy { + return false + } + if !lhs.MatchPrefixSet.Equal(&(rhs.MatchPrefixSet)) { + return false + } + if !lhs.MatchNeighborSet.Equal(&(rhs.MatchNeighborSet)) { + return false + } + if !lhs.MatchTagSet.Equal(&(rhs.MatchTagSet)) { + return false + } + if lhs.InstallProtocolEq != rhs.InstallProtocolEq { + return false + } + if !lhs.IgpConditions.Equal(&(rhs.IgpConditions)) { + return false + } + if !lhs.BgpConditions.Equal(&(rhs.BgpConditions)) { + return false + } + return true +} + +// struct for container rpol:statement. +// Policy statements group conditions and actions +// within a policy definition. They are evaluated in +// the order specified (see the description of policy +// evaluation at the top of this module. +type Statement struct { + // original -> rpol:name + // name of the policy statement. + Name string `mapstructure:"name" json:"name,omitempty"` + // original -> rpol:conditions + // Condition statements for this + // policy statement. + Conditions Conditions `mapstructure:"conditions" json:"conditions,omitempty"` + // original -> rpol:actions + // Action statements for this policy + // statement. + Actions Actions `mapstructure:"actions" json:"actions,omitempty"` +} + +func (lhs *Statement) Equal(rhs *Statement) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Name != rhs.Name { + return false + } + if !lhs.Conditions.Equal(&(rhs.Conditions)) { + return false + } + if !lhs.Actions.Equal(&(rhs.Actions)) { + return false + } + return true +} + +// struct for container rpol:policy-definition. +// List of top-level policy definitions, keyed by unique +// name. These policy definitions are expected to be +// referenced (by name) in policy chains specified in import +// or export configuration statements. +type PolicyDefinition struct { + // original -> rpol:name + // Name of the top-level policy definition -- this name + // is used in references to the current policy. + Name string `mapstructure:"name" json:"name,omitempty"` + // original -> rpol:statements + // Enclosing container for policy statements. + Statements []Statement `mapstructure:"statements" json:"statements,omitempty"` +} + +func (lhs *PolicyDefinition) Equal(rhs *PolicyDefinition) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Name != rhs.Name { + return false + } + if len(lhs.Statements) != len(rhs.Statements) { + return false + } + { + lmap := make(map[string]*Statement) + for i, l := range lhs.Statements { + lmap[mapkey(i, string(l.Name))] = &lhs.Statements[i] + } + for i, r := range rhs.Statements { + if l, y := lmap[mapkey(i, string(r.Name))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} + +// struct for container gobgp:large-community-set. +type LargeCommunitySet struct { + // original -> gobgp:large-community-set-name + LargeCommunitySetName string `mapstructure:"large-community-set-name" json:"large-community-set-name,omitempty"` + // original -> gobgp:large-community + // extended community set member. + LargeCommunityList []string `mapstructure:"large-community-list" json:"large-community-list,omitempty"` +} + +func (lhs *LargeCommunitySet) Equal(rhs *LargeCommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.LargeCommunitySetName != rhs.LargeCommunitySetName { + return false + } + if len(lhs.LargeCommunityList) != len(rhs.LargeCommunityList) { + return false + } + for idx, l := range lhs.LargeCommunityList { + if l != rhs.LargeCommunityList[idx] { + return false + } + } + return true +} + +// struct for container bgp-pol:as-path-set. +// Definitions for AS path sets. +type AsPathSet struct { + // original -> bgp-pol:as-path-set-name + // name of the AS path set -- this is used to reference + // the set in match conditions. + AsPathSetName string `mapstructure:"as-path-set-name" json:"as-path-set-name,omitempty"` + // original -> gobgp:as-path + // AS path expression. + AsPathList []string `mapstructure:"as-path-list" json:"as-path-list,omitempty"` +} + +func (lhs *AsPathSet) Equal(rhs *AsPathSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.AsPathSetName != rhs.AsPathSetName { + return false + } + if len(lhs.AsPathList) != len(rhs.AsPathList) { + return false + } + for idx, l := range lhs.AsPathList { + if l != rhs.AsPathList[idx] { + return false + } + } + return true +} + +// struct for container bgp-pol:ext-community-set. +// Definitions for extended community sets. +type ExtCommunitySet struct { + // original -> bgp-pol:ext-community-set-name + // name / label of the extended community set -- this is + // used to reference the set in match conditions. + ExtCommunitySetName string `mapstructure:"ext-community-set-name" json:"ext-community-set-name,omitempty"` + // original -> gobgp:ext-community + // extended community set member. + ExtCommunityList []string `mapstructure:"ext-community-list" json:"ext-community-list,omitempty"` +} + +func (lhs *ExtCommunitySet) Equal(rhs *ExtCommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.ExtCommunitySetName != rhs.ExtCommunitySetName { + return false + } + if len(lhs.ExtCommunityList) != len(rhs.ExtCommunityList) { + return false + } + for idx, l := range lhs.ExtCommunityList { + if l != rhs.ExtCommunityList[idx] { + return false + } + } + return true +} + +// struct for container bgp-pol:community-set. +// Definitions for community sets. +type CommunitySet struct { + // original -> bgp-pol:community-set-name + // name / label of the community set -- this is used to + // reference the set in match conditions. + CommunitySetName string `mapstructure:"community-set-name" json:"community-set-name,omitempty"` + // original -> gobgp:community + // community set member. + CommunityList []string `mapstructure:"community-list" json:"community-list,omitempty"` +} + +func (lhs *CommunitySet) Equal(rhs *CommunitySet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.CommunitySetName != rhs.CommunitySetName { + return false + } + if len(lhs.CommunityList) != len(rhs.CommunityList) { + return false + } + for idx, l := range lhs.CommunityList { + if l != rhs.CommunityList[idx] { + return false + } + } + return true +} + +// struct for container bgp-pol:bgp-defined-sets. +// BGP-related set definitions for policy match conditions. +type BgpDefinedSets struct { + // original -> bgp-pol:community-sets + // Enclosing container for community sets. + CommunitySets []CommunitySet `mapstructure:"community-sets" json:"community-sets,omitempty"` + // original -> bgp-pol:ext-community-sets + // Enclosing container for extended community sets. + ExtCommunitySets []ExtCommunitySet `mapstructure:"ext-community-sets" json:"ext-community-sets,omitempty"` + // original -> bgp-pol:as-path-sets + // Enclosing container for AS path sets. + AsPathSets []AsPathSet `mapstructure:"as-path-sets" json:"as-path-sets,omitempty"` + // original -> gobgp:large-community-sets + LargeCommunitySets []LargeCommunitySet `mapstructure:"large-community-sets" json:"large-community-sets,omitempty"` +} + +func (lhs *BgpDefinedSets) Equal(rhs *BgpDefinedSets) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.CommunitySets) != len(rhs.CommunitySets) { + return false + } + { + lmap := make(map[string]*CommunitySet) + for i, l := range lhs.CommunitySets { + lmap[mapkey(i, string(l.CommunitySetName))] = &lhs.CommunitySets[i] + } + for i, r := range rhs.CommunitySets { + if l, y := lmap[mapkey(i, string(r.CommunitySetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.ExtCommunitySets) != len(rhs.ExtCommunitySets) { + return false + } + { + lmap := make(map[string]*ExtCommunitySet) + for i, l := range lhs.ExtCommunitySets { + lmap[mapkey(i, string(l.ExtCommunitySetName))] = &lhs.ExtCommunitySets[i] + } + for i, r := range rhs.ExtCommunitySets { + if l, y := lmap[mapkey(i, string(r.ExtCommunitySetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.AsPathSets) != len(rhs.AsPathSets) { + return false + } + { + lmap := make(map[string]*AsPathSet) + for i, l := range lhs.AsPathSets { + lmap[mapkey(i, string(l.AsPathSetName))] = &lhs.AsPathSets[i] + } + for i, r := range rhs.AsPathSets { + if l, y := lmap[mapkey(i, string(r.AsPathSetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.LargeCommunitySets) != len(rhs.LargeCommunitySets) { + return false + } + { + lmap := make(map[string]*LargeCommunitySet) + for i, l := range lhs.LargeCommunitySets { + lmap[mapkey(i, string(l.LargeCommunitySetName))] = &lhs.LargeCommunitySets[i] + } + for i, r := range rhs.LargeCommunitySets { + if l, y := lmap[mapkey(i, string(r.LargeCommunitySetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} + +// struct for container rpol:tag. +// list of tags that are part of the tag set. +type Tag struct { + // original -> rpol:value + // Value of the tag set member. + Value TagType `mapstructure:"value" json:"value,omitempty"` +} + +func (lhs *Tag) Equal(rhs *Tag) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.Value != rhs.Value { + return false + } + return true +} + +// struct for container rpol:tag-set. +// Definitions for tag sets. +type TagSet struct { + // original -> rpol:tag-set-name + // name / label of the tag set -- this is used to reference + // the set in match conditions. + TagSetName string `mapstructure:"tag-set-name" json:"tag-set-name,omitempty"` + // original -> rpol:tag + // list of tags that are part of the tag set. + TagList []Tag `mapstructure:"tag-list" json:"tag-list,omitempty"` +} + +func (lhs *TagSet) Equal(rhs *TagSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.TagSetName != rhs.TagSetName { + return false + } + if len(lhs.TagList) != len(rhs.TagList) { + return false + } + { + lmap := make(map[string]*Tag) + for i, l := range lhs.TagList { + lmap[mapkey(i, string(l.Value))] = &lhs.TagList[i] + } + for i, r := range rhs.TagList { + if l, y := lmap[mapkey(i, string(r.Value))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} + +// struct for container rpol:neighbor-set. +// Definitions for neighbor sets. +type NeighborSet struct { + // original -> rpol:neighbor-set-name + // name / label of the neighbor set -- this is used to + // reference the set in match conditions. + NeighborSetName string `mapstructure:"neighbor-set-name" json:"neighbor-set-name,omitempty"` + // original -> gobgp:neighbor-info + // original type is list of inet:ip-address + // neighbor ip address or prefix. + NeighborInfoList []string `mapstructure:"neighbor-info-list" json:"neighbor-info-list,omitempty"` +} + +func (lhs *NeighborSet) Equal(rhs *NeighborSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.NeighborSetName != rhs.NeighborSetName { + return false + } + if len(lhs.NeighborInfoList) != len(rhs.NeighborInfoList) { + return false + } + for idx, l := range lhs.NeighborInfoList { + if l != rhs.NeighborInfoList[idx] { + return false + } + } + return true +} + +// struct for container rpol:prefix. +// List of prefix expressions that are part of the set. +type Prefix struct { + // original -> rpol:ip-prefix + // rpol:ip-prefix's original type is inet:ip-prefix. + // The prefix member in CIDR notation -- while the + // prefix may be either IPv4 or IPv6, most + // implementations require all members of the prefix set + // to be the same address family. Mixing address types in + // the same prefix set is likely to cause an error. + IpPrefix string `mapstructure:"ip-prefix" json:"ip-prefix,omitempty"` + // original -> rpol:masklength-range + // Defines a range for the masklength, or 'exact' if + // the prefix has an exact length. + // + // Example: 10.3.192.0/21 through 10.3.192.0/24 would be + // expressed as prefix: 10.3.192.0/21, + // masklength-range: 21..24. + // + // Example: 10.3.192.0/21 would be expressed as + // prefix: 10.3.192.0/21, + // masklength-range: exact. + MasklengthRange string `mapstructure:"masklength-range" json:"masklength-range,omitempty"` +} + +func (lhs *Prefix) Equal(rhs *Prefix) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.IpPrefix != rhs.IpPrefix { + return false + } + if lhs.MasklengthRange != rhs.MasklengthRange { + return false + } + return true +} + +// struct for container rpol:prefix-set. +// List of the defined prefix sets. +type PrefixSet struct { + // original -> rpol:prefix-set-name + // name / label of the prefix set -- this is used to + // reference the set in match conditions. + PrefixSetName string `mapstructure:"prefix-set-name" json:"prefix-set-name,omitempty"` + // original -> rpol:prefix + // List of prefix expressions that are part of the set. + PrefixList []Prefix `mapstructure:"prefix-list" json:"prefix-list,omitempty"` +} + +func (lhs *PrefixSet) Equal(rhs *PrefixSet) bool { + if lhs == nil || rhs == nil { + return false + } + if lhs.PrefixSetName != rhs.PrefixSetName { + return false + } + if len(lhs.PrefixList) != len(rhs.PrefixList) { + return false + } + { + lmap := make(map[string]*Prefix) + for i, l := range lhs.PrefixList { + lmap[mapkey(i, string(l.IpPrefix+l.MasklengthRange))] = &lhs.PrefixList[i] + } + for i, r := range rhs.PrefixList { + if l, y := lmap[mapkey(i, string(r.IpPrefix+r.MasklengthRange))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} + +// struct for container rpol:defined-sets. +// Predefined sets of attributes used in policy match +// statements. +type DefinedSets struct { + // original -> rpol:prefix-sets + // Enclosing container for defined prefix sets for matching. + PrefixSets []PrefixSet `mapstructure:"prefix-sets" json:"prefix-sets,omitempty"` + // original -> rpol:neighbor-sets + // Enclosing container for defined neighbor sets for matching. + NeighborSets []NeighborSet `mapstructure:"neighbor-sets" json:"neighbor-sets,omitempty"` + // original -> rpol:tag-sets + // Enclosing container for defined tag sets for matching. + TagSets []TagSet `mapstructure:"tag-sets" json:"tag-sets,omitempty"` + // original -> bgp-pol:bgp-defined-sets + // BGP-related set definitions for policy match conditions. + BgpDefinedSets BgpDefinedSets `mapstructure:"bgp-defined-sets" json:"bgp-defined-sets,omitempty"` +} + +func (lhs *DefinedSets) Equal(rhs *DefinedSets) bool { + if lhs == nil || rhs == nil { + return false + } + if len(lhs.PrefixSets) != len(rhs.PrefixSets) { + return false + } + { + lmap := make(map[string]*PrefixSet) + for i, l := range lhs.PrefixSets { + lmap[mapkey(i, string(l.PrefixSetName))] = &lhs.PrefixSets[i] + } + for i, r := range rhs.PrefixSets { + if l, y := lmap[mapkey(i, string(r.PrefixSetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.NeighborSets) != len(rhs.NeighborSets) { + return false + } + { + lmap := make(map[string]*NeighborSet) + for i, l := range lhs.NeighborSets { + lmap[mapkey(i, string(l.NeighborSetName))] = &lhs.NeighborSets[i] + } + for i, r := range rhs.NeighborSets { + if l, y := lmap[mapkey(i, string(r.NeighborSetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if len(lhs.TagSets) != len(rhs.TagSets) { + return false + } + { + lmap := make(map[string]*TagSet) + for i, l := range lhs.TagSets { + lmap[mapkey(i, string(l.TagSetName))] = &lhs.TagSets[i] + } + for i, r := range rhs.TagSets { + if l, y := lmap[mapkey(i, string(r.TagSetName))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + if !lhs.BgpDefinedSets.Equal(&(rhs.BgpDefinedSets)) { + return false + } + return true +} + +// struct for container rpol:routing-policy. +// top-level container for all routing policy configuration. +type RoutingPolicy struct { + // original -> rpol:defined-sets + // Predefined sets of attributes used in policy match + // statements. + DefinedSets DefinedSets `mapstructure:"defined-sets" json:"defined-sets,omitempty"` + // original -> rpol:policy-definitions + // Enclosing container for the list of top-level policy + // definitions. + PolicyDefinitions []PolicyDefinition `mapstructure:"policy-definitions" json:"policy-definitions,omitempty"` +} + +func (lhs *RoutingPolicy) Equal(rhs *RoutingPolicy) bool { + if lhs == nil || rhs == nil { + return false + } + if !lhs.DefinedSets.Equal(&(rhs.DefinedSets)) { + return false + } + if len(lhs.PolicyDefinitions) != len(rhs.PolicyDefinitions) { + return false + } + { + lmap := make(map[string]*PolicyDefinition) + for i, l := range lhs.PolicyDefinitions { + lmap[mapkey(i, string(l.Name))] = &lhs.PolicyDefinitions[i] + } + for i, r := range rhs.PolicyDefinitions { + if l, y := lmap[mapkey(i, string(r.Name))]; !y { + return false + } else if !r.Equal(l) { + return false + } + } + } + return true +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default.go new file mode 100644 index 000000000..eb47b6111 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default.go @@ -0,0 +1,537 @@ +package config + +import ( + "encoding/binary" + "fmt" + "math" + "net" + "reflect" + "strconv" + + "github.com/osrg/gobgp/v3/internal/pkg/version" + "github.com/osrg/gobgp/v3/internal/pkg/zebra" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" + "github.com/osrg/gobgp/v3/pkg/packet/bmp" + "github.com/osrg/gobgp/v3/pkg/packet/rtr" + "github.com/spf13/viper" +) + +const ( + DEFAULT_HOLDTIME = 90 + DEFAULT_IDLE_HOLDTIME_AFTER_RESET = 30 + DEFAULT_CONNECT_RETRY = 120 +) + +var forcedOverwrittenConfig = []string{ + "neighbor.config.peer-as", + "neighbor.timers.config.minimum-advertisement-interval", +} + +var configuredFields map[string]interface{} + +func RegisterConfiguredFields(addr string, n interface{}) { + if configuredFields == nil { + configuredFields = make(map[string]interface{}) + } + configuredFields[addr] = n +} + +func defaultAfiSafi(typ AfiSafiType, enable bool) AfiSafi { + return AfiSafi{ + Config: AfiSafiConfig{ + AfiSafiName: typ, + Enabled: enable, + }, + State: AfiSafiState{ + AfiSafiName: typ, + Family: bgp.AddressFamilyValueMap[string(typ)], + }, + } +} + +func SetDefaultNeighborConfigValues(n *Neighbor, pg *PeerGroup, g *Global) error { + // Determines this function is called against the same Neighbor struct, + // and if already called, returns immediately. + if n.State.LocalAs != 0 { + return nil + } + + return setDefaultNeighborConfigValuesWithViper(nil, n, g, pg) +} + +func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Global, pg *PeerGroup) error { + if n == nil { + return fmt.Errorf("neighbor config is nil") + } + if g == nil { + return fmt.Errorf("global config is nil") + } + + if v == nil { + v = viper.New() + } + + if pg != nil { + if err := OverwriteNeighborConfigWithPeerGroup(n, pg); err != nil { + return err + } + } + + if n.Config.LocalAs == 0 { + n.Config.LocalAs = g.Config.As + if !g.Confederation.Config.Enabled || n.IsConfederation(g) { + n.Config.LocalAs = g.Config.As + } else { + n.Config.LocalAs = g.Confederation.Config.Identifier + } + } + n.State.LocalAs = n.Config.LocalAs + + if n.Config.PeerAs != n.Config.LocalAs { + n.Config.PeerType = PEER_TYPE_EXTERNAL + n.State.PeerType = PEER_TYPE_EXTERNAL + n.State.RemovePrivateAs = n.Config.RemovePrivateAs + n.AsPathOptions.State.ReplacePeerAs = n.AsPathOptions.Config.ReplacePeerAs + } else { + n.Config.PeerType = PEER_TYPE_INTERNAL + n.State.PeerType = PEER_TYPE_INTERNAL + if string(n.Config.RemovePrivateAs) != "" { + return fmt.Errorf("can't set remove-private-as for iBGP peer") + } + if n.AsPathOptions.Config.ReplacePeerAs { + return fmt.Errorf("can't set replace-peer-as for iBGP peer") + } + } + + if n.State.NeighborAddress == "" { + n.State.NeighborAddress = n.Config.NeighborAddress + } + + n.State.PeerAs = n.Config.PeerAs + n.AsPathOptions.State.AllowOwnAs = n.AsPathOptions.Config.AllowOwnAs + + if !v.IsSet("neighbor.error-handling.config.treat-as-withdraw") { + n.ErrorHandling.Config.TreatAsWithdraw = true + } + + if !v.IsSet("neighbor.timers.config.connect-retry") && n.Timers.Config.ConnectRetry == 0 { + n.Timers.Config.ConnectRetry = float64(DEFAULT_CONNECT_RETRY) + } + if !v.IsSet("neighbor.timers.config.hold-time") && n.Timers.Config.HoldTime == 0 { + n.Timers.Config.HoldTime = float64(DEFAULT_HOLDTIME) + } + if !v.IsSet("neighbor.timers.config.keepalive-interval") && n.Timers.Config.KeepaliveInterval == 0 { + n.Timers.Config.KeepaliveInterval = n.Timers.Config.HoldTime / 3 + } + if !v.IsSet("neighbor.timers.config.idle-hold-time-after-reset") && n.Timers.Config.IdleHoldTimeAfterReset == 0 { + n.Timers.Config.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET) + } + + if n.Config.NeighborInterface != "" { + if n.RouteServer.Config.RouteServerClient { + return fmt.Errorf("configuring route server client as unnumbered peer is not supported") + } + addr, err := GetIPv6LinkLocalNeighborAddress(n.Config.NeighborInterface) + if err != nil { + return err + } + n.State.NeighborAddress = addr + } + + if n.Transport.Config.LocalAddress == "" { + if n.State.NeighborAddress == "" { + return fmt.Errorf("no neighbor address/interface specified") + } + ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress) + if err != nil { + return err + } + localAddress := "0.0.0.0" + if ipAddr.IP.To4() == nil { + localAddress = "::" + if ipAddr.Zone != "" { + localAddress, err = getIPv6LinkLocalAddress(ipAddr.Zone) + if err != nil { + return err + } + } + } + n.Transport.Config.LocalAddress = localAddress + } + + if len(n.AfiSafis) == 0 { + if n.Config.NeighborInterface != "" { + n.AfiSafis = []AfiSafi{ + defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true), + defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true), + } + } else if ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress); err != nil { + return fmt.Errorf("invalid neighbor address: %s", n.State.NeighborAddress) + } else if ipAddr.IP.To4() != nil { + n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true)} + } else { + n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true)} + } + for i := range n.AfiSafis { + n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive + n.AfiSafis[i].AddPaths.State.Receive = n.AddPaths.Config.Receive + n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax + n.AfiSafis[i].AddPaths.State.SendMax = n.AddPaths.Config.SendMax + } + } else { + afs, err := extractArray(v.Get("neighbor.afi-safis")) + if err != nil { + return err + } + for i := range n.AfiSafis { + vv := viper.New() + if len(afs) > i { + vv.Set("afi-safi", afs[i]) + } + rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName)) + if err != nil { + return err + } + n.AfiSafis[i].State.Family = rf + n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName + if !vv.IsSet("afi-safi.config.enabled") { + n.AfiSafis[i].Config.Enabled = true + } + n.AfiSafis[i].MpGracefulRestart.State.Enabled = n.AfiSafis[i].MpGracefulRestart.Config.Enabled + if !vv.IsSet("afi-safi.add-paths.config.receive") { + if n.AddPaths.Config.Receive { + n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive + } + } + n.AfiSafis[i].AddPaths.State.Receive = n.AfiSafis[i].AddPaths.Config.Receive + if !vv.IsSet("afi-safi.add-paths.config.send-max") { + if n.AddPaths.Config.SendMax != 0 { + n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax + } + } + n.AfiSafis[i].AddPaths.State.SendMax = n.AfiSafis[i].AddPaths.Config.SendMax + } + } + + n.State.Description = n.Config.Description + n.State.AdminDown = n.Config.AdminDown + + if n.GracefulRestart.Config.Enabled { + if !v.IsSet("neighbor.graceful-restart.config.restart-time") && n.GracefulRestart.Config.RestartTime == 0 { + // RFC 4724 4. Operation + // A suggested default for the Restart Time is a value less than or + // equal to the HOLDTIME carried in the OPEN. + n.GracefulRestart.Config.RestartTime = uint16(n.Timers.Config.HoldTime) + } + if !v.IsSet("neighbor.graceful-restart.config.deferral-time") && n.GracefulRestart.Config.DeferralTime == 0 { + // RFC 4724 4.1. Procedures for the Restarting Speaker + // The value of this timer should be large + // enough, so as to provide all the peers of the Restarting Speaker with + // enough time to send all the routes to the Restarting Speaker + n.GracefulRestart.Config.DeferralTime = uint16(360) + } + } + + if n.EbgpMultihop.Config.Enabled { + if n.TtlSecurity.Config.Enabled { + return fmt.Errorf("ebgp-multihop and ttl-security are mututally exclusive") + } + if n.EbgpMultihop.Config.MultihopTtl == 0 { + n.EbgpMultihop.Config.MultihopTtl = 255 + } + } else if n.TtlSecurity.Config.Enabled { + if n.TtlSecurity.Config.TtlMin == 0 { + n.TtlSecurity.Config.TtlMin = 255 + } + } + + if n.RouteReflector.Config.RouteReflectorClient { + if n.RouteReflector.Config.RouteReflectorClusterId == "" { + n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId) + } else { + id := string(n.RouteReflector.Config.RouteReflectorClusterId) + if ip := net.ParseIP(id).To4(); ip != nil { + n.RouteReflector.State.RouteReflectorClusterId = n.RouteReflector.Config.RouteReflectorClusterId + } else if num, err := strconv.ParseUint(id, 10, 32); err == nil { + ip = make(net.IP, 4) + binary.BigEndian.PutUint32(ip, uint32(num)) + n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(ip.String()) + } else { + return fmt.Errorf("route-reflector-cluster-id should be specified as IPv4 address or 32-bit unsigned integer") + } + } + } + + return nil +} + +func SetDefaultGlobalConfigValues(g *Global) error { + if len(g.AfiSafis) == 0 { + g.AfiSafis = []AfiSafi{} + for k := range AfiSafiTypeToIntMap { + g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true)) + } + } + + if g.Config.Port == 0 { + g.Config.Port = bgp.BGP_PORT + } + + if len(g.Config.LocalAddressList) == 0 { + g.Config.LocalAddressList = []string{"0.0.0.0", "::"} + } + return nil +} + +func setDefaultVrfConfigValues(v *Vrf) error { + if v == nil { + return fmt.Errorf("cannot set default values for nil vrf config") + } + + if v.Config.Name == "" { + return fmt.Errorf("specify vrf name") + } + + _, err := bgp.ParseRouteDistinguisher(v.Config.Rd) + if err != nil { + return fmt.Errorf("invalid rd for vrf %s: %s", v.Config.Name, v.Config.Rd) + } + + if len(v.Config.ImportRtList) == 0 { + v.Config.ImportRtList = v.Config.BothRtList + } + for _, rtString := range v.Config.ImportRtList { + _, err := bgp.ParseRouteTarget(rtString) + if err != nil { + return fmt.Errorf("invalid import rt for vrf %s: %s", v.Config.Name, rtString) + } + } + + if len(v.Config.ExportRtList) == 0 { + v.Config.ExportRtList = v.Config.BothRtList + } + for _, rtString := range v.Config.ExportRtList { + _, err := bgp.ParseRouteTarget(rtString) + if err != nil { + return fmt.Errorf("invalid export rt for vrf %s: %s", v.Config.Name, rtString) + } + } + + return nil +} + +func SetDefaultConfigValues(b *BgpConfigSet) error { + return setDefaultConfigValuesWithViper(nil, b) +} + +func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) error { + stmts, err := extractArray(v.Get("policy.statements")) + if err != nil { + return err + } + for i := range p.Statements { + vv := viper.New() + if len(stmts) > i { + vv.Set("statement", stmts[i]) + } + if !vv.IsSet("statement.actions.route-disposition") { + p.Statements[i].Actions.RouteDisposition = ROUTE_DISPOSITION_NONE + } + } + return nil +} + +func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { + if v == nil { + v = viper.New() + } + + if err := SetDefaultGlobalConfigValues(&b.Global); err != nil { + return err + } + + for idx, server := range b.BmpServers { + if server.Config.SysName == "" { + server.Config.SysName = "GoBGP" + } + if server.Config.SysDescr == "" { + server.Config.SysDescr = version.Version() + } + if server.Config.Port == 0 { + server.Config.Port = bmp.BMP_DEFAULT_PORT + } + if server.Config.RouteMonitoringPolicy == "" { + server.Config.RouteMonitoringPolicy = BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY + } + // statistics-timeout is uint16 value and implicitly less than 65536 + if server.Config.StatisticsTimeout != 0 && server.Config.StatisticsTimeout < 15 { + return fmt.Errorf("too small statistics-timeout value: %d", server.Config.StatisticsTimeout) + } + b.BmpServers[idx] = server + } + + vrfNames := make(map[string]struct{}) + vrfIDs := make(map[uint32]struct{}) + for idx, vrf := range b.Vrfs { + if err := setDefaultVrfConfigValues(&vrf); err != nil { + return err + } + + if _, ok := vrfNames[vrf.Config.Name]; ok { + return fmt.Errorf("duplicated vrf name: %s", vrf.Config.Name) + } + vrfNames[vrf.Config.Name] = struct{}{} + + if vrf.Config.Id != 0 { + if _, ok := vrfIDs[vrf.Config.Id]; ok { + return fmt.Errorf("duplicated vrf id: %d", vrf.Config.Id) + } + vrfIDs[vrf.Config.Id] = struct{}{} + } + + b.Vrfs[idx] = vrf + } + // Auto assign VRF identifier + for idx, vrf := range b.Vrfs { + if vrf.Config.Id == 0 { + for id := uint32(1); id < math.MaxUint32; id++ { + if _, ok := vrfIDs[id]; !ok { + vrf.Config.Id = id + vrfIDs[id] = struct{}{} + break + } + } + } + b.Vrfs[idx] = vrf + } + + if b.Zebra.Config.Url == "" { + b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api" + } + if b.Zebra.Config.Version < zebra.MinZapiVer { + b.Zebra.Config.Version = zebra.MinZapiVer + } else if b.Zebra.Config.Version > zebra.MaxZapiVer { + b.Zebra.Config.Version = zebra.MaxZapiVer + } + + if !v.IsSet("zebra.config.nexthop-trigger-enable") && !b.Zebra.Config.NexthopTriggerEnable && b.Zebra.Config.Version > 2 { + b.Zebra.Config.NexthopTriggerEnable = true + } + if b.Zebra.Config.NexthopTriggerDelay == 0 { + b.Zebra.Config.NexthopTriggerDelay = 5 + } + + list, err := extractArray(v.Get("neighbors")) + if err != nil { + return err + } + + for idx, n := range b.Neighbors { + vv := viper.New() + if len(list) > idx { + vv.Set("neighbor", list[idx]) + } + + pg, err := b.getPeerGroup(n.Config.PeerGroup) + if err != nil { + return nil + } + + if pg != nil { + identifier := vv.Get("neighbor.config.neighbor-address") + if identifier == nil { + identifier = vv.Get("neighbor.config.neighbor-interface") + } + RegisterConfiguredFields(identifier.(string), list[idx]) + } + + if err := setDefaultNeighborConfigValuesWithViper(vv, &n, &b.Global, pg); err != nil { + return err + } + b.Neighbors[idx] = n + } + + for _, d := range b.DynamicNeighbors { + if err := d.validate(b); err != nil { + return err + } + } + + for idx, r := range b.RpkiServers { + if r.Config.Port == 0 { + b.RpkiServers[idx].Config.Port = rtr.RPKI_DEFAULT_PORT + } + } + + list, err = extractArray(v.Get("policy-definitions")) + if err != nil { + return err + } + + for idx, p := range b.PolicyDefinitions { + vv := viper.New() + if len(list) > idx { + vv.Set("policy", list[idx]) + } + if err := setDefaultPolicyConfigValuesWithViper(vv, &p); err != nil { + return err + } + b.PolicyDefinitions[idx] = p + } + + return nil +} + +func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error { + v := viper.New() + + val, ok := configuredFields[c.Config.NeighborAddress] + if ok { + v.Set("neighbor", val) + } else { + v.Set("neighbor.config.peer-group", c.Config.PeerGroup) + } + + overwriteConfig(&c.Config, &pg.Config, "neighbor.config", v) + overwriteConfig(&c.Timers.Config, &pg.Timers.Config, "neighbor.timers.config", v) + overwriteConfig(&c.Transport.Config, &pg.Transport.Config, "neighbor.transport.config", v) + overwriteConfig(&c.ErrorHandling.Config, &pg.ErrorHandling.Config, "neighbor.error-handling.config", v) + overwriteConfig(&c.LoggingOptions.Config, &pg.LoggingOptions.Config, "neighbor.logging-options.config", v) + overwriteConfig(&c.EbgpMultihop.Config, &pg.EbgpMultihop.Config, "neighbor.ebgp-multihop.config", v) + overwriteConfig(&c.RouteReflector.Config, &pg.RouteReflector.Config, "neighbor.route-reflector.config", v) + overwriteConfig(&c.AsPathOptions.Config, &pg.AsPathOptions.Config, "neighbor.as-path-options.config", v) + overwriteConfig(&c.AddPaths.Config, &pg.AddPaths.Config, "neighbor.add-paths.config", v) + overwriteConfig(&c.GracefulRestart.Config, &pg.GracefulRestart.Config, "neighbor.gradeful-restart.config", v) + overwriteConfig(&c.ApplyPolicy.Config, &pg.ApplyPolicy.Config, "neighbor.apply-policy.config", v) + overwriteConfig(&c.UseMultiplePaths.Config, &pg.UseMultiplePaths.Config, "neighbor.use-multiple-paths.config", v) + overwriteConfig(&c.RouteServer.Config, &pg.RouteServer.Config, "neighbor.route-server.config", v) + overwriteConfig(&c.TtlSecurity.Config, &pg.TtlSecurity.Config, "neighbor.ttl-security.config", v) + + if !v.IsSet("neighbor.afi-safis") { + c.AfiSafis = append([]AfiSafi{}, pg.AfiSafis...) + } + + return nil +} + +func overwriteConfig(c, pg interface{}, tagPrefix string, v *viper.Viper) { + nValue := reflect.Indirect(reflect.ValueOf(c)) + nType := reflect.Indirect(nValue).Type() + pgValue := reflect.Indirect(reflect.ValueOf(pg)) + pgType := reflect.Indirect(pgValue).Type() + + for i := 0; i < pgType.NumField(); i++ { + field := pgType.Field(i).Name + tag := tagPrefix + "." + nType.Field(i).Tag.Get("mapstructure") + if func() bool { + for _, t := range forcedOverwrittenConfig { + if t == tag { + return true + } + } + return false + }() || !v.IsSet(tag) { + nValue.FieldByName(field).Set(pgValue.FieldByName(field)) + } + } +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_linux.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_linux.go new file mode 100644 index 000000000..878988022 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_linux.go @@ -0,0 +1,73 @@ +// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. +// +// 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. +//go:build linux +// +build linux + +package config + +import ( + "fmt" + "net" + + "github.com/vishvananda/netlink" +) + +func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) { + ifi, err := net.InterfaceByName(ifname) + if err != nil { + return "", err + } + neighs, err := netlink.NeighList(ifi.Index, netlink.FAMILY_V6) + if err != nil { + return "", err + } + cnt := 0 + var addr net.IP + for _, neigh := range neighs { + local, err := isLocalLinkLocalAddress(ifi.Index, neigh.IP) + if err != nil { + return "", err + } + if neigh.State&netlink.NUD_FAILED == 0 && neigh.IP.IsLinkLocalUnicast() && !local { + addr = neigh.IP + cnt++ + } + } + + if cnt == 0 { + return "", fmt.Errorf("no ipv6 link-local neighbor found") + } else if cnt > 1 { + return "", fmt.Errorf("found %d link-local neighbors. only support p2p link", cnt) + } + + return fmt.Sprintf("%s%%%s", addr, ifname), nil +} + +func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) { + ifi, err := net.InterfaceByIndex(ifindex) + if err != nil { + return false, err + } + addrs, err := ifi.Addrs() + if err != nil { + return false, err + } + for _, a := range addrs { + if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) { + return true, nil + } + } + return false, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_nonlinux.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_nonlinux.go new file mode 100644 index 000000000..e9ad86dc4 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_nonlinux.go @@ -0,0 +1,26 @@ +// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. +// +// 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. +//go:build !linux +// +build !linux + +package config + +import ( + "fmt" +) + +func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) { + return "", fmt.Errorf("unnumbered peering is not supported") +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/serve.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/serve.go new file mode 100644 index 000000000..84db10221 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/serve.go @@ -0,0 +1,131 @@ +package config + +import ( + "github.com/spf13/viper" + + "github.com/osrg/gobgp/v3/pkg/log" +) + +type BgpConfigSet struct { + Global Global `mapstructure:"global"` + Neighbors []Neighbor `mapstructure:"neighbors"` + PeerGroups []PeerGroup `mapstructure:"peer-groups"` + RpkiServers []RpkiServer `mapstructure:"rpki-servers"` + BmpServers []BmpServer `mapstructure:"bmp-servers"` + Vrfs []Vrf `mapstructure:"vrfs"` + MrtDump []Mrt `mapstructure:"mrt-dump"` + Zebra Zebra `mapstructure:"zebra"` + Collector Collector `mapstructure:"collector"` + DefinedSets DefinedSets `mapstructure:"defined-sets"` + PolicyDefinitions []PolicyDefinition `mapstructure:"policy-definitions"` + DynamicNeighbors []DynamicNeighbor `mapstructure:"dynamic-neighbors"` +} + +func ReadConfigfile(path, format string) (*BgpConfigSet, error) { + // Update config file type, if detectable + format = detectConfigFileType(path, format) + + config := &BgpConfigSet{} + v := viper.New() + v.SetConfigFile(path) + v.SetConfigType(format) + var err error + if err = v.ReadInConfig(); err != nil { + return nil, err + } + if err = v.UnmarshalExact(config); err != nil { + return nil, err + } + if err = setDefaultConfigValuesWithViper(v, config); err != nil { + return nil, err + } + return config, nil +} + +func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy { + return &RoutingPolicy{ + DefinedSets: c.DefinedSets, + PolicyDefinitions: c.PolicyDefinitions, + } +} + +func UpdatePeerGroupConfig(logger log.Logger, curC, newC *BgpConfigSet) ([]PeerGroup, []PeerGroup, []PeerGroup) { + addedPg := []PeerGroup{} + deletedPg := []PeerGroup{} + updatedPg := []PeerGroup{} + + for _, n := range newC.PeerGroups { + if idx := existPeerGroup(n.Config.PeerGroupName, curC.PeerGroups); idx < 0 { + addedPg = append(addedPg, n) + } else if !n.Equal(&curC.PeerGroups[idx]) { + logger.Debug("Current peer-group config", + log.Fields{ + "Topic": "Config", + "Key": curC.PeerGroups[idx]}) + logger.Debug("New peer-group config", + log.Fields{ + "Topic": "Config", + "Key": n}) + updatedPg = append(updatedPg, n) + } + } + + for _, n := range curC.PeerGroups { + if existPeerGroup(n.Config.PeerGroupName, newC.PeerGroups) < 0 { + deletedPg = append(deletedPg, n) + } + } + return addedPg, deletedPg, updatedPg +} + +func UpdateNeighborConfig(logger log.Logger, curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor) { + added := []Neighbor{} + deleted := []Neighbor{} + updated := []Neighbor{} + + for _, n := range newC.Neighbors { + if idx := inSlice(n, curC.Neighbors); idx < 0 { + added = append(added, n) + } else if !n.Equal(&curC.Neighbors[idx]) { + logger.Debug("Current neighbor config", + log.Fields{ + "Topic": "Config", + "Key": curC.Neighbors[idx]}) + logger.Debug("New neighbor config", + log.Fields{ + "Topic": "Config", + "Key": n}) + updated = append(updated, n) + } + } + + for _, n := range curC.Neighbors { + if inSlice(n, newC.Neighbors) < 0 { + deleted = append(deleted, n) + } + } + return added, deleted, updated +} + +func CheckPolicyDifference(logger log.Logger, currentPolicy *RoutingPolicy, newPolicy *RoutingPolicy) bool { + logger.Debug("Current policy", + log.Fields{ + "Topic": "Config", + "Key": currentPolicy}) + logger.Debug("New policy", + log.Fields{ + "Topic": "Config", + "Key": newPolicy}) + + var result bool + if currentPolicy == nil && newPolicy == nil { + result = false + } else { + if currentPolicy != nil && newPolicy != nil { + result = !currentPolicy.Equal(newPolicy) + } else { + result = true + } + } + return result +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/util.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/util.go new file mode 100644 index 000000000..b49c20ebd --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/config/util.go @@ -0,0 +1,763 @@ +// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 ( + "fmt" + "net" + "path/filepath" + "regexp" + "strconv" + "strings" + "time" + + tspb "google.golang.org/protobuf/types/known/timestamppb" + + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/pkg/apiutil" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +// Returns config file type by retrieving extension from the given path. +// If no corresponding type found, returns the given def as the default value. +func detectConfigFileType(path, def string) string { + switch ext := filepath.Ext(path); ext { + case ".toml": + return "toml" + case ".yaml", ".yml": + return "yaml" + case ".json": + return "json" + default: + return def + } +} + +// yaml is decoded as []interface{} +// but toml is decoded as []map[string]interface{}. +// currently, viper can't hide this difference. +// handle the difference here. +func extractArray(intf interface{}) ([]interface{}, error) { + if intf != nil { + list, ok := intf.([]interface{}) + if ok { + return list, nil + } + l, ok := intf.([]map[string]interface{}) + if !ok { + return nil, fmt.Errorf("invalid configuration: neither []interface{} nor []map[string]interface{}") + } + list = make([]interface{}, 0, len(l)) + for _, m := range l { + list = append(list, m) + } + return list, nil + } + return nil, nil +} + +func getIPv6LinkLocalAddress(ifname string) (string, error) { + ifi, err := net.InterfaceByName(ifname) + if err != nil { + return "", err + } + addrs, err := ifi.Addrs() + if err != nil { + return "", err + } + for _, addr := range addrs { + ip := addr.(*net.IPNet).IP + if ip.To4() == nil && ip.IsLinkLocalUnicast() { + return fmt.Sprintf("%s%%%s", ip.String(), ifname), nil + } + } + return "", fmt.Errorf("no ipv6 link local address for %s", ifname) +} + +func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) { + if n == "" { + return nil, nil + } + for _, pg := range b.PeerGroups { + if n == pg.Config.PeerGroupName { + return &pg, nil + } + } + return nil, fmt.Errorf("no such peer-group: %s", n) +} + +func (d *DynamicNeighbor) validate(b *BgpConfigSet) error { + if d.Config.PeerGroup == "" { + return fmt.Errorf("dynamic neighbor requires the peer group config") + } + + if _, err := b.getPeerGroup(d.Config.PeerGroup); err != nil { + return err + } + if _, _, err := net.ParseCIDR(d.Config.Prefix); err != nil { + return fmt.Errorf("invalid dynamic neighbor prefix %s", d.Config.Prefix) + } + return nil +} + +func (n *Neighbor) IsConfederationMember(g *Global) bool { + for _, member := range g.Confederation.Config.MemberAsList { + if member == n.Config.PeerAs { + return true + } + } + return false +} + +func (n *Neighbor) IsConfederation(g *Global) bool { + if n.Config.PeerAs == g.Config.As { + return true + } + return n.IsConfederationMember(g) +} + +func (n *Neighbor) IsEBGPPeer(g *Global) bool { + return n.Config.PeerAs != n.Config.LocalAs +} + +func (n *Neighbor) CreateRfMap() map[bgp.RouteFamily]bgp.BGPAddPathMode { + rfMap := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) + for _, af := range n.AfiSafis { + mode := bgp.BGP_ADD_PATH_NONE + if af.AddPaths.State.Receive { + mode |= bgp.BGP_ADD_PATH_RECEIVE + } + if af.AddPaths.State.SendMax > 0 { + mode |= bgp.BGP_ADD_PATH_SEND + } + rfMap[af.State.Family] = mode + } + return rfMap +} + +func (n *Neighbor) GetAfiSafi(family bgp.RouteFamily) *AfiSafi { + for _, a := range n.AfiSafis { + if string(a.Config.AfiSafiName) == family.String() { + return &a + } + } + return nil +} + +func (n *Neighbor) ExtractNeighborAddress() (string, error) { + addr := n.State.NeighborAddress + if addr == "" { + addr = n.Config.NeighborAddress + if addr == "" { + return "", fmt.Errorf("NeighborAddress is not configured") + } + } + return addr, nil +} + +func (n *Neighbor) IsAddPathReceiveEnabled(family bgp.RouteFamily) bool { + for _, af := range n.AfiSafis { + if af.State.Family == family { + return af.AddPaths.State.Receive + } + } + return false +} + +type AfiSafis []AfiSafi + +func (c AfiSafis) ToRfList() ([]bgp.RouteFamily, error) { + rfs := make([]bgp.RouteFamily, 0, len(c)) + for _, af := range c { + rfs = append(rfs, af.State.Family) + } + return rfs, nil +} + +func inSlice(n Neighbor, b []Neighbor) int { + for i, nb := range b { + if nb.State.NeighborAddress == n.State.NeighborAddress { + return i + } + } + return -1 +} + +func existPeerGroup(n string, b []PeerGroup) int { + for i, nb := range b { + if nb.Config.PeerGroupName == n { + return i + } + } + return -1 +} + +func isAfiSafiChanged(x, y []AfiSafi) bool { + if len(x) != len(y) { + return true + } + m := make(map[string]AfiSafi) + for i, e := range x { + m[string(e.Config.AfiSafiName)] = x[i] + } + for _, e := range y { + if v, ok := m[string(e.Config.AfiSafiName)]; !ok || !v.Config.Equal(&e.Config) || !v.AddPaths.Config.Equal(&e.AddPaths.Config) || !v.MpGracefulRestart.Config.Equal(&e.MpGracefulRestart.Config) { + return true + } + } + return false +} + +func (n *Neighbor) NeedsResendOpenMessage(new *Neighbor) bool { + return !n.Config.Equal(&new.Config) || + !n.Transport.Config.Equal(&new.Transport.Config) || + !n.AddPaths.Config.Equal(&new.AddPaths.Config) || + !n.AsPathOptions.Config.Equal(&new.AsPathOptions.Config) || + !n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) || + isAfiSafiChanged(n.AfiSafis, new.AfiSafis) +} + +// TODO: these regexp are duplicated in api +var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) + +func ParseMaskLength(prefix, mask string) (int, int, error) { + _, ipNet, err := net.ParseCIDR(prefix) + if err != nil { + return 0, 0, fmt.Errorf("invalid prefix: %s", prefix) + } + if mask == "" { + l, _ := ipNet.Mask.Size() + return l, l, nil + } + elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask) + if len(elems) != 3 { + return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) + } + // we've already checked the range is sane by regexp + min, _ := strconv.ParseUint(elems[1], 10, 8) + max, _ := strconv.ParseUint(elems[2], 10, 8) + if min > max { + return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) + } + if ipv4 := ipNet.IP.To4(); ipv4 != nil { + f := func(i uint64) bool { + return i <= 32 + } + if !f(min) || !f(max) { + return 0, 0, fmt.Errorf("ipv4 mask length range outside scope :%s", mask) + } + } else { + f := func(i uint64) bool { + return i <= 128 + } + if !f(min) || !f(max) { + return 0, 0, fmt.Errorf("ipv6 mask length range outside scope :%s", mask) + } + } + return int(min), int(max), nil +} + +func extractFamilyFromConfigAfiSafi(c *AfiSafi) uint32 { + if c == nil { + return 0 + } + // If address family value is already stored in AfiSafiState structure, + // we prefer to use this value. + if c.State.Family != 0 { + return uint32(c.State.Family) + } + // In case that Neighbor structure came from CLI or gRPC, address family + // value in AfiSafiState structure can be omitted. + // Here extracts value from AfiSafiName field in AfiSafiConfig structure. + if rf, err := bgp.GetRouteFamily(string(c.Config.AfiSafiName)); err == nil { + return uint32(rf) + } + // Ignores invalid address family name + return 0 +} + +func newAfiSafiConfigFromConfigStruct(c *AfiSafi) *api.AfiSafiConfig { + rf := extractFamilyFromConfigAfiSafi(c) + afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(rf)) + return &api.AfiSafiConfig{ + Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, + Enabled: c.Config.Enabled, + } +} + +func newApplyPolicyFromConfigStruct(c *ApplyPolicy) *api.ApplyPolicy { + f := func(t DefaultPolicyType) api.RouteAction { + if t == DEFAULT_POLICY_TYPE_ACCEPT_ROUTE { + return api.RouteAction_ACCEPT + } else if t == DEFAULT_POLICY_TYPE_REJECT_ROUTE { + return api.RouteAction_REJECT + } + return api.RouteAction_NONE + } + applyPolicy := &api.ApplyPolicy{ + ImportPolicy: &api.PolicyAssignment{ + Direction: api.PolicyDirection_IMPORT, + DefaultAction: f(c.Config.DefaultImportPolicy), + }, + ExportPolicy: &api.PolicyAssignment{ + Direction: api.PolicyDirection_EXPORT, + DefaultAction: f(c.Config.DefaultExportPolicy), + }, + } + + for _, pname := range c.Config.ImportPolicyList { + applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &api.Policy{Name: pname}) + } + for _, pname := range c.Config.ExportPolicyList { + applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &api.Policy{Name: pname}) + } + + return applyPolicy +} + +func newPrefixLimitFromConfigStruct(c *AfiSafi) *api.PrefixLimit { + if c.PrefixLimit.Config.MaxPrefixes == 0 { + return nil + } + afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(c.State.Family)) + return &api.PrefixLimit{ + Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, + MaxPrefixes: c.PrefixLimit.Config.MaxPrefixes, + ShutdownThresholdPct: uint32(c.PrefixLimit.Config.ShutdownThresholdPct), + } +} + +func newRouteTargetMembershipFromConfigStruct(c *RouteTargetMembership) *api.RouteTargetMembership { + return &api.RouteTargetMembership{ + Config: &api.RouteTargetMembershipConfig{ + DeferralTime: uint32(c.Config.DeferralTime), + }, + } +} + +func newLongLivedGracefulRestartFromConfigStruct(c *LongLivedGracefulRestart) *api.LongLivedGracefulRestart { + return &api.LongLivedGracefulRestart{ + Config: &api.LongLivedGracefulRestartConfig{ + Enabled: c.Config.Enabled, + RestartTime: c.Config.RestartTime, + }, + } +} + +func newAddPathsFromConfigStruct(c *AddPaths) *api.AddPaths { + return &api.AddPaths{ + Config: &api.AddPathsConfig{ + Receive: c.Config.Receive, + SendMax: uint32(c.Config.SendMax), + }, + } +} + +func newRouteSelectionOptionsFromConfigStruct(c *RouteSelectionOptions) *api.RouteSelectionOptions { + return &api.RouteSelectionOptions{ + Config: &api.RouteSelectionOptionsConfig{ + AlwaysCompareMed: c.Config.AlwaysCompareMed, + IgnoreAsPathLength: c.Config.IgnoreAsPathLength, + ExternalCompareRouterId: c.Config.ExternalCompareRouterId, + AdvertiseInactiveRoutes: c.Config.AdvertiseInactiveRoutes, + EnableAigp: c.Config.EnableAigp, + IgnoreNextHopIgpMetric: c.Config.IgnoreNextHopIgpMetric, + }, + } +} + +func newMpGracefulRestartFromConfigStruct(c *MpGracefulRestart) *api.MpGracefulRestart { + return &api.MpGracefulRestart{ + Config: &api.MpGracefulRestartConfig{ + Enabled: c.Config.Enabled, + }, + State: &api.MpGracefulRestartState{ + Enabled: c.State.Enabled, + Received: c.State.Received, + Advertised: c.State.Advertised, + EndOfRibReceived: c.State.EndOfRibReceived, + EndOfRibSent: c.State.EndOfRibSent, + }, + } +} + +func newUseMultiplePathsFromConfigStruct(c *UseMultiplePaths) *api.UseMultiplePaths { + return &api.UseMultiplePaths{ + Config: &api.UseMultiplePathsConfig{ + Enabled: c.Config.Enabled, + }, + Ebgp: &api.Ebgp{ + Config: &api.EbgpConfig{ + AllowMultipleAsn: c.Ebgp.Config.AllowMultipleAs, + MaximumPaths: c.Ebgp.Config.MaximumPaths, + }, + }, + Ibgp: &api.Ibgp{ + Config: &api.IbgpConfig{ + MaximumPaths: c.Ibgp.Config.MaximumPaths, + }, + }, + } +} + +func newAfiSafiFromConfigStruct(c *AfiSafi) *api.AfiSafi { + return &api.AfiSafi{ + MpGracefulRestart: newMpGracefulRestartFromConfigStruct(&c.MpGracefulRestart), + Config: newAfiSafiConfigFromConfigStruct(c), + ApplyPolicy: newApplyPolicyFromConfigStruct(&c.ApplyPolicy), + RouteSelectionOptions: newRouteSelectionOptionsFromConfigStruct(&c.RouteSelectionOptions), + UseMultiplePaths: newUseMultiplePathsFromConfigStruct(&c.UseMultiplePaths), + PrefixLimits: newPrefixLimitFromConfigStruct(c), + RouteTargetMembership: newRouteTargetMembershipFromConfigStruct(&c.RouteTargetMembership), + LongLivedGracefulRestart: newLongLivedGracefulRestartFromConfigStruct(&c.LongLivedGracefulRestart), + AddPaths: newAddPathsFromConfigStruct(&c.AddPaths), + } +} + +func ProtoTimestamp(secs int64) *tspb.Timestamp { + if secs == 0 { + return nil + } + return tspb.New(time.Unix(secs, 0)) +} + +func NewPeerFromConfigStruct(pconf *Neighbor) *api.Peer { + afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) + for _, f := range pconf.AfiSafis { + if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { + afiSafis = append(afiSafis, afiSafi) + } + } + + timer := pconf.Timers + s := pconf.State + localAddress := pconf.Transport.Config.LocalAddress + if pconf.Transport.State.LocalAddress != "" { + localAddress = pconf.Transport.State.LocalAddress + } + remoteCap, err := apiutil.MarshalCapabilities(pconf.State.RemoteCapabilityList) + if err != nil { + return nil + } + localCap, err := apiutil.MarshalCapabilities(pconf.State.LocalCapabilityList) + if err != nil { + return nil + } + var removePrivate api.RemovePrivate + switch pconf.Config.RemovePrivateAs { + case REMOVE_PRIVATE_AS_OPTION_ALL: + removePrivate = api.RemovePrivate_REMOVE_ALL + case REMOVE_PRIVATE_AS_OPTION_REPLACE: + removePrivate = api.RemovePrivate_REPLACE + } + return &api.Peer{ + ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), + Conf: &api.PeerConf{ + NeighborAddress: pconf.Config.NeighborAddress, + PeerAsn: pconf.Config.PeerAs, + LocalAsn: pconf.Config.LocalAs, + Type: api.PeerType(pconf.Config.PeerType.ToInt()), + AuthPassword: pconf.Config.AuthPassword, + RouteFlapDamping: pconf.Config.RouteFlapDamping, + Description: pconf.Config.Description, + PeerGroup: pconf.Config.PeerGroup, + NeighborInterface: pconf.Config.NeighborInterface, + Vrf: pconf.Config.Vrf, + AllowOwnAsn: uint32(pconf.AsPathOptions.Config.AllowOwnAs), + RemovePrivate: removePrivate, + ReplacePeerAsn: pconf.AsPathOptions.Config.ReplacePeerAs, + AdminDown: pconf.Config.AdminDown, + }, + State: &api.PeerState{ + SessionState: api.PeerState_SessionState(api.PeerState_SessionState_value[strings.ToUpper(string(s.SessionState))]), + AdminState: api.PeerState_AdminState(s.AdminState.ToInt()), + Messages: &api.Messages{ + Received: &api.Message{ + Notification: s.Messages.Received.Notification, + Update: s.Messages.Received.Update, + Open: s.Messages.Received.Open, + Keepalive: s.Messages.Received.Keepalive, + Refresh: s.Messages.Received.Refresh, + Discarded: s.Messages.Received.Discarded, + Total: s.Messages.Received.Total, + WithdrawUpdate: uint64(s.Messages.Received.WithdrawUpdate), + WithdrawPrefix: uint64(s.Messages.Received.WithdrawPrefix), + }, + Sent: &api.Message{ + Notification: s.Messages.Sent.Notification, + Update: s.Messages.Sent.Update, + Open: s.Messages.Sent.Open, + Keepalive: s.Messages.Sent.Keepalive, + Refresh: s.Messages.Sent.Refresh, + Discarded: s.Messages.Sent.Discarded, + Total: s.Messages.Sent.Total, + }, + }, + PeerAsn: s.PeerAs, + Type: api.PeerType(s.PeerType.ToInt()), + NeighborAddress: pconf.State.NeighborAddress, + Queues: &api.Queues{}, + RemoteCap: remoteCap, + LocalCap: localCap, + RouterId: s.RemoteRouterId, + }, + EbgpMultihop: &api.EbgpMultihop{ + Enabled: pconf.EbgpMultihop.Config.Enabled, + MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl), + }, + TtlSecurity: &api.TtlSecurity{ + Enabled: pconf.TtlSecurity.Config.Enabled, + TtlMin: uint32(pconf.TtlSecurity.Config.TtlMin), + }, + Timers: &api.Timers{ + Config: &api.TimersConfig{ + ConnectRetry: uint64(timer.Config.ConnectRetry), + HoldTime: uint64(timer.Config.HoldTime), + KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), + IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset), + }, + State: &api.TimersState{ + KeepaliveInterval: uint64(timer.State.KeepaliveInterval), + NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), + Uptime: ProtoTimestamp(timer.State.Uptime), + Downtime: ProtoTimestamp(timer.State.Downtime), + }, + }, + RouteReflector: &api.RouteReflector{ + RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, + RouteReflectorClusterId: string(pconf.RouteReflector.State.RouteReflectorClusterId), + }, + RouteServer: &api.RouteServer{ + RouteServerClient: pconf.RouteServer.Config.RouteServerClient, + SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute, + }, + GracefulRestart: &api.GracefulRestart{ + Enabled: pconf.GracefulRestart.Config.Enabled, + RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), + HelperOnly: pconf.GracefulRestart.Config.HelperOnly, + DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), + NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, + LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, + LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, + }, + Transport: &api.Transport{ + RemotePort: uint32(pconf.Transport.Config.RemotePort), + LocalPort: uint32(pconf.Transport.Config.LocalPort), + LocalAddress: localAddress, + PassiveMode: pconf.Transport.Config.PassiveMode, + BindInterface: pconf.Transport.Config.BindInterface, + }, + AfiSafis: afiSafis, + } +} + +func NewPeerGroupFromConfigStruct(pconf *PeerGroup) *api.PeerGroup { + afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) + for _, f := range pconf.AfiSafis { + if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { + afiSafi.AddPaths.Config.Receive = pconf.AddPaths.Config.Receive + afiSafi.AddPaths.Config.SendMax = uint32(pconf.AddPaths.Config.SendMax) + afiSafis = append(afiSafis, afiSafi) + } + } + + timer := pconf.Timers + s := pconf.State + return &api.PeerGroup{ + ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), + Conf: &api.PeerGroupConf{ + PeerAsn: pconf.Config.PeerAs, + LocalAsn: pconf.Config.LocalAs, + Type: api.PeerType(pconf.Config.PeerType.ToInt()), + AuthPassword: pconf.Config.AuthPassword, + RouteFlapDamping: pconf.Config.RouteFlapDamping, + Description: pconf.Config.Description, + PeerGroupName: pconf.Config.PeerGroupName, + }, + Info: &api.PeerGroupState{ + PeerAsn: s.PeerAs, + Type: api.PeerType(s.PeerType.ToInt()), + TotalPaths: s.TotalPaths, + TotalPrefixes: s.TotalPrefixes, + }, + EbgpMultihop: &api.EbgpMultihop{ + Enabled: pconf.EbgpMultihop.Config.Enabled, + MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl), + }, + TtlSecurity: &api.TtlSecurity{ + Enabled: pconf.TtlSecurity.Config.Enabled, + TtlMin: uint32(pconf.TtlSecurity.Config.TtlMin), + }, + Timers: &api.Timers{ + Config: &api.TimersConfig{ + ConnectRetry: uint64(timer.Config.ConnectRetry), + HoldTime: uint64(timer.Config.HoldTime), + KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), + IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset), + }, + State: &api.TimersState{ + KeepaliveInterval: uint64(timer.State.KeepaliveInterval), + NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), + Uptime: ProtoTimestamp(timer.State.Uptime), + Downtime: ProtoTimestamp(timer.State.Downtime), + }, + }, + RouteReflector: &api.RouteReflector{ + RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, + RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId), + }, + RouteServer: &api.RouteServer{ + RouteServerClient: pconf.RouteServer.Config.RouteServerClient, + SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute, + }, + GracefulRestart: &api.GracefulRestart{ + Enabled: pconf.GracefulRestart.Config.Enabled, + RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), + HelperOnly: pconf.GracefulRestart.Config.HelperOnly, + DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), + NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, + LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, + LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, + }, + Transport: &api.Transport{ + RemotePort: uint32(pconf.Transport.Config.RemotePort), + LocalAddress: pconf.Transport.Config.LocalAddress, + PassiveMode: pconf.Transport.Config.PassiveMode, + }, + AfiSafis: afiSafis, + } +} + +func NewGlobalFromConfigStruct(c *Global) *api.Global { + families := make([]uint32, 0, len(c.AfiSafis)) + for _, f := range c.AfiSafis { + families = append(families, uint32(AfiSafiTypeToIntMap[f.Config.AfiSafiName])) + } + + applyPolicy := newApplyPolicyFromConfigStruct(&c.ApplyPolicy) + + return &api.Global{ + Asn: c.Config.As, + RouterId: c.Config.RouterId, + ListenPort: c.Config.Port, + ListenAddresses: c.Config.LocalAddressList, + Families: families, + UseMultiplePaths: c.UseMultiplePaths.Config.Enabled, + RouteSelectionOptions: &api.RouteSelectionOptionsConfig{ + AlwaysCompareMed: c.RouteSelectionOptions.Config.AlwaysCompareMed, + IgnoreAsPathLength: c.RouteSelectionOptions.Config.IgnoreAsPathLength, + ExternalCompareRouterId: c.RouteSelectionOptions.Config.ExternalCompareRouterId, + AdvertiseInactiveRoutes: c.RouteSelectionOptions.Config.AdvertiseInactiveRoutes, + EnableAigp: c.RouteSelectionOptions.Config.EnableAigp, + IgnoreNextHopIgpMetric: c.RouteSelectionOptions.Config.IgnoreNextHopIgpMetric, + DisableBestPathSelection: c.RouteSelectionOptions.Config.DisableBestPathSelection, + }, + DefaultRouteDistance: &api.DefaultRouteDistance{ + ExternalRouteDistance: uint32(c.DefaultRouteDistance.Config.ExternalRouteDistance), + InternalRouteDistance: uint32(c.DefaultRouteDistance.Config.InternalRouteDistance), + }, + Confederation: &api.Confederation{ + Enabled: c.Confederation.Config.Enabled, + Identifier: c.Confederation.Config.Identifier, + MemberAsList: c.Confederation.Config.MemberAsList, + }, + GracefulRestart: &api.GracefulRestart{ + Enabled: c.GracefulRestart.Config.Enabled, + RestartTime: uint32(c.GracefulRestart.Config.RestartTime), + StaleRoutesTime: uint32(c.GracefulRestart.Config.StaleRoutesTime), + HelperOnly: c.GracefulRestart.Config.HelperOnly, + DeferralTime: uint32(c.GracefulRestart.Config.DeferralTime), + NotificationEnabled: c.GracefulRestart.Config.NotificationEnabled, + LonglivedEnabled: c.GracefulRestart.Config.LongLivedEnabled, + }, + ApplyPolicy: applyPolicy, + } +} + +func newAPIPrefixFromConfigStruct(c Prefix) (*api.Prefix, error) { + min, max, err := ParseMaskLength(c.IpPrefix, c.MasklengthRange) + if err != nil { + return nil, err + } + return &api.Prefix{ + IpPrefix: c.IpPrefix, + MaskLengthMin: uint32(min), + MaskLengthMax: uint32(max), + }, nil +} + +func NewAPIDefinedSetsFromConfigStruct(t *DefinedSets) ([]*api.DefinedSet, error) { + definedSets := make([]*api.DefinedSet, 0) + + for _, ps := range t.PrefixSets { + prefixes := make([]*api.Prefix, 0) + for _, p := range ps.PrefixList { + ap, err := newAPIPrefixFromConfigStruct(p) + if err != nil { + return nil, err + } + prefixes = append(prefixes, ap) + } + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_PREFIX, + Name: ps.PrefixSetName, + Prefixes: prefixes, + }) + } + + for _, ns := range t.NeighborSets { + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_NEIGHBOR, + Name: ns.NeighborSetName, + List: ns.NeighborInfoList, + }) + } + + bs := t.BgpDefinedSets + for _, cs := range bs.CommunitySets { + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_COMMUNITY, + Name: cs.CommunitySetName, + List: cs.CommunityList, + }) + } + + for _, es := range bs.ExtCommunitySets { + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_EXT_COMMUNITY, + Name: es.ExtCommunitySetName, + List: es.ExtCommunityList, + }) + } + + for _, ls := range bs.LargeCommunitySets { + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_LARGE_COMMUNITY, + Name: ls.LargeCommunitySetName, + List: ls.LargeCommunityList, + }) + } + + for _, as := range bs.AsPathSets { + definedSets = append(definedSets, &api.DefinedSet{ + DefinedType: api.DefinedType_AS_PATH, + Name: as.AsPathSetName, + List: as.AsPathList, + }) + } + + return definedSets, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/adj.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/adj.go new file mode 100644 index 000000000..5289e659d --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/adj.go @@ -0,0 +1,253 @@ +// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "fmt" + + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +type AdjRib struct { + accepted map[bgp.RouteFamily]int + table map[bgp.RouteFamily]*Table + logger log.Logger +} + +func NewAdjRib(logger log.Logger, rfList []bgp.RouteFamily) *AdjRib { + m := make(map[bgp.RouteFamily]*Table) + for _, f := range rfList { + m[f] = NewTable(logger, f) + } + return &AdjRib{ + table: m, + accepted: make(map[bgp.RouteFamily]int), + logger: logger, + } +} + +func (adj *AdjRib) Update(pathList []*Path) { + for _, path := range pathList { + if path == nil || path.IsEOR() { + continue + } + rf := path.GetRouteFamily() + t := adj.table[path.GetRouteFamily()] + d := t.getOrCreateDest(path.GetNlri(), 0) + var old *Path + idx := -1 + for i, p := range d.knownPathList { + if p.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() { + idx = i + break + } + } + if idx != -1 { + old = d.knownPathList[idx] + } + + if path.IsWithdraw { + if idx != -1 { + d.knownPathList = append(d.knownPathList[:idx], d.knownPathList[idx+1:]...) + if len(d.knownPathList) == 0 { + t.deleteDest(d) + } + if !old.IsRejected() { + adj.accepted[rf]-- + } + } + path.SetDropped(true) + } else { + if idx != -1 { + if old.IsRejected() && !path.IsRejected() { + adj.accepted[rf]++ + } else if !old.IsRejected() && path.IsRejected() { + adj.accepted[rf]-- + } + if old.Equal(path) { + path.setTimestamp(old.GetTimestamp()) + } + d.knownPathList[idx] = path + } else { + d.knownPathList = append(d.knownPathList, path) + if !path.IsRejected() { + adj.accepted[rf]++ + } + } + } + } +} + +/* +The provided pathList is expected to be the real candidate routes after policy evaluation. + + For routes that are filtered by policy, there could be a mismatch between display + and actual rib sent to the peer (if softreset out was not run). + Only used to display adj-out because we do not maintain a separate adj-out table +*/ +func (adj *AdjRib) UpdateAdjRibOut(pathList []*Path) { + for _, path := range pathList { + if path == nil || path.IsEOR() { + continue + } + t := adj.table[path.GetRouteFamily()] + d := t.getOrCreateDest(path.GetNlri(), 0) + d.knownPathList = append(d.knownPathList, path) + } +} + +func (adj *AdjRib) walk(families []bgp.RouteFamily, fn func(*Destination) bool) { + for _, f := range families { + if t, ok := adj.table[f]; ok { + for _, d := range t.destinations { + if fn(d) { + return + } + } + } + } +} + +func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path { + pathList := make([]*Path, 0, adj.Count(rfList)) + adj.walk(rfList, func(d *Destination) bool { + for _, p := range d.knownPathList { + if accepted && p.IsRejected() { + continue + } + pathList = append(pathList, p) + } + return false + }) + return pathList +} + +func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int { + count := 0 + adj.walk(rfList, func(d *Destination) bool { + count += len(d.knownPathList) + return false + }) + return count +} + +func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int { + count := 0 + for _, rf := range rfList { + if n, ok := adj.accepted[rf]; ok { + count += n + } + } + return count +} + +func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) []*Path { + l := make([]*Path, 0, adj.Count(rfList)) + adj.walk(rfList, func(d *Destination) bool { + for _, p := range d.knownPathList { + w := p.Clone(true) + w.SetDropped(true) + l = append(l, w) + } + return false + }) + for _, rf := range rfList { + adj.table[rf] = NewTable(adj.logger, rf) + adj.accepted[rf] = 0 + } + return l +} + +func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path { + pathList := make([]*Path, 0, adj.Count(rfList)) + adj.walk(rfList, func(d *Destination) bool { + for _, p := range d.knownPathList { + if p.IsStale() { + w := p.Clone(true) + w.SetDropped(true) + pathList = append(pathList, w) + } + } + return false + }) + adj.Update(pathList) + return pathList +} + +func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path { + pathList := make([]*Path, 0, adj.Count(rfList)) + adj.walk(rfList, func(d *Destination) bool { + for i, p := range d.knownPathList { + n := p.Clone(false) + n.MarkStale(true) + n.SetRejected(p.IsRejected()) + d.knownPathList[i] = n + if !n.IsRejected() { + pathList = append(pathList, n) + } + } + return false + }) + return pathList +} + +func (adj *AdjRib) MarkLLGRStaleOrDrop(rfList []bgp.RouteFamily) []*Path { + pathList := make([]*Path, 0, adj.Count(rfList)) + adj.walk(rfList, func(d *Destination) bool { + for i, p := range d.knownPathList { + if p.HasNoLLGR() { + n := p.Clone(true) + n.SetDropped(true) + pathList = append(pathList, n) + } else { + n := p.Clone(false) + n.SetRejected(p.IsRejected()) + n.SetCommunities([]uint32{uint32(bgp.COMMUNITY_LLGR_STALE)}, false) + if p.IsRejected() { + d.knownPathList[i] = n + } else { + pathList = append(pathList, n) + } + } + } + return false + }) + adj.Update(pathList) + return pathList +} + +func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) { + t, ok := adj.table[family] + if !ok { + t = NewTable(adj.logger, family) + } + option = append(option, TableSelectOption{adj: true}) + return t.Select(option...) +} + +func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) { + if _, ok := adj.table[family]; !ok { + return nil, fmt.Errorf("%s unsupported", family) + } + c := adj.Count([]bgp.RouteFamily{family}) + a := adj.Accepted([]bgp.RouteFamily{family}) + return &TableInfo{ + NumDestination: c, + NumPath: c, + NumAccepted: a, + }, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/destination.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/destination.go new file mode 100644 index 000000000..d5b6bcd21 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/destination.go @@ -0,0 +1,934 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "fmt" + "net" + "sort" + + "github.com/osrg/gobgp/v3/internal/pkg/config" + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +var SelectionOptions config.RouteSelectionOptionsConfig +var UseMultiplePaths config.UseMultiplePathsConfig + +type BestPathReason uint8 + +const ( + BPR_UNKNOWN BestPathReason = iota + BPR_DISABLED + BPR_ONLY_PATH + BPR_REACHABLE_NEXT_HOP + BPR_HIGHEST_WEIGHT + BPR_LOCAL_PREF + BPR_LOCAL_ORIGIN + BPR_ASPATH + BPR_ORIGIN + BPR_MED + BPR_ASN + BPR_IGP_COST + BPR_ROUTER_ID + BPR_OLDER + BPR_NON_LLGR_STALE + BPR_NEIGH_ADDR +) + +var BestPathReasonStringMap = map[BestPathReason]string{ + BPR_UNKNOWN: "Unknown", + BPR_DISABLED: "Bestpath selection disabled", + BPR_ONLY_PATH: "Only Path", + BPR_REACHABLE_NEXT_HOP: "Reachable Next Hop", + BPR_HIGHEST_WEIGHT: "Highest Weight", + BPR_LOCAL_PREF: "Local Pref", + BPR_LOCAL_ORIGIN: "Local Origin", + BPR_ASPATH: "AS Path", + BPR_ORIGIN: "Origin", + BPR_MED: "MED", + BPR_ASN: "ASN", + BPR_IGP_COST: "IGP Cost", + BPR_ROUTER_ID: "Router ID", + BPR_OLDER: "Older", + BPR_NON_LLGR_STALE: "no LLGR Stale", + BPR_NEIGH_ADDR: "Neighbor Address", +} + +func (r *BestPathReason) String() string { + return BestPathReasonStringMap[*r] +} + +type PeerInfo struct { + AS uint32 + ID net.IP + LocalAS uint32 + LocalID net.IP + Address net.IP + LocalAddress net.IP + RouteReflectorClient bool + RouteReflectorClusterID net.IP + MultihopTtl uint8 + Confederation bool +} + +func (lhs *PeerInfo) Equal(rhs *PeerInfo) bool { + if lhs == rhs { + return true + } + + if rhs == nil { + return false + } + + if (lhs.AS == rhs.AS) && lhs.ID.Equal(rhs.ID) && lhs.LocalID.Equal(rhs.LocalID) && lhs.Address.Equal(rhs.Address) { + return true + } + return false +} + +func (i *PeerInfo) String() string { + if i.Address == nil { + return "local" + } + s := bytes.NewBuffer(make([]byte, 0, 64)) + s.WriteString(fmt.Sprintf("{ %s | ", i.Address)) + s.WriteString(fmt.Sprintf("as: %d", i.AS)) + s.WriteString(fmt.Sprintf(", id: %s", i.ID)) + if i.RouteReflectorClient { + s.WriteString(fmt.Sprintf(", cluster-id: %s", i.RouteReflectorClusterID)) + } + s.WriteString(" }") + return s.String() +} + +func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo { + clusterID := net.ParseIP(string(p.RouteReflector.State.RouteReflectorClusterId)).To4() + // exclude zone info + naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress) + return &PeerInfo{ + AS: p.Config.PeerAs, + LocalAS: g.Config.As, + LocalID: net.ParseIP(g.Config.RouterId).To4(), + RouteReflectorClient: p.RouteReflector.Config.RouteReflectorClient, + Address: naddr.IP, + RouteReflectorClusterID: clusterID, + MultihopTtl: p.EbgpMultihop.Config.MultihopTtl, + Confederation: p.IsConfederationMember(g), + } +} + +type Destination struct { + routeFamily bgp.RouteFamily + nlri bgp.AddrPrefixInterface + knownPathList []*Path + localIdMap *Bitmap +} + +func NewDestination(nlri bgp.AddrPrefixInterface, mapSize int, known ...*Path) *Destination { + d := &Destination{ + routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()), + nlri: nlri, + knownPathList: known, + localIdMap: NewBitmap(mapSize), + } + // the id zero means id is not allocated yet. + if mapSize != 0 { + d.localIdMap.Flag(0) + } + return d +} + +func (dd *Destination) Family() bgp.RouteFamily { + return dd.routeFamily +} + +func (dd *Destination) setRouteFamily(routeFamily bgp.RouteFamily) { + dd.routeFamily = routeFamily +} + +func (dd *Destination) GetNlri() bgp.AddrPrefixInterface { + return dd.nlri +} + +func (dd *Destination) setNlri(nlri bgp.AddrPrefixInterface) { + dd.nlri = nlri +} + +func (dd *Destination) GetAllKnownPathList() []*Path { + return dd.knownPathList +} + +func rsFilter(id string, as uint32, path *Path) bool { + isASLoop := func(as uint32, path *Path) bool { + for _, v := range path.GetAsList() { + if as == v { + return true + } + } + return false + } + + if id != GLOBAL_RIB_NAME && (path.GetSource().Address.String() == id || isASLoop(as, path)) { + return true + } + return false +} + +func (dd *Destination) GetKnownPathList(id string, as uint32) []*Path { + list := make([]*Path, 0, len(dd.knownPathList)) + for _, p := range dd.knownPathList { + if rsFilter(id, as, p) { + continue + } + list = append(list, p) + } + return list +} + +func getBestPath(id string, as uint32, pathList []*Path) *Path { + for _, p := range pathList { + if rsFilter(id, as, p) { + continue + } + return p + } + return nil +} + +func (dd *Destination) GetBestPath(id string, as uint32) *Path { + p := getBestPath(id, as, dd.knownPathList) + if p == nil || p.IsNexthopInvalid { + return nil + } + return p +} + +func (dd *Destination) GetMultiBestPath(id string) []*Path { + return getMultiBestPath(id, dd.knownPathList) +} + +// Calculates best-path among known paths for this destination. +// +// Modifies destination's state related to stored paths. Removes withdrawn +// paths from known paths. Also, adds new paths to known paths. +func (dest *Destination) Calculate(logger log.Logger, newPath *Path) *Update { + oldKnownPathList := make([]*Path, len(dest.knownPathList)) + copy(oldKnownPathList, dest.knownPathList) + + if newPath.IsWithdraw { + p := dest.explicitWithdraw(logger, newPath) + if p != nil && newPath.IsDropped() { + if id := p.GetNlri().PathLocalIdentifier(); id != 0 { + dest.localIdMap.Unflag(uint(id)) + } + } + } else { + dest.implicitWithdraw(logger, newPath) + dest.knownPathList = append(dest.knownPathList, newPath) + } + + for _, path := range dest.knownPathList { + if path.GetNlri().PathLocalIdentifier() == 0 { + id, err := dest.localIdMap.FindandSetZeroBit() + if err != nil { + dest.localIdMap.Expand() + id, _ = dest.localIdMap.FindandSetZeroBit() + } + path.GetNlri().SetPathLocalIdentifier(uint32(id)) + } + } + // Compute new best path + dest.computeKnownBestPath() + + l := make([]*Path, len(dest.knownPathList)) + copy(l, dest.knownPathList) + return &Update{ + KnownPathList: l, + OldKnownPathList: oldKnownPathList, + } +} + +// Removes withdrawn paths. +// +// Note: +// We may have disproportionate number of withdraws compared to know paths +// since not all paths get installed into the table due to bgp policy and +// we can receive withdraws for such paths and withdrawals may not be +// stopped by the same policies. +func (dest *Destination) explicitWithdraw(logger log.Logger, withdraw *Path) *Path { + logger.Debug("Removing withdrawals", + log.Fields{ + "Topic": "Table", + "Key": dest.GetNlri().String()}) + + // If we have some withdrawals and no know-paths, it means it is safe to + // delete these withdraws. + if len(dest.knownPathList) == 0 { + logger.Debug("Found withdrawals for path(s) that did not get installed", + log.Fields{ + "Topic": "Table", + "Key": dest.GetNlri().String()}) + return nil + } + + // Match all withdrawals from destination paths. + isFound := -1 + for i, path := range dest.knownPathList { + // We have a match if the source and path-id are same. + if path.GetSource().Equal(withdraw.GetSource()) && path.GetNlri().PathIdentifier() == withdraw.GetNlri().PathIdentifier() { + isFound = i + withdraw.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier()) + } + } + + // We do no have any match for this withdraw. + if isFound == -1 { + logger.Warn("No matching path for withdraw found, may be path was not installed into table", + log.Fields{ + "Topic": "Table", + "Key": dest.GetNlri().String(), + "Path": withdraw}) + return nil + } else { + p := dest.knownPathList[isFound] + dest.knownPathList = append(dest.knownPathList[:isFound], dest.knownPathList[isFound+1:]...) + return p + } +} + +// Identifies which of known paths are old and removes them. +// +// Known paths will no longer have paths whose new version is present in +// new paths. +func (dest *Destination) implicitWithdraw(logger log.Logger, newPath *Path) { + found := -1 + for i, path := range dest.knownPathList { + if newPath.NoImplicitWithdraw() { + continue + } + // Here we just check if source is same and not check if path + // version num. as newPaths are implicit withdrawal of old + // paths and when doing RouteRefresh (not EnhancedRouteRefresh) + // we get same paths again. + if newPath.GetSource().Equal(path.GetSource()) && newPath.GetNlri().PathIdentifier() == path.GetNlri().PathIdentifier() { + logger.Debug("Implicit withdrawal of old path, since we have learned new path from the same peer", + log.Fields{ + "Topic": "Table", + "Key": dest.GetNlri().String(), + "Path": path}) + + found = i + newPath.GetNlri().SetPathLocalIdentifier(path.GetNlri().PathLocalIdentifier()) + break + } + } + if found != -1 { + dest.knownPathList = append(dest.knownPathList[:found], dest.knownPathList[found+1:]...) + } +} + +func (dest *Destination) computeKnownBestPath() (*Path, BestPathReason, error) { + if SelectionOptions.DisableBestPathSelection { + return nil, BPR_DISABLED, nil + } + + // If we do not have any paths to this destination, then we do not have + // new best path. + if len(dest.knownPathList) == 0 { + return nil, BPR_UNKNOWN, nil + } + + // We pick the first path as current best path. This helps in breaking + // tie between two new paths learned in one cycle for which best-path + // calculation steps lead to tie. + if len(dest.knownPathList) == 1 { + // If the first path has the invalidated next-hop, which evaluated by + // IGP, returns no path with the reason of the next-hop reachability. + if dest.knownPathList[0].IsNexthopInvalid { + return nil, BPR_REACHABLE_NEXT_HOP, nil + } + return dest.knownPathList[0], BPR_ONLY_PATH, nil + } + reason := dest.sort() + newBest := dest.knownPathList[0] + // If the first path has the invalidated next-hop, which evaluated by IGP, + // returns no path with the reason of the next-hop reachability. + if dest.knownPathList[0].IsNexthopInvalid { + return nil, BPR_REACHABLE_NEXT_HOP, nil + } + return newBest, reason, nil +} + +func (dst *Destination) sort() BestPathReason { + reason := BPR_UNKNOWN + + sort.SliceStable(dst.knownPathList, func(i, j int) bool { + //Compares given paths and returns best path. + // + //Parameters: + // -`path1`: first path to compare + // -`path2`: second path to compare + // + // Best path processing will involve following steps: + // 1. Select a path with a reachable next hop. + // 2. Select the path with the highest weight. + // 3. If path weights are the same, select the path with the highest + // local preference value. + // 4. Prefer locally originated routes (network routes, redistributed + // routes, or aggregated routes) over received routes. + // 5. Select the route with the shortest AS-path length. + // 6. If all paths have the same AS-path length, select the path based + // on origin: IGP is preferred over EGP; EGP is preferred over + // Incomplete. + // 7. If the origins are the same, select the path with lowest MED + // value. + // 8. If the paths have the same MED values, select the path learned + // via EBGP over one learned via IBGP. + // 9. Select the route with the lowest IGP cost to the next hop. + // 10. Select the route received from the peer with the lowest BGP + // router ID. + // + // Returns None if best-path among given paths cannot be computed else best + // path. + // Assumes paths from NC has source equal to None. + // + + path1 := dst.knownPathList[i] + path2 := dst.knownPathList[j] + + var better *Path + + // draft-uttaro-idr-bgp-persistence-02 + if better == nil { + better = compareByLLGRStaleCommunity(path1, path2) + reason = BPR_NON_LLGR_STALE + } + // Follow best path calculation algorithm steps. + // compare by reachability + if better == nil { + better = compareByReachableNexthop(path1, path2) + reason = BPR_REACHABLE_NEXT_HOP + } + + // compareByHighestWeight was a no-op and was removed. + + if better == nil { + better = compareByLocalPref(path1, path2) + reason = BPR_LOCAL_PREF + } + if better == nil { + better = compareByLocalOrigin(path1, path2) + reason = BPR_LOCAL_ORIGIN + } + if better == nil { + better = compareByASPath(path1, path2) + reason = BPR_ASPATH + } + if better == nil { + better = compareByOrigin(path1, path2) + reason = BPR_ORIGIN + } + if better == nil { + better = compareByMED(path1, path2) + reason = BPR_MED + } + if better == nil { + better = compareByASNumber(path1, path2) + reason = BPR_ASN + } + + // compareByIGPCost was a no-op and was removed. + + if better == nil { + better = compareByAge(path1, path2) + reason = BPR_OLDER + } + if better == nil { + better, _ = compareByRouterID(path1, path2) + reason = BPR_ROUTER_ID + } + if better == nil { + better = compareByNeighborAddress(path1, path2) + reason = BPR_NEIGH_ADDR + } + if better == nil { + reason = BPR_UNKNOWN + better = path1 + } + return better == path1 + }) + return reason +} + +type Update struct { + KnownPathList []*Path + OldKnownPathList []*Path +} + +func getMultiBestPath(id string, pathList []*Path) []*Path { + list := make([]*Path, 0, len(pathList)) + var best *Path + for _, p := range pathList { + if !p.IsNexthopInvalid { + if best == nil { + best = p + list = append(list, p) + } else if best.Compare(p) == 0 { + list = append(list, p) + } + } + } + return list +} + +func (u *Update) GetWithdrawnPath() []*Path { + if len(u.KnownPathList) == len(u.OldKnownPathList) { + return nil + } + + l := make([]*Path, 0, len(u.OldKnownPathList)) + + for _, p := range u.OldKnownPathList { + y := func() bool { + for _, old := range u.KnownPathList { + if p == old { + return true + } + } + return false + }() + if !y { + l = append(l, p.Clone(true)) + } + } + return l +} + +func (u *Update) GetChanges(id string, as uint32, peerDown bool) (*Path, *Path, []*Path) { + best, old := func(id string) (*Path, *Path) { + old := getBestPath(id, as, u.OldKnownPathList) + best := getBestPath(id, as, u.KnownPathList) + if best != nil && best.Equal(old) { + // RFC4684 3.2. Intra-AS VPN Route Distribution + // When processing RT membership NLRIs received from internal iBGP + // peers, it is necessary to consider all available iBGP paths for a + // given RT prefix, for building the outbound route filter, and not just + // the best path. + if best.GetRouteFamily() == bgp.RF_RTC_UC { + return best, old + } + // For BGP Nexthop Tracking, checks if the nexthop reachability + // was changed or not. + if best.IsNexthopInvalid != old.IsNexthopInvalid { + // If the nexthop of the best path became unreachable, we need + // to withdraw that path. + if best.IsNexthopInvalid { + return best.Clone(true), old + } + return best, old + } + return nil, old + } + if best == nil { + if old == nil { + return nil, nil + } + if peerDown { + // withdraws were generated by peer + // down so paths are not in knowpath + // or adjin. + old.IsWithdraw = true + return old, old + } + return old.Clone(true), old + } + return best, old + }(id) + + var multi []*Path + + if id == GLOBAL_RIB_NAME && UseMultiplePaths.Enabled { + diff := func(lhs, rhs []*Path) bool { + if len(lhs) != len(rhs) { + return true + } + for idx, l := range lhs { + if !l.Equal(rhs[idx]) { + return true + } + } + return false + } + oldM := getMultiBestPath(id, u.OldKnownPathList) + newM := getMultiBestPath(id, u.KnownPathList) + if diff(oldM, newM) { + multi = newM + if len(newM) == 0 { + multi = []*Path{best} + } + } + } + return best, old, multi +} + +func compareByLLGRStaleCommunity(path1, path2 *Path) *Path { + p1 := path1.IsLLGRStale() + p2 := path2.IsLLGRStale() + if p1 == p2 { + return nil + } else if p1 { + return path2 + } + return path1 +} + +func compareByReachableNexthop(path1, path2 *Path) *Path { + // Compares given paths and selects best path based on reachable next-hop. + // + // If no path matches this criteria, return nil. + // For BGP Nexthop Tracking, evaluates next-hop is validated by IGP. + + if path1.IsNexthopInvalid && !path2.IsNexthopInvalid { + return path2 + } else if !path1.IsNexthopInvalid && path2.IsNexthopInvalid { + return path1 + } + + return nil +} + +func compareByLocalPref(path1, path2 *Path) *Path { + // Selects a path with highest local-preference. + // + // Unlike the weight attribute, which is only relevant to the local + // router, local preference is an attribute that routers exchange in the + // same AS. Highest local-pref is preferred. If we cannot decide, + // we return None. + // + // # Default local-pref values is 100 + localPref1, _ := path1.GetLocalPref() + localPref2, _ := path2.GetLocalPref() + // Highest local-preference value is preferred. + if localPref1 > localPref2 { + return path1 + } else if localPref1 < localPref2 { + return path2 + } else { + return nil + } +} + +func compareByLocalOrigin(path1, path2 *Path) *Path { + + // Select locally originating path as best path. + // Locally originating routes are network routes, redistributed routes, + // or aggregated routes. + // Returns None if given paths have same source. + // + // If both paths are from same sources we cannot compare them here. + if path1.GetSource().Equal(path2.GetSource()) { + return nil + } + + // Here we consider prefix from NC as locally originating static route. + // Hence it is preferred. + if path1.IsLocal() { + return path1 + } + + if path2.IsLocal() { + return path2 + } + return nil +} + +func compareByASPath(path1, path2 *Path) *Path { + // Calculated the best-paths by comparing as-path lengths. + // + // Shortest as-path length is preferred. If both path have same lengths, + // we return None. + if SelectionOptions.IgnoreAsPathLength { + return nil + } + + l1 := path1.GetAsPathLen() + l2 := path2.GetAsPathLen() + + if l1 > l2 { + return path2 + } else if l1 < l2 { + return path1 + } else { + return nil + } +} + +func compareByOrigin(path1, path2 *Path) *Path { + // Select the best path based on origin attribute. + // + // IGP is preferred over EGP; EGP is preferred over Incomplete. + // If both paths have same origin, we return None. + + attribute1 := path1.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN) + attribute2 := path2.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN) + + if attribute1 == nil || attribute2 == nil { + return nil + } + + origin1 := attribute1.(*bgp.PathAttributeOrigin).Value + origin2 := attribute2.(*bgp.PathAttributeOrigin).Value + + // If both paths have same origins + if origin1 == origin2 { + return nil + } else if origin1 < origin2 { + return path1 + } else { + return path2 + } +} + +func compareByMED(path1, path2 *Path) *Path { + // Select the path based with lowest MED value. + // + // If both paths have same MED, return None. + // By default, a route that arrives with no MED value is treated as if it + // had a MED of 0, the most preferred value. + // RFC says lower MED is preferred over higher MED value. + // compare MED among not only same AS path but also all path, + // like bgp always-compare-med + + isInternal := func() bool { return path1.GetAsPathLen() == 0 && path2.GetAsPathLen() == 0 }() + + isSameAS := func() bool { + firstAS := func(path *Path) uint32 { + if asPath := path.GetAsPath(); asPath != nil { + for _, v := range asPath.Value { + segType := v.GetType() + asList := v.GetAS() + if len(asList) == 0 { + continue + } + switch segType { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + continue + } + return asList[0] + } + } + return 0 + } + return firstAS(path1) != 0 && firstAS(path1) == firstAS(path2) + }() + + if SelectionOptions.AlwaysCompareMed || isInternal || isSameAS { + getMed := func(path *Path) uint32 { + attribute := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) + if attribute == nil { + return 0 + } + med := attribute.(*bgp.PathAttributeMultiExitDisc).Value + return med + } + + med1 := getMed(path1) + med2 := getMed(path2) + if med1 == med2 { + return nil + } else if med1 < med2 { + return path1 + } + return path2 + } else { + return nil + } +} + +func compareByASNumber(path1, path2 *Path) *Path { + + //Select the path based on source (iBGP/eBGP) peer. + // + //eBGP path is preferred over iBGP. If both paths are from same kind of + //peers, return None. + + // Path from confederation member should be treated as internal (IBGP learned) path. + isIBGP1 := path1.GetSource().Confederation || path1.IsIBGP() + isIBGP2 := path2.GetSource().Confederation || path2.IsIBGP() + // If one path is from ibgp peer and another is from ebgp peer, take the ebgp path. + if isIBGP1 != isIBGP2 { + if isIBGP1 { + return path2 + } + return path1 + } + + // If both paths are from ebgp or ibpg peers, we cannot decide. + return nil +} + +func compareByRouterID(path1, path2 *Path) (*Path, error) { + // Select the route received from the peer with the lowest BGP router ID. + // + // If both paths are eBGP paths, then we do not do any tie breaking, i.e we do + // not pick best-path based on this criteria. + // RFC: http://tools.ietf.org/html/rfc5004 + // We pick best path between two iBGP paths as usual. + + // If both paths are from NC we have same router Id, hence cannot compare. + if path1.IsLocal() && path2.IsLocal() { + return nil, nil + } + + // If both paths are from eBGP peers, then according to RFC we need + // not tie break using router id. + if !SelectionOptions.ExternalCompareRouterId && !path1.IsIBGP() && !path2.IsIBGP() { + return nil, nil + } + + if !SelectionOptions.ExternalCompareRouterId && path1.IsIBGP() != path2.IsIBGP() { + return nil, fmt.Errorf("this method does not support comparing ebgp with ibgp path") + } + + // At least one path is not coming from NC, so we get local bgp id. + id1 := binary.BigEndian.Uint32(path1.GetSource().ID) + id2 := binary.BigEndian.Uint32(path2.GetSource().ID) + + // If both router ids are same/equal we cannot decide. + // This case is possible since router ids are arbitrary. + if id1 == id2 { + return nil, nil + } else if id1 < id2 { + return path1, nil + } else { + return path2, nil + } +} + +func compareByNeighborAddress(path1, path2 *Path) *Path { + // Select the route received from the peer with the lowest peer address as + // per RFC 4271 9.1.2.2. g + + p1 := path1.GetSource().Address + if p1 == nil { + return path1 + } + p2 := path2.GetSource().Address + if p2 == nil { + return path2 + } + + cmp := bytes.Compare(p1, p2) + if cmp < 0 { + return path1 + } else if cmp > 0 { + return path2 + } + return nil +} + +func compareByAge(path1, path2 *Path) *Path { + if !path1.IsIBGP() && !path2.IsIBGP() && !SelectionOptions.ExternalCompareRouterId { + age1 := path1.GetTimestamp().UnixNano() + age2 := path2.GetTimestamp().UnixNano() + if age1 == age2 { + return nil + } else if age1 < age2 { + return path1 + } + return path2 + } + return nil +} + +func (dest *Destination) String() string { + return fmt.Sprintf("Destination NLRI: %s", dest.nlri.String()) +} + +type DestinationSelectOption struct { + ID string + AS uint32 + VRF *Vrf + adj bool + Best bool + MultiPath bool +} + +func (d *Destination) MarshalJSON() ([]byte, error) { + return json.Marshal(d.GetAllKnownPathList()) +} + +func (d *Destination) Select(option ...DestinationSelectOption) *Destination { + id := GLOBAL_RIB_NAME + var vrf *Vrf + adj := false + best := false + mp := false + as := uint32(0) + for _, o := range option { + if o.ID != "" { + id = o.ID + } + if o.VRF != nil { + vrf = o.VRF + } + adj = o.adj + best = o.Best + mp = o.MultiPath + as = o.AS + } + var paths []*Path + if adj { + paths = make([]*Path, len(d.knownPathList)) + copy(paths, d.knownPathList) + } else { + paths = d.GetKnownPathList(id, as) + if vrf != nil { + ps := make([]*Path, 0, len(paths)) + for _, p := range paths { + if CanImportToVrf(vrf, p) { + ps = append(ps, p.ToLocal()) + } + } + paths = ps + } + if len(paths) == 0 { + return nil + } + if best { + if !mp { + paths = []*Path{paths[0]} + } else { + ps := make([]*Path, 0, len(paths)) + var best *Path + for _, p := range paths { + if best == nil { + best = p + ps = append(ps, p) + } else if best.Compare(p) == 0 { + ps = append(ps, p) + } + } + paths = ps + } + } + } + return NewDestination(d.nlri, 0, paths...) +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/message.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/message.go new file mode 100644 index 000000000..816e202a8 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/message.go @@ -0,0 +1,519 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "bytes" + "fmt" + "reflect" + + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error { + ps := msg.PathAttributes + msg.PathAttributes = make([]bgp.PathAttributeInterface, len(ps)) + copy(msg.PathAttributes, ps) + var asAttr *bgp.PathAttributeAsPath + idx := 0 + for i, attr := range msg.PathAttributes { + if a, ok := attr.(*bgp.PathAttributeAsPath); ok { + asAttr = a + idx = i + break + } + } + + if asAttr == nil { + return nil + } + + as4Params := make([]*bgp.As4PathParam, 0, len(asAttr.Value)) + as2Params := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) + mkAs4 := false + for _, param := range asAttr.Value { + segType := param.GetType() + asList := param.GetAS() + as2Path := make([]uint16, 0, len(asList)) + for _, as := range asList { + if as > (1<<16)-1 { + mkAs4 = true + as2Path = append(as2Path, bgp.AS_TRANS) + } else { + as2Path = append(as2Path, uint16(as)) + } + } + as2Params = append(as2Params, bgp.NewAsPathParam(segType, as2Path)) + + // RFC 6793 4.2.2 Generating Updates + // + // Whenever the AS path information contains the AS_CONFED_SEQUENCE or + // AS_CONFED_SET path segment, the NEW BGP speaker MUST exclude such + // path segments from the AS4_PATH attribute being constructed. + switch segType { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: + // pass + default: + if as4param, ok := param.(*bgp.As4PathParam); ok { + as4Params = append(as4Params, as4param) + } + } + } + msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(as2Params) + if mkAs4 { + msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Path(as4Params)) + } + return nil +} + +func UpdatePathAttrs4ByteAs(logger log.Logger, msg *bgp.BGPUpdate) error { + var asAttr *bgp.PathAttributeAsPath + var as4Attr *bgp.PathAttributeAs4Path + asAttrPos := 0 + as4AttrPos := 0 + for i, attr := range msg.PathAttributes { + switch a := attr.(type) { + case *bgp.PathAttributeAsPath: + asAttr = a + for j, param := range asAttr.Value { + as2Param, ok := param.(*bgp.AsPathParam) + if ok { + asPath := make([]uint32, 0, len(as2Param.AS)) + for _, as := range as2Param.AS { + asPath = append(asPath, uint32(as)) + } + as4Param := bgp.NewAs4PathParam(as2Param.Type, asPath) + asAttr.Value[j] = as4Param + } + } + asAttrPos = i + msg.PathAttributes[i] = asAttr + case *bgp.PathAttributeAs4Path: + as4AttrPos = i + as4Attr = a + } + } + + if as4Attr != nil { + msg.PathAttributes = append(msg.PathAttributes[:as4AttrPos], msg.PathAttributes[as4AttrPos+1:]...) + } + + if asAttr == nil || as4Attr == nil { + return nil + } + + asLen := 0 + asConfedLen := 0 + asParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) + for _, param := range asAttr.Value { + asLen += param.ASLen() + switch param.GetType() { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: + asConfedLen++ + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + asConfedLen += len(param.GetAS()) + } + asParams = append(asParams, param) + } + + as4Len := 0 + var as4Params []bgp.AsPathParamInterface + if as4Attr != nil { + as4Params = make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value)) + for _, p := range as4Attr.Value { + // RFC 6793 6. Error Handling + // + // the path segment types AS_CONFED_SEQUENCE and AS_CONFED_SET [RFC5065] + // MUST NOT be carried in the AS4_PATH attribute of an UPDATE message. + // A NEW BGP speaker that receives these path segment types in the AS4_PATH + // attribute of an UPDATE message from an OLD BGP speaker MUST discard + // these path segments, adjust the relevant attribute fields accordingly, + // and continue processing the UPDATE message. + // This case SHOULD be logged locally for analysis. + switch p.Type { + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET: + typ := "CONFED_SEQ" + if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET { + typ = "CONFED_SET" + } + logger.Warn(fmt.Sprintf("AS4_PATH contains %s segment %s. ignore", typ, p.String()), + log.Fields{ + "Topic": "Table"}) + continue + } + as4Len += p.ASLen() + as4Params = append(as4Params, p) + } + } + + if asLen+asConfedLen < as4Len { + logger.Warn("AS4_PATH is longer than AS_PATH. ignore AS4_PATH", + log.Fields{ + "Topic": "Table"}) + return nil + } + + keepNum := asLen + asConfedLen - as4Len + + newParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) + for _, param := range asParams { + if keepNum-param.ASLen() >= 0 { + newParams = append(newParams, param) + keepNum -= param.ASLen() + } else { + // only SEQ param reaches here + newParams = append(newParams, bgp.NewAs4PathParam(param.GetType(), param.GetAS()[:keepNum])) + keepNum = 0 + } + + if keepNum <= 0 { + break + } + } + + for _, param := range as4Params { + lastParam := newParams[len(newParams)-1] + lastParamAS := lastParam.GetAS() + paramType := param.GetType() + paramAS := param.GetAS() + if paramType == lastParam.GetType() && paramType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { + if len(lastParamAS)+len(paramAS) > 255 { + newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS[:255-len(lastParamAS)]...)) + newParams = append(newParams, bgp.NewAs4PathParam(paramType, paramAS[255-len(lastParamAS):])) + } else { + newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS...)) + } + } else { + newParams = append(newParams, param) + } + } + + newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value)) + newIntfParams = append(newIntfParams, newParams...) + + msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams) + return nil +} + +func UpdatePathAggregator2ByteAs(msg *bgp.BGPUpdate) { + as := uint32(0) + var addr string + for i, attr := range msg.PathAttributes { + switch agg := attr.(type) { + case *bgp.PathAttributeAggregator: + addr = agg.Value.Address.String() + if agg.Value.AS > (1<<16)-1 { + as = agg.Value.AS + msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(bgp.AS_TRANS), addr) + } else { + msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(agg.Value.AS), addr) + } + } + } + if as != 0 { + msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Aggregator(as, addr)) + } +} + +func UpdatePathAggregator4ByteAs(msg *bgp.BGPUpdate) error { + var aggAttr *bgp.PathAttributeAggregator + var agg4Attr *bgp.PathAttributeAs4Aggregator + agg4AttrPos := 0 + for i, attr := range msg.PathAttributes { + switch agg := attr.(type) { + case *bgp.PathAttributeAggregator: + attr := agg + if attr.Value.Askind == reflect.Uint16 { + aggAttr = attr + aggAttr.Value.Askind = reflect.Uint32 + } + case *bgp.PathAttributeAs4Aggregator: + agg4Attr = agg + agg4AttrPos = i + } + } + if aggAttr == nil && agg4Attr == nil { + return nil + } + + if aggAttr == nil && agg4Attr != nil { + return bgp.NewMessageError(bgp.BGP_ERROR_UPDATE_MESSAGE_ERROR, bgp.BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "AS4 AGGREGATOR attribute exists, but AGGREGATOR doesn't") + } + + if agg4Attr != nil { + msg.PathAttributes = append(msg.PathAttributes[:agg4AttrPos], msg.PathAttributes[agg4AttrPos+1:]...) + aggAttr.Value.AS = agg4Attr.Value.AS + } + return nil +} + +type cage struct { + attrsBytes []byte + paths []*Path +} + +func newCage(b []byte, path *Path) *cage { + return &cage{ + attrsBytes: b, + paths: []*Path{path}, + } +} + +type packerInterface interface { + add(*Path) + pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage +} + +type packer struct { + eof bool + family bgp.RouteFamily + total uint32 +} + +type packerMP struct { + packer + paths []*Path + withdrawals []*Path +} + +func (p *packerMP) add(path *Path) { + p.packer.total++ + + if path.IsEOR() { + p.packer.eof = true + return + } + + if path.IsWithdraw { + p.withdrawals = append(p.withdrawals, path) + return + } + + p.paths = append(p.paths, path) +} + +func createMPReachMessage(path *Path) *bgp.BGPMessage { + oattrs := path.GetPathAttrs() + attrs := make([]bgp.PathAttributeInterface, 0, len(oattrs)) + for _, a := range oattrs { + if a.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { + attrs = append(attrs, bgp.NewPathAttributeMpReachNLRI(path.GetNexthop().String(), []bgp.AddrPrefixInterface{path.GetNlri()})) + } else { + attrs = append(attrs, a) + } + } + return bgp.NewBGPUpdateMessage(nil, attrs, nil) +} + +func (p *packerMP) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage { + msgs := make([]*bgp.BGPMessage, 0, p.packer.total) + + for _, path := range p.withdrawals { + nlris := []bgp.AddrPrefixInterface{path.GetNlri()} + msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeMpUnreachNLRI(nlris)}, nil)) + } + + for _, path := range p.paths { + msgs = append(msgs, createMPReachMessage(path)) + } + + if p.eof { + msgs = append(msgs, bgp.NewEndOfRib(p.family)) + } + return msgs +} + +func newPackerMP(f bgp.RouteFamily) *packerMP { + return &packerMP{ + packer: packer{ + family: f, + }, + withdrawals: make([]*Path, 0), + paths: make([]*Path, 0), + } +} + +type packerV4 struct { + packer + hashmap map[uint32][]*cage + mpPaths []*Path + withdrawals []*Path +} + +func (p *packerV4) add(path *Path) { + p.packer.total++ + + if path.IsEOR() { + p.packer.eof = true + return + } + + if path.IsWithdraw { + p.withdrawals = append(p.withdrawals, path) + return + } + + if path.GetNexthop().To4() == nil { + // RFC 5549 + p.mpPaths = append(p.mpPaths, path) + return + } + + key := path.GetHash() + attrsB := bytes.NewBuffer(make([]byte, 0)) + for _, v := range path.GetPathAttrs() { + b, _ := v.Serialize() + attrsB.Write(b) + } + + if cages, y := p.hashmap[key]; y { + added := false + for _, c := range cages { + if bytes.Equal(c.attrsBytes, attrsB.Bytes()) { + c.paths = append(c.paths, path) + added = true + break + } + } + if !added { + p.hashmap[key] = append(p.hashmap[key], newCage(attrsB.Bytes(), path)) + } + } else { + p.hashmap[key] = []*cage{newCage(attrsB.Bytes(), path)} + } +} + +func (p *packerV4) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage { + split := func(max int, paths []*Path) ([]*bgp.IPAddrPrefix, []*Path) { + nlris := make([]*bgp.IPAddrPrefix, 0, max) + i := 0 + if max > len(paths) { + max = len(paths) + } + for ; i < max; i++ { + nlris = append(nlris, paths[i].GetNlri().(*bgp.IPAddrPrefix)) + } + return nlris, paths[i:] + } + addpathNLRILen := 0 + if bgp.IsAddPathEnabled(false, p.packer.family, options) { + addpathNLRILen = 4 + } + // Header + Update (WithdrawnRoutesLen + + // TotalPathAttributeLen + attributes + maxlen of NLRI). + // the max size of NLRI is 5bytes (plus 4bytes with addpath enabled) + maxNLRIs := func(attrsLen int) int { + return (bgp.BGP_MAX_MESSAGE_LENGTH - (19 + 2 + 2 + attrsLen)) / (5 + addpathNLRILen) + } + + loop := func(attrsLen int, paths []*Path, cb func([]*bgp.IPAddrPrefix)) { + max := maxNLRIs(attrsLen) + var nlris []*bgp.IPAddrPrefix + for { + nlris, paths = split(max, paths) + if len(nlris) == 0 { + break + } + cb(nlris) + } + } + + msgs := make([]*bgp.BGPMessage, 0, p.packer.total) + + loop(0, p.withdrawals, func(nlris []*bgp.IPAddrPrefix) { + msgs = append(msgs, bgp.NewBGPUpdateMessage(nlris, nil, nil)) + }) + + for _, cages := range p.hashmap { + for _, c := range cages { + paths := c.paths + + attrs := paths[0].GetPathAttrs() + // we can apply a fix here when gobgp receives from MP peer + // and propagtes to non-MP peer + // we should make sure that next-hop exists in pathattrs + // while we build the update message + // we do not want to modify the `path` though + if paths[0].getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) == nil { + attrs = append(attrs, bgp.NewPathAttributeNextHop(paths[0].GetNexthop().String())) + } + // if we have ever reach here + // there is no point keeping MP_REACH_NLRI in the announcement + attrs_without_mp := make([]bgp.PathAttributeInterface, 0, len(attrs)) + for _, attr := range attrs { + if attr.GetType() != bgp.BGP_ATTR_TYPE_MP_REACH_NLRI { + attrs_without_mp = append(attrs_without_mp, attr) + } + } + attrsLen := 0 + for _, a := range attrs_without_mp { + attrsLen += a.Len() + } + + loop(attrsLen, paths, func(nlris []*bgp.IPAddrPrefix) { + msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, attrs_without_mp, nlris)) + }) + } + } + + for _, path := range p.mpPaths { + msgs = append(msgs, createMPReachMessage(path)) + } + + if p.eof { + msgs = append(msgs, bgp.NewEndOfRib(p.family)) + } + return msgs +} + +func newPackerV4(f bgp.RouteFamily) *packerV4 { + return &packerV4{ + packer: packer{ + family: f, + }, + hashmap: make(map[uint32][]*cage), + withdrawals: make([]*Path, 0), + mpPaths: make([]*Path, 0), + } +} + +func newPacker(f bgp.RouteFamily) packerInterface { + switch f { + case bgp.RF_IPv4_UC: + return newPackerV4(bgp.RF_IPv4_UC) + default: + return newPackerMP(f) + } +} + +func CreateUpdateMsgFromPaths(pathList []*Path, options ...*bgp.MarshallingOption) []*bgp.BGPMessage { + msgs := make([]*bgp.BGPMessage, 0, len(pathList)) + + m := make(map[bgp.RouteFamily]packerInterface) + for _, path := range pathList { + f := path.GetRouteFamily() + if _, y := m[f]; !y { + m[f] = newPacker(f) + } + m[f].add(path) + } + + for _, p := range m { + msgs = append(msgs, p.pack(options...)...) + } + return msgs +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/path.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/path.go new file mode 100644 index 000000000..d6f222a6f --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/path.go @@ -0,0 +1,1283 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "bytes" + "encoding/json" + "fmt" + "math" + "net" + "sort" + "time" + + "github.com/osrg/gobgp/v3/internal/pkg/config" + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +const ( + DEFAULT_LOCAL_PREF = 100 +) + +type Bitmap struct { + bitmap []uint64 +} + +func (b *Bitmap) Flag(i uint) { + b.bitmap[i/64] |= 1 << uint(i%64) +} + +func (b *Bitmap) Unflag(i uint) { + b.bitmap[i/64] &^= 1 << uint(i%64) +} + +func (b *Bitmap) GetFlag(i uint) bool { + return b.bitmap[i/64]&(1< 0 +} + +func (b *Bitmap) FindandSetZeroBit() (uint, error) { + for i := 0; i < len(b.bitmap); i++ { + if b.bitmap[i] == math.MaxUint64 { + continue + } + // replace this with TrailingZero64() when gobgp drops go 1.8 support. + for j := 0; j < 64; j++ { + v := ^b.bitmap[i] + if v&(1< 0 { + r := i*64 + j + b.Flag(uint(r)) + return uint(r), nil + } + } + } + return 0, fmt.Errorf("no space") +} + +func (b *Bitmap) Expand() { + old := b.bitmap + new := make([]uint64, len(old)+1) + copy(new, old) + b.bitmap = new +} + +func NewBitmap(size int) *Bitmap { + b := &Bitmap{} + if size != 0 { + b.bitmap = make([]uint64, (size+64-1)/64) + } + return b +} + +type originInfo struct { + nlri bgp.AddrPrefixInterface + source *PeerInfo + timestamp int64 + noImplicitWithdraw bool + isFromExternal bool + eor bool + stale bool +} + +type RpkiValidationReasonType string + +const ( + RPKI_VALIDATION_REASON_TYPE_NONE RpkiValidationReasonType = "none" + RPKI_VALIDATION_REASON_TYPE_AS RpkiValidationReasonType = "as" + RPKI_VALIDATION_REASON_TYPE_LENGTH RpkiValidationReasonType = "length" +) + +var RpkiValidationReasonTypeToIntMap = map[RpkiValidationReasonType]int{ + RPKI_VALIDATION_REASON_TYPE_NONE: 0, + RPKI_VALIDATION_REASON_TYPE_AS: 1, + RPKI_VALIDATION_REASON_TYPE_LENGTH: 2, +} + +func (v RpkiValidationReasonType) ToInt() int { + i, ok := RpkiValidationReasonTypeToIntMap[v] + if !ok { + return -1 + } + return i +} + +var IntToRpkiValidationReasonTypeMap = map[int]RpkiValidationReasonType{ + 0: RPKI_VALIDATION_REASON_TYPE_NONE, + 1: RPKI_VALIDATION_REASON_TYPE_AS, + 2: RPKI_VALIDATION_REASON_TYPE_LENGTH, +} + +type Validation struct { + Status config.RpkiValidationResultType + Reason RpkiValidationReasonType + Matched []*ROA + UnmatchedAs []*ROA + UnmatchedLength []*ROA +} + +type Path struct { + info *originInfo + parent *Path + pathAttrs []bgp.PathAttributeInterface + dels []bgp.BGPAttrType + attrsHash uint32 + rejected bool + // doesn't exist in the adj + dropped bool + + // For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP. + IsNexthopInvalid bool + IsWithdraw bool +} + +var localSource = &PeerInfo{} + +func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path { + if source == nil { + source = localSource + } + if !isWithdraw && pattrs == nil { + return nil + } + + return &Path{ + info: &originInfo{ + nlri: nlri, + source: source, + timestamp: timestamp.Unix(), + noImplicitWithdraw: noImplicitWithdraw, + }, + IsWithdraw: isWithdraw, + pathAttrs: pattrs, + } +} + +func NewEOR(family bgp.RouteFamily) *Path { + afi, safi := bgp.RouteFamilyToAfiSafi(family) + nlri, _ := bgp.NewPrefixFromRouteFamily(afi, safi) + return &Path{ + info: &originInfo{ + nlri: nlri, + eor: true, + }, + } +} + +func (path *Path) IsEOR() bool { + if path.info != nil && path.info.eor { + return true + } + return false +} + +func cloneAsPath(asAttr *bgp.PathAttributeAsPath) *bgp.PathAttributeAsPath { + newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value)) + for i, param := range asAttr.Value { + asList := param.GetAS() + as := make([]uint32, len(asList)) + copy(as, asList) + newASparams[i] = bgp.NewAs4PathParam(param.GetType(), as) + } + return bgp.NewPathAttributeAsPath(newASparams) +} + +func UpdatePathAttrs(logger log.Logger, global *config.Global, peer *config.Neighbor, info *PeerInfo, original *Path) *Path { + if peer.RouteServer.Config.RouteServerClient { + return original + } + path := original.Clone(original.IsWithdraw) + + for _, a := range path.GetPathAttrs() { + if _, y := bgp.PathAttrFlags[a.GetType()]; !y { + if a.GetFlags()&bgp.BGP_ATTR_FLAG_TRANSITIVE == 0 { + path.delPathAttr(a.GetType()) + } + } else { + switch a.GetType() { + case bgp.BGP_ATTR_TYPE_CLUSTER_LIST, bgp.BGP_ATTR_TYPE_ORIGINATOR_ID: + if !(peer.State.PeerType == config.PEER_TYPE_INTERNAL && peer.RouteReflector.Config.RouteReflectorClient) { + // send these attributes to only rr clients + path.delPathAttr(a.GetType()) + } + } + } + } + + localAddress := info.LocalAddress + nexthop := path.GetNexthop() + if peer.State.PeerType == config.PEER_TYPE_EXTERNAL { + // NEXTHOP handling + if !path.IsLocal() || nexthop.IsUnspecified() { + path.SetNexthop(localAddress) + } + + // remove-private-as handling + path.RemovePrivateAS(peer.Config.LocalAs, peer.State.RemovePrivateAs) + + // AS_PATH handling + confed := peer.IsConfederationMember(global) + path.PrependAsn(peer.Config.LocalAs, 1, confed) + if !confed { + path.removeConfedAs() + } + + // MED Handling + if med := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); med != nil && !path.IsLocal() { + path.delPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) + } + + } else if peer.State.PeerType == config.PEER_TYPE_INTERNAL { + // NEXTHOP handling for iBGP + // if the path generated locally set local address as nexthop. + // if not, don't modify it. + // TODO: NEXT-HOP-SELF support + if path.IsLocal() && nexthop.IsUnspecified() { + path.SetNexthop(localAddress) + } + + // AS_PATH handling for iBGP + // if the path has AS_PATH path attribute, don't modify it. + // if not, attach *empty* AS_PATH path attribute. + if nh := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); nh == nil { + path.PrependAsn(0, 0, false) + } + + // For iBGP peers we are required to send local-pref attribute + // for connected or local prefixes. + // We set default local-pref 100. + if pref := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF); pref == nil { + path.setPathAttr(bgp.NewPathAttributeLocalPref(DEFAULT_LOCAL_PREF)) + } + + // RFC4456: BGP Route Reflection + // 8. Avoiding Routing Information Loops + info := path.GetSource() + if peer.RouteReflector.Config.RouteReflectorClient { + // This attribute will carry the BGP Identifier of the originator of the route in the local AS. + // A BGP speaker SHOULD NOT create an ORIGINATOR_ID attribute if one already exists. + // + // RFC4684 3.2 Intra-AS VPN Route Distribution + // When advertising RT membership NLRI to a route-reflector client, + // the Originator attribute shall be set to the router-id of the + // advertiser, and the Next-hop attribute shall be set of the local + // address for that session. + if path.GetRouteFamily() == bgp.RF_RTC_UC { + path.SetNexthop(localAddress) + path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.LocalID.String())) + } else if path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID) == nil { + if path.IsLocal() { + path.setPathAttr(bgp.NewPathAttributeOriginatorId(global.Config.RouterId)) + } else { + path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.ID.String())) + } + } + // When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST. + // If the CLUSTER_LIST is empty, it MUST create a new one. + clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId) + if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil { + path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID})) + } else { + clusterList := p.(*bgp.PathAttributeClusterList) + newClusterList := make([]string, 0, len(clusterList.Value)) + for _, ip := range clusterList.Value { + newClusterList = append(newClusterList, ip.String()) + } + path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...))) + } + } + + } else { + logger.Warn("invalid peer type", + log.Fields{ + "Topic": "Peer", + "Key": peer.State.NeighborAddress, + "Type": peer.State.PeerType}) + } + return path +} + +func (path *Path) GetTimestamp() time.Time { + return time.Unix(path.OriginInfo().timestamp, 0) +} + +func (path *Path) setTimestamp(t time.Time) { + path.OriginInfo().timestamp = t.Unix() +} + +func (path *Path) IsLocal() bool { + return path.GetSource().Address == nil +} + +func (path *Path) IsIBGP() bool { + as := path.GetSource().AS + return (as == path.GetSource().LocalAS) && as != 0 +} + +// create new PathAttributes +func (path *Path) Clone(isWithdraw bool) *Path { + return &Path{ + parent: path, + IsWithdraw: isWithdraw, + IsNexthopInvalid: path.IsNexthopInvalid, + attrsHash: path.attrsHash, + } +} + +func (path *Path) root() *Path { + p := path + for p.parent != nil { + p = p.parent + } + return p +} + +func (path *Path) OriginInfo() *originInfo { + return path.root().info +} + +func (path *Path) NoImplicitWithdraw() bool { + return path.OriginInfo().noImplicitWithdraw +} + +func (path *Path) IsFromExternal() bool { + return path.OriginInfo().isFromExternal +} + +func (path *Path) SetIsFromExternal(y bool) { + path.OriginInfo().isFromExternal = y +} + +func (path *Path) GetRouteFamily() bgp.RouteFamily { + return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI()) +} + +func (path *Path) GetSource() *PeerInfo { + return path.OriginInfo().source +} + +func (path *Path) MarkStale(s bool) { + path.OriginInfo().stale = s +} + +func (path *Path) IsStale() bool { + return path.OriginInfo().stale +} + +func (path *Path) IsRejected() bool { + return path.rejected +} + +func (path *Path) SetRejected(y bool) { + path.rejected = y +} + +func (path *Path) IsDropped() bool { + return path.dropped +} + +func (path *Path) SetDropped(y bool) { + path.dropped = y +} + +func (path *Path) HasNoLLGR() bool { + for _, c := range path.GetCommunities() { + if c == uint32(bgp.COMMUNITY_NO_LLGR) { + return true + } + } + return false +} + +func (path *Path) IsLLGRStale() bool { + for _, c := range path.GetCommunities() { + if c == uint32(bgp.COMMUNITY_LLGR_STALE) { + return true + } + } + return false +} + +func (path *Path) GetSourceAs() uint32 { + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH) + if attr != nil { + asPathParam := attr.(*bgp.PathAttributeAsPath).Value + if len(asPathParam) == 0 { + return 0 + } + asList := asPathParam[len(asPathParam)-1].GetAS() + if len(asList) == 0 { + return 0 + } + return asList[len(asList)-1] + } + return 0 +} + +func (path *Path) GetNexthop() net.IP { + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) + if attr != nil { + return attr.(*bgp.PathAttributeNextHop).Value + } + attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) + if attr != nil { + return attr.(*bgp.PathAttributeMpReachNLRI).Nexthop + } + return net.IP{} +} + +func (path *Path) SetNexthop(nexthop net.IP) { + if path.GetRouteFamily() == bgp.RF_IPv4_UC && nexthop.To4() == nil { + path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) + mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop.String(), []bgp.AddrPrefixInterface{path.GetNlri()}) + path.setPathAttr(mpreach) + return + } + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) + if attr != nil { + path.setPathAttr(bgp.NewPathAttributeNextHop(nexthop.String())) + } + attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) + if attr != nil { + oldNlri := attr.(*bgp.PathAttributeMpReachNLRI) + path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nexthop.String(), oldNlri.Value)) + } +} + +func (path *Path) GetNlri() bgp.AddrPrefixInterface { + return path.OriginInfo().nlri +} + +type PathAttrs []bgp.PathAttributeInterface + +func (a PathAttrs) Len() int { + return len(a) +} + +func (a PathAttrs) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} + +func (a PathAttrs) Less(i, j int) bool { + return a[i].GetType() < a[j].GetType() +} + +func (path *Path) GetPathAttrs() []bgp.PathAttributeInterface { + deleted := NewBitmap(math.MaxUint8) + modified := make(map[uint]bgp.PathAttributeInterface) + p := path + for { + for _, t := range p.dels { + deleted.Flag(uint(t)) + } + if p.parent == nil { + list := PathAttrs(make([]bgp.PathAttributeInterface, 0, len(p.pathAttrs))) + // we assume that the original pathAttrs are + // in order, that is, other bgp speakers send + // attributes in order. + for _, a := range p.pathAttrs { + typ := uint(a.GetType()) + if m, ok := modified[typ]; ok { + list = append(list, m) + delete(modified, typ) + } else if !deleted.GetFlag(typ) { + list = append(list, a) + } + } + if len(modified) > 0 { + // Huh, some attributes were newly + // added. So we need to sort... + for _, m := range modified { + list = append(list, m) + } + sort.Sort(list) + } + return list + } else { + for _, a := range p.pathAttrs { + typ := uint(a.GetType()) + if _, ok := modified[typ]; !deleted.GetFlag(typ) && !ok { + modified[typ] = a + } + } + } + p = p.parent + } +} + +func (path *Path) getPathAttr(typ bgp.BGPAttrType) bgp.PathAttributeInterface { + p := path + for { + for _, t := range p.dels { + if t == typ { + return nil + } + } + for _, a := range p.pathAttrs { + if a.GetType() == typ { + return a + } + } + if p.parent == nil { + return nil + } + p = p.parent + } +} + +func (path *Path) setPathAttr(a bgp.PathAttributeInterface) { + if len(path.pathAttrs) == 0 { + path.pathAttrs = []bgp.PathAttributeInterface{a} + } else { + for i, b := range path.pathAttrs { + if a.GetType() == b.GetType() { + path.pathAttrs[i] = a + return + } + } + path.pathAttrs = append(path.pathAttrs, a) + } +} + +func (path *Path) delPathAttr(typ bgp.BGPAttrType) { + if len(path.dels) == 0 { + path.dels = []bgp.BGPAttrType{typ} + } else { + path.dels = append(path.dels, typ) + } +} + +// return Path's string representation +func (path *Path) String() string { + s := bytes.NewBuffer(make([]byte, 0, 64)) + if path.IsEOR() { + s.WriteString(fmt.Sprintf("{ %s EOR | src: %s }", path.GetRouteFamily(), path.GetSource())) + return s.String() + } + s.WriteString(fmt.Sprintf("{ %s | ", path.getPrefix())) + s.WriteString(fmt.Sprintf("src: %s", path.GetSource())) + s.WriteString(fmt.Sprintf(", nh: %s", path.GetNexthop())) + if path.IsNexthopInvalid { + s.WriteString(" (not reachable)") + } + if path.IsWithdraw { + s.WriteString(", withdraw") + } + s.WriteString(" }") + return s.String() +} + +func (path *Path) getPrefix() string { + return path.GetNlri().String() +} + +func (path *Path) GetAsPath() *bgp.PathAttributeAsPath { + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH) + if attr != nil { + return attr.(*bgp.PathAttributeAsPath) + } + return nil +} + +// GetAsPathLen returns the number of AS_PATH +func (path *Path) GetAsPathLen() int { + + var length int = 0 + if aspath := path.GetAsPath(); aspath != nil { + for _, as := range aspath.Value { + length += as.ASLen() + } + } + return length +} + +func (path *Path) GetAsString() string { + s := bytes.NewBuffer(make([]byte, 0, 64)) + if aspath := path.GetAsPath(); aspath != nil { + return bgp.AsPathString(aspath) + } + return s.String() +} + +func (path *Path) GetAsList() []uint32 { + return path.getAsListOfSpecificType(true, true) + +} + +func (path *Path) GetAsSeqList() []uint32 { + return path.getAsListOfSpecificType(true, false) + +} + +func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 { + asList := []uint32{} + if aspath := path.GetAsPath(); aspath != nil { + for _, param := range aspath.Value { + segType := param.GetType() + if getAsSeq && segType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { + asList = append(asList, param.GetAS()...) + continue + } + if getAsSet && segType == bgp.BGP_ASPATH_ATTR_TYPE_SET { + asList = append(asList, param.GetAS()...) + } else { + asList = append(asList, 0) + } + } + } + return asList +} + +func (path *Path) GetLabelString() string { + return bgp.LabelString(path.GetNlri()) +} + +// PrependAsn prepends AS number. +// This function updates the AS_PATH attribute as follows. +// (If the peer is in the confederation member AS, +// +// replace AS_SEQUENCE in the following sentence with AS_CONFED_SEQUENCE.) +// 1) if the first path segment of the AS_PATH is of type +// AS_SEQUENCE, the local system prepends the specified AS num as +// the last element of the sequence (put it in the left-most +// position with respect to the position of octets in the +// protocol message) the specified number of times. +// If the act of prepending will cause an overflow in the AS_PATH +// segment (i.e., more than 255 ASes), +// it SHOULD prepend a new segment of type AS_SEQUENCE +// and prepend its own AS number to this new segment. +// +// 2) if the first path segment of the AS_PATH is of other than type +// AS_SEQUENCE, the local system prepends a new path segment of type +// AS_SEQUENCE to the AS_PATH, including the specified AS number in +// that segment. +// +// 3) if the AS_PATH is empty, the local system creates a path +// segment of type AS_SEQUENCE, places the specified AS number +// into that segment, and places that segment into the AS_PATH. +func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) { + var segType uint8 + if confed { + segType = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ + } else { + segType = bgp.BGP_ASPATH_ATTR_TYPE_SEQ + } + + original := path.GetAsPath() + + asns := make([]uint32, repeat) + for i := range asns { + asns[i] = asn + } + + var asPath *bgp.PathAttributeAsPath + if original == nil { + asPath = bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{}) + } else { + asPath = cloneAsPath(original) + } + + if len(asPath.Value) > 0 { + param := asPath.Value[0] + asList := param.GetAS() + if param.GetType() == segType { + if int(repeat)+len(asList) > 255 { + repeat = uint8(255 - len(asList)) + } + newAsList := append(asns[:int(repeat)], asList...) + asPath.Value[0] = bgp.NewAs4PathParam(segType, newAsList) + asns = asns[int(repeat):] + } + } + + if len(asns) > 0 { + p := bgp.NewAs4PathParam(segType, asns) + asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...) + } + path.setPathAttr(asPath) +} + +func isPrivateAS(as uint32) bool { + return (64512 <= as && as <= 65534) || (4200000000 <= as && as <= 4294967294) +} + +func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsOption) { + original := path.GetAsPath() + if original == nil { + return + } + switch option { + case config.REMOVE_PRIVATE_AS_OPTION_ALL, config.REMOVE_PRIVATE_AS_OPTION_REPLACE: + newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) + for _, param := range original.Value { + asList := param.GetAS() + newASParam := make([]uint32, 0, len(asList)) + for _, as := range asList { + if isPrivateAS(as) { + if option == config.REMOVE_PRIVATE_AS_OPTION_REPLACE { + newASParam = append(newASParam, localAS) + } + } else { + newASParam = append(newASParam, as) + } + } + if len(newASParam) > 0 { + newASParams = append(newASParams, bgp.NewAs4PathParam(param.GetType(), newASParam)) + } + } + path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) + } +} + +func (path *Path) removeConfedAs() { + original := path.GetAsPath() + if original == nil { + return + } + newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) + for _, param := range original.Value { + switch param.GetType() { + case bgp.BGP_ASPATH_ATTR_TYPE_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_SET: + newAsParams = append(newAsParams, param) + } + } + path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams)) +} + +func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path { + original := path.GetAsPath() + if original == nil { + return path + } + newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) + changed := false + for _, param := range original.Value { + segType := param.GetType() + asList := param.GetAS() + newASParam := make([]uint32, 0, len(asList)) + for _, as := range asList { + if as == peerAS { + as = localAS + changed = true + } + newASParam = append(newASParam, as) + } + newASParams = append(newASParams, bgp.NewAs4PathParam(segType, newASParam)) + } + if changed { + path = path.Clone(path.IsWithdraw) + path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) + } + return path +} + +func (path *Path) GetCommunities() []uint32 { + communityList := []uint32{} + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES); attr != nil { + communities := attr.(*bgp.PathAttributeCommunities) + communityList = append(communityList, communities.Value...) + } + return communityList +} + +// SetCommunities adds or replaces communities with new ones. +// If the length of communities is 0 and doReplace is true, it clears communities. +func (path *Path) SetCommunities(communities []uint32, doReplace bool) { + + if len(communities) == 0 && doReplace { + // clear communities + path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) + return + } + + newList := make([]uint32, 0) + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) + if attr != nil { + c := attr.(*bgp.PathAttributeCommunities) + if doReplace { + newList = append(newList, communities...) + } else { + newList = append(newList, c.Value...) + newList = append(newList, communities...) + } + } else { + newList = append(newList, communities...) + } + path.setPathAttr(bgp.NewPathAttributeCommunities(newList)) + +} + +// RemoveCommunities removes specific communities. +// If the length of communities is 0, it does nothing. +// If all communities are removed, it removes Communities path attribute itself. +func (path *Path) RemoveCommunities(communities []uint32) int { + + if len(communities) == 0 { + // do nothing + return 0 + } + + find := func(val uint32) bool { + for _, com := range communities { + if com == val { + return true + } + } + return false + } + + count := 0 + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) + if attr != nil { + newList := make([]uint32, 0) + c := attr.(*bgp.PathAttributeCommunities) + + for _, value := range c.Value { + if find(value) { + count += 1 + } else { + newList = append(newList, value) + } + } + + if len(newList) != 0 { + path.setPathAttr(bgp.NewPathAttributeCommunities(newList)) + } else { + path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) + } + } + return count +} + +func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface { + eCommunityList := make([]bgp.ExtendedCommunityInterface, 0) + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil { + eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value + eCommunityList = append(eCommunityList, eCommunities...) + } + return eCommunityList +} + +func (path *Path) SetExtCommunities(exts []bgp.ExtendedCommunityInterface, doReplace bool) { + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES) + if attr != nil { + l := attr.(*bgp.PathAttributeExtendedCommunities).Value + if doReplace { + l = exts + } else { + l = append(l, exts...) + } + path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(l)) + } else { + path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(exts)) + } +} + +func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity { + if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil { + v := a.(*bgp.PathAttributeLargeCommunities).Values + ret := make([]*bgp.LargeCommunity, 0, len(v)) + ret = append(ret, v...) + return ret + } + return nil +} + +func (path *Path) SetLargeCommunities(cs []*bgp.LargeCommunity, doReplace bool) { + if len(cs) == 0 && doReplace { + // clear large communities + path.delPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY) + return + } + + a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY) + if a == nil || doReplace { + path.setPathAttr(bgp.NewPathAttributeLargeCommunities(cs)) + } else { + l := a.(*bgp.PathAttributeLargeCommunities).Values + path.setPathAttr(bgp.NewPathAttributeLargeCommunities(append(l, cs...))) + } +} + +func (path *Path) GetMed() (uint32, error) { + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) + if attr == nil { + return 0, fmt.Errorf("no med path attr") + } + return attr.(*bgp.PathAttributeMultiExitDisc).Value, nil +} + +// SetMed replace, add or subtraction med with new ones. +func (path *Path) SetMed(med int64, doReplace bool) error { + parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) { + if doReplace { + return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil + } + + medVal := int64(orgMed) + med + if medVal < 0 { + return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal) + } else if medVal > int64(math.MaxUint32) { + return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal) + } + + return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil + } + + m := uint32(0) + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); attr != nil { + m = attr.(*bgp.PathAttributeMultiExitDisc).Value + } + newMed, err := parseMed(m, med, doReplace) + if err != nil { + return err + } + path.setPathAttr(newMed) + return nil +} + +func (path *Path) RemoveLocalPref() { + if path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) != nil { + path.delPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) + } +} + +func (path *Path) GetOriginatorID() net.IP { + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID); attr != nil { + return attr.(*bgp.PathAttributeOriginatorId).Value + } + return nil +} + +func (path *Path) GetClusterList() []net.IP { + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); attr != nil { + return attr.(*bgp.PathAttributeClusterList).Value + } + return nil +} + +func (path *Path) GetOrigin() (uint8, error) { + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN); attr != nil { + return attr.(*bgp.PathAttributeOrigin).Value, nil + } + return 0, fmt.Errorf("no origin path attr") +} + +func (path *Path) GetLocalPref() (uint32, error) { + lp := uint32(DEFAULT_LOCAL_PREF) + attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) + if attr != nil { + lp = attr.(*bgp.PathAttributeLocalPref).Value + } + return lp, nil +} + +func (lhs *Path) Equal(rhs *Path) bool { + if rhs == nil { + return false + } + + if !lhs.GetSource().Equal(rhs.GetSource()) { + return false + } + + pattrs := func(arg []bgp.PathAttributeInterface) []byte { + ret := make([]byte, 0) + for _, a := range arg { + aa, _ := a.Serialize() + ret = append(ret, aa...) + } + return ret + } + return bytes.Equal(pattrs(lhs.GetPathAttrs()), pattrs(rhs.GetPathAttrs())) +} + +func (path *Path) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Nlri bgp.AddrPrefixInterface `json:"nlri"` + PathAttrs []bgp.PathAttributeInterface `json:"attrs"` + Age int64 `json:"age"` + Withdrawal bool `json:"withdrawal,omitempty"` + Validation string `json:"validation,omitempty"` + SourceID net.IP `json:"source-id,omitempty"` + NeighborIP net.IP `json:"neighbor-ip,omitempty"` + Stale bool `json:"stale,omitempty"` + UUID string `json:"uuid,omitempty"` + ID uint32 `json:"id,omitempty"` + }{ + Nlri: path.GetNlri(), + PathAttrs: path.GetPathAttrs(), + Age: path.GetTimestamp().Unix(), + Withdrawal: path.IsWithdraw, + SourceID: path.GetSource().ID, + NeighborIP: path.GetSource().Address, + Stale: path.IsStale(), + ID: path.GetNlri().PathIdentifier(), + }) +} + +func (lhs *Path) Compare(rhs *Path) int { + if lhs.IsLocal() && !rhs.IsLocal() { + return 1 + } else if !lhs.IsLocal() && rhs.IsLocal() { + return -1 + } + + if !lhs.IsIBGP() && rhs.IsIBGP() { + return 1 + } else if lhs.IsIBGP() && !rhs.IsIBGP() { + return -1 + } + + lp1, _ := lhs.GetLocalPref() + lp2, _ := rhs.GetLocalPref() + if lp1 != lp2 { + return int(lp1 - lp2) + } + + l1 := lhs.GetAsPathLen() + l2 := rhs.GetAsPathLen() + if l1 != l2 { + return int(l2 - l1) + } + + o1, _ := lhs.GetOrigin() + o2, _ := rhs.GetOrigin() + if o1 != o2 { + return int(o2 - o1) + } + + m1, _ := lhs.GetMed() + m2, _ := rhs.GetMed() + return int(m2 - m1) +} + +func (v *Vrf) ToGlobalPath(path *Path) error { + nlri := path.GetNlri() + switch rf := path.GetRouteFamily(); rf { + case bgp.RF_IPv4_UC: + n := nlri.(*bgp.IPAddrPrefix) + pathIdentifier := path.GetNlri().PathIdentifier() + path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd) + path.GetNlri().SetPathIdentifier(pathIdentifier) + case bgp.RF_FS_IPv4_UC: + n := nlri.(*bgp.FlowSpecIPv4Unicast) + pathIdentifier := path.GetNlri().PathIdentifier() + path.OriginInfo().nlri = bgp.NewFlowSpecIPv4VPN(v.Rd, n.FlowSpecNLRI.Value) + path.GetNlri().SetPathIdentifier(pathIdentifier) + case bgp.RF_IPv6_UC: + n := nlri.(*bgp.IPv6AddrPrefix) + pathIdentifier := path.GetNlri().PathIdentifier() + path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(v.MplsLabel), v.Rd) + path.GetNlri().SetPathIdentifier(pathIdentifier) + case bgp.RF_FS_IPv6_UC: + n := nlri.(*bgp.FlowSpecIPv6Unicast) + pathIdentifier := path.GetNlri().PathIdentifier() + path.OriginInfo().nlri = bgp.NewFlowSpecIPv6VPN(v.Rd, n.FlowSpecNLRI.Value) + path.GetNlri().SetPathIdentifier(pathIdentifier) + case bgp.RF_EVPN: + n := nlri.(*bgp.EVPNNLRI) + switch n.RouteType { + case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: + n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute).RD = v.Rd + case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute).RD = v.Rd + } + case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6: + n := nlri.(*bgp.MUPNLRI) + switch n.RouteType { + case bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY: + n.RouteTypeData.(*bgp.MUPInterworkSegmentDiscoveryRoute).RD = v.Rd + case bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY: + n.RouteTypeData.(*bgp.MUPDirectSegmentDiscoveryRoute).RD = v.Rd + case bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED: + n.RouteTypeData.(*bgp.MUPType1SessionTransformedRoute).RD = v.Rd + case bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED: + n.RouteTypeData.(*bgp.MUPType2SessionTransformedRoute).RD = v.Rd + } + default: + return fmt.Errorf("unsupported route family for vrf: %s", rf) + } + path.SetExtCommunities(v.ExportRt, false) + return nil +} + +func (p *Path) ToGlobal(vrf *Vrf) *Path { + nlri := p.GetNlri() + nh := p.GetNexthop() + pathId := nlri.PathIdentifier() + switch rf := p.GetRouteFamily(); rf { + case bgp.RF_IPv4_UC: + n := nlri.(*bgp.IPAddrPrefix) + nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd) + nlri.SetPathIdentifier(pathId) + case bgp.RF_IPv6_UC: + n := nlri.(*bgp.IPv6AddrPrefix) + nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(vrf.MplsLabel), vrf.Rd) + nlri.SetPathIdentifier(pathId) + case bgp.RF_EVPN: + n := nlri.(*bgp.EVPNNLRI) + switch n.RouteType { + case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: + old := n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute) + new := &bgp.EVPNMacIPAdvertisementRoute{ + RD: vrf.Rd, + ESI: old.ESI, + ETag: old.ETag, + MacAddressLength: old.MacAddressLength, + MacAddress: old.MacAddress, + IPAddressLength: old.IPAddressLength, + IPAddress: old.IPAddress, + Labels: old.Labels, + } + nlri = bgp.NewEVPNNLRI(n.RouteType, new) + case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + old := n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute) + new := &bgp.EVPNMulticastEthernetTagRoute{ + RD: vrf.Rd, + ETag: old.ETag, + IPAddressLength: old.IPAddressLength, + IPAddress: old.IPAddress, + } + nlri = bgp.NewEVPNNLRI(n.RouteType, new) + } + case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6: + n := nlri.(*bgp.MUPNLRI) + switch n.RouteType { + case bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY: + old := n.RouteTypeData.(*bgp.MUPInterworkSegmentDiscoveryRoute) + nlri = bgp.NewMUPInterworkSegmentDiscoveryRoute(vrf.Rd, old.Prefix) + case bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY: + old := n.RouteTypeData.(*bgp.MUPDirectSegmentDiscoveryRoute) + nlri = bgp.NewMUPDirectSegmentDiscoveryRoute(vrf.Rd, old.Address) + case bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED: + old := n.RouteTypeData.(*bgp.MUPType1SessionTransformedRoute) + nlri = bgp.NewMUPType1SessionTransformedRoute(vrf.Rd, old.Prefix, old.TEID, old.QFI, old.EndpointAddress) + case bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED: + old := n.RouteTypeData.(*bgp.MUPType2SessionTransformedRoute) + nlri = bgp.NewMUPType2SessionTransformedRoute(vrf.Rd, old.EndpointAddress, old.TEID) + } + default: + return p + } + path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false) + path.SetExtCommunities(vrf.ExportRt, false) + path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) + path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri})) + return path +} + +func (p *Path) ToLocal() *Path { + nlri := p.GetNlri() + f := p.GetRouteFamily() + localPathId := nlri.PathLocalIdentifier() + pathId := nlri.PathIdentifier() + switch f { + case bgp.RF_IPv4_VPN: + n := nlri.(*bgp.LabeledVPNIPAddrPrefix) + _, c, _ := net.ParseCIDR(n.IPPrefix()) + ones, _ := c.Mask.Size() + nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String()) + nlri.SetPathLocalIdentifier(localPathId) + nlri.SetPathIdentifier(pathId) + case bgp.RF_FS_IPv4_VPN: + n := nlri.(*bgp.FlowSpecIPv4VPN) + nlri = bgp.NewFlowSpecIPv4Unicast(n.FlowSpecNLRI.Value) + nlri.SetPathLocalIdentifier(localPathId) + nlri.SetPathIdentifier(pathId) + case bgp.RF_IPv6_VPN: + n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix) + _, c, _ := net.ParseCIDR(n.IPPrefix()) + ones, _ := c.Mask.Size() + nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String()) + nlri.SetPathLocalIdentifier(localPathId) + nlri.SetPathIdentifier(pathId) + case bgp.RF_FS_IPv6_VPN: + n := nlri.(*bgp.FlowSpecIPv6VPN) + nlri = bgp.NewFlowSpecIPv6Unicast(n.FlowSpecNLRI.Value) + nlri.SetPathLocalIdentifier(localPathId) + nlri.SetPathIdentifier(pathId) + default: + return p + } + path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false) + switch f { + case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN: + path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES) + case bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN: + extcomms := path.GetExtCommunities() + newExtComms := make([]bgp.ExtendedCommunityInterface, 0, len(extcomms)) + for _, extComm := range extcomms { + _, subType := extComm.GetTypes() + if subType == bgp.EC_SUBTYPE_ROUTE_TARGET { + continue + } + newExtComms = append(newExtComms, extComm) + } + path.SetExtCommunities(newExtComms, true) + } + + if f == bgp.RF_IPv4_VPN { + nh := path.GetNexthop() + path.delPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) + path.setPathAttr(bgp.NewPathAttributeNextHop(nh.String())) + } + path.IsNexthopInvalid = p.IsNexthopInvalid + return path +} + +func (p *Path) SetHash(v uint32) { + p.attrsHash = v +} + +func (p *Path) GetHash() uint32 { + return p.attrsHash +} + +func nlriToIPNet(nlri bgp.AddrPrefixInterface) *net.IPNet { + switch T := nlri.(type) { + case *bgp.IPAddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To4()), + Mask: net.CIDRMask(int(T.Length), 32), + } + case *bgp.IPv6AddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To16()), + Mask: net.CIDRMask(int(T.Length), 128), + } + case *bgp.LabeledIPAddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To4()), + Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8, 32), + } + case *bgp.LabeledIPv6AddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To16()), + Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8, 128), + } + case *bgp.LabeledVPNIPAddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To4()), + Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8-T.RD.Len()*8, 32), + } + case *bgp.LabeledVPNIPv6AddrPrefix: + return &net.IPNet{ + IP: net.IP(T.Prefix.To16()), + Mask: net.CIDRMask(int(T.Length)-T.Labels.Len()*8-T.RD.Len()*8, 128), + } + } + return nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/policy.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/policy.go new file mode 100644 index 000000000..d22b1ad95 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/policy.go @@ -0,0 +1,4166 @@ +// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "encoding/json" + "fmt" + "net" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "sync" + + "github.com/k-sone/critbitgo" + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/internal/pkg/config" + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +type PolicyOptions struct { + Info *PeerInfo + OldNextHop net.IP + Validate func(*Path) *Validation +} + +type DefinedType int + +const ( + DEFINED_TYPE_PREFIX DefinedType = iota + DEFINED_TYPE_NEIGHBOR + DEFINED_TYPE_TAG + DEFINED_TYPE_AS_PATH + DEFINED_TYPE_COMMUNITY + DEFINED_TYPE_EXT_COMMUNITY + DEFINED_TYPE_LARGE_COMMUNITY + DEFINED_TYPE_NEXT_HOP +) + +type RouteType int + +const ( + ROUTE_TYPE_NONE RouteType = iota + ROUTE_TYPE_ACCEPT + ROUTE_TYPE_REJECT +) + +func (t RouteType) String() string { + switch t { + case ROUTE_TYPE_NONE: + return "continue" + case ROUTE_TYPE_ACCEPT: + return "accept" + case ROUTE_TYPE_REJECT: + return "reject" + } + return fmt.Sprintf("unknown(%d)", t) +} + +type PolicyDirection int + +const ( + POLICY_DIRECTION_NONE PolicyDirection = iota + POLICY_DIRECTION_IMPORT + POLICY_DIRECTION_EXPORT +) + +func (d PolicyDirection) String() string { + switch d { + case POLICY_DIRECTION_IMPORT: + return "import" + case POLICY_DIRECTION_EXPORT: + return "export" + } + return fmt.Sprintf("unknown(%d)", d) +} + +type MatchOption int + +const ( + MATCH_OPTION_ANY MatchOption = iota + MATCH_OPTION_ALL + MATCH_OPTION_INVERT +) + +func (o MatchOption) String() string { + switch o { + case MATCH_OPTION_ANY: + return "any" + case MATCH_OPTION_ALL: + return "all" + case MATCH_OPTION_INVERT: + return "invert" + default: + return fmt.Sprintf("MatchOption(%d)", o) + } +} + +func (o MatchOption) ConvertToMatchSetOptionsRestrictedType() config.MatchSetOptionsRestrictedType { + switch o { + case MATCH_OPTION_ANY: + return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY + case MATCH_OPTION_INVERT: + return config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT + } + return "unknown" +} + +type MedActionType int + +const ( + MED_ACTION_MOD MedActionType = iota + MED_ACTION_REPLACE +) + +var CommunityOptionNameMap = map[config.BgpSetCommunityOptionType]string{ + config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: "add", + config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: "remove", + config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: "replace", +} + +var CommunityOptionValueMap = map[string]config.BgpSetCommunityOptionType{ + CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD]: config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD, + CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE, + CommunityOptionNameMap[config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE]: config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE, +} + +type ConditionType int + +const ( + CONDITION_PREFIX ConditionType = iota + CONDITION_NEIGHBOR + CONDITION_AS_PATH + CONDITION_COMMUNITY + CONDITION_EXT_COMMUNITY + CONDITION_AS_PATH_LENGTH + CONDITION_RPKI + CONDITION_ROUTE_TYPE + CONDITION_LARGE_COMMUNITY + CONDITION_NEXT_HOP + CONDITION_AFI_SAFI_IN +) + +type ActionType int + +const ( + ACTION_ROUTING ActionType = iota + ACTION_COMMUNITY + ACTION_EXT_COMMUNITY + ACTION_MED + ACTION_AS_PATH_PREPEND + ACTION_NEXTHOP + ACTION_LOCAL_PREF + ACTION_LARGE_COMMUNITY +) + +func NewMatchOption(c interface{}) (MatchOption, error) { + switch t := c.(type) { + case config.MatchSetOptionsType: + t = t.DefaultAsNeeded() + switch t { + case config.MATCH_SET_OPTIONS_TYPE_ANY: + return MATCH_OPTION_ANY, nil + case config.MATCH_SET_OPTIONS_TYPE_ALL: + return MATCH_OPTION_ALL, nil + case config.MATCH_SET_OPTIONS_TYPE_INVERT: + return MATCH_OPTION_INVERT, nil + } + case config.MatchSetOptionsRestrictedType: + t = t.DefaultAsNeeded() + switch t { + case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY: + return MATCH_OPTION_ANY, nil + case config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT: + return MATCH_OPTION_INVERT, nil + } + } + return MATCH_OPTION_ANY, fmt.Errorf("invalid argument to create match option: %v", c) +} + +type AttributeComparison int + +const ( + // "== comparison" + ATTRIBUTE_EQ AttributeComparison = iota + // ">= comparison" + ATTRIBUTE_GE + // "<= comparison" + ATTRIBUTE_LE +) + +func (c AttributeComparison) String() string { + switch c { + case ATTRIBUTE_EQ: + return "=" + case ATTRIBUTE_GE: + return ">=" + case ATTRIBUTE_LE: + return "<=" + } + return "?" +} + +const ( + ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)" +) + +type DefinedSet interface { + Type() DefinedType + Name() string + Append(DefinedSet) error + Remove(DefinedSet) error + Replace(DefinedSet) error + String() string + List() []string +} + +type DefinedSetMap map[DefinedType]map[string]DefinedSet + +type DefinedSetList []DefinedSet + +func (l DefinedSetList) Len() int { + return len(l) +} + +func (l DefinedSetList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +func (l DefinedSetList) Less(i, j int) bool { + if l[i].Type() != l[j].Type() { + return l[i].Type() < l[j].Type() + } + return l[i].Name() < l[j].Name() +} + +type Prefix struct { + Prefix *net.IPNet + AddressFamily bgp.RouteFamily + MasklengthRangeMax uint8 + MasklengthRangeMin uint8 +} + +func (p *Prefix) Match(path *Path) bool { + rf := path.GetRouteFamily() + if rf != p.AddressFamily { + return false + } + + var pAddr net.IP + var pMasklen uint8 + switch rf { + case bgp.RF_IPv4_UC: + pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix + pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length + case bgp.RF_IPv6_UC: + pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix + pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length + default: + return false + } + + return (p.MasklengthRangeMin <= pMasklen && pMasklen <= p.MasklengthRangeMax) && p.Prefix.Contains(pAddr) +} + +func (lhs *Prefix) Equal(rhs *Prefix) bool { + if lhs == rhs { + return true + } + if rhs == nil { + return false + } + return lhs.Prefix.String() == rhs.Prefix.String() && lhs.MasklengthRangeMin == rhs.MasklengthRangeMin && lhs.MasklengthRangeMax == rhs.MasklengthRangeMax +} + +func (p *Prefix) PrefixString() string { + isZeros := func(p net.IP) bool { + for i := 0; i < len(p); i++ { + if p[i] != 0 { + return false + } + } + return true + } + + ip := p.Prefix.IP + if p.AddressFamily == bgp.RF_IPv6_UC && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff { + m, _ := p.Prefix.Mask.Size() + return fmt.Sprintf("::FFFF:%s/%d", ip.To16(), m) + } + return p.Prefix.String() +} + +var _regexpPrefixRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) + +func NewPrefix(c config.Prefix) (*Prefix, error) { + _, prefix, err := net.ParseCIDR(c.IpPrefix) + if err != nil { + return nil, err + } + + rf := bgp.RF_IPv4_UC + if strings.Contains(c.IpPrefix, ":") { + rf = bgp.RF_IPv6_UC + } + p := &Prefix{ + Prefix: prefix, + AddressFamily: rf, + } + maskRange := c.MasklengthRange + + if maskRange == "" { + l, _ := prefix.Mask.Size() + maskLength := uint8(l) + p.MasklengthRangeMax = maskLength + p.MasklengthRangeMin = maskLength + return p, nil + } + + elems := _regexpPrefixRange.FindStringSubmatch(maskRange) + if len(elems) != 3 { + return nil, fmt.Errorf("mask length range format is invalid") + } + + // we've already checked the range is sane by regexp + min, _ := strconv.ParseUint(elems[1], 10, 8) + max, _ := strconv.ParseUint(elems[2], 10, 8) + p.MasklengthRangeMin = uint8(min) + p.MasklengthRangeMax = uint8(max) + return p, nil +} + +type PrefixSet struct { + name string + tree *critbitgo.Net + family bgp.RouteFamily +} + +func (s *PrefixSet) Name() string { + return s.name +} + +func (s *PrefixSet) Type() DefinedType { + return DEFINED_TYPE_PREFIX +} + +func (lhs *PrefixSet) Append(arg DefinedSet) error { + rhs, ok := arg.(*PrefixSet) + if !ok { + return fmt.Errorf("type cast failed") + } + + if rhs.tree.Size() == 0 { + // if try to append an empty set, then return directly + return nil + } else if lhs.tree.Size() != 0 && rhs.family != lhs.family { + return fmt.Errorf("can't append different family") + } + rhs.tree.Walk(nil, func(r *net.IPNet, v interface{}) bool { + w, ok, _ := lhs.tree.Get(r) + if ok { + rp := v.([]*Prefix) + lp := w.([]*Prefix) + lhs.tree.Add(r, append(lp, rp...)) + } else { + lhs.tree.Add(r, v) + } + return true + }) + lhs.family = rhs.family + return nil +} + +func (lhs *PrefixSet) Remove(arg DefinedSet) error { + rhs, ok := arg.(*PrefixSet) + if !ok { + return fmt.Errorf("type cast failed") + } + rhs.tree.Walk(nil, func(r *net.IPNet, v interface{}) bool { + w, ok, _ := lhs.tree.Get(r) + if !ok { + return true + } + rp := v.([]*Prefix) + lp := w.([]*Prefix) + new := make([]*Prefix, 0, len(lp)) + for _, lp := range lp { + delete := false + for _, rp := range rp { + if lp.Equal(rp) { + delete = true + break + } + } + if !delete { + new = append(new, lp) + } + } + if len(new) == 0 { + lhs.tree.Delete(r) + } else { + lhs.tree.Add(r, new) + } + return true + }) + return nil +} + +func (lhs *PrefixSet) Replace(arg DefinedSet) error { + rhs, ok := arg.(*PrefixSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.tree = rhs.tree + lhs.family = rhs.family + return nil +} + +func (s *PrefixSet) List() []string { + var list []string + s.tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool { + ps := v.([]*Prefix) + for _, p := range ps { + list = append(list, fmt.Sprintf("%s %d..%d", p.PrefixString(), p.MasklengthRangeMin, p.MasklengthRangeMax)) + } + return true + }) + return list +} + +func (s *PrefixSet) ToConfig() *config.PrefixSet { + list := make([]config.Prefix, 0, s.tree.Size()) + s.tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool { + ps := v.([]*Prefix) + for _, p := range ps { + list = append(list, config.Prefix{IpPrefix: p.PrefixString(), MasklengthRange: fmt.Sprintf("%d..%d", p.MasklengthRangeMin, p.MasklengthRangeMax)}) + } + return true + }) + return &config.PrefixSet{ + PrefixSetName: s.name, + PrefixList: list, + } +} + +func (s *PrefixSet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *PrefixSet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, error) { + if name == "" { + return nil, fmt.Errorf("empty prefix set name") + } + tree := critbitgo.NewNet() + var family bgp.RouteFamily + for i, x := range prefixes { + if i == 0 { + family = x.AddressFamily + } else if family != x.AddressFamily { + return nil, fmt.Errorf("multiple families") + } + d, ok, _ := tree.Get(x.Prefix) + if ok { + ps := d.([]*Prefix) + tree.Add(x.Prefix, append(ps, x)) + } else { + tree.Add(x.Prefix, []*Prefix{x}) + } + } + return &PrefixSet{ + name: name, + tree: tree, + family: family, + }, nil +} + +func NewPrefixSet(c config.PrefixSet) (*PrefixSet, error) { + name := c.PrefixSetName + if name == "" { + if len(c.PrefixList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty prefix set name") + } + tree := critbitgo.NewNet() + var family bgp.RouteFamily + for i, x := range c.PrefixList { + y, err := NewPrefix(x) + if err != nil { + return nil, err + } + if i == 0 { + family = y.AddressFamily + } else if family != y.AddressFamily { + return nil, fmt.Errorf("multiple families") + } + d, ok, _ := tree.Get(y.Prefix) + if ok { + ps := d.([]*Prefix) + tree.Add(y.Prefix, append(ps, y)) + } else { + tree.Add(y.Prefix, []*Prefix{y}) + } + } + return &PrefixSet{ + name: name, + tree: tree, + family: family, + }, nil +} + +type NextHopSet struct { + list []net.IPNet +} + +func (s *NextHopSet) Name() string { + return "NextHopSet: NO NAME" +} + +func (s *NextHopSet) Type() DefinedType { + return DEFINED_TYPE_NEXT_HOP +} + +func (lhs *NextHopSet) Append(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = append(lhs.list, rhs.list...) + return nil +} + +func (lhs *NextHopSet) Remove(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + ps := make([]net.IPNet, 0, len(lhs.list)) + for _, x := range lhs.list { + found := false + for _, y := range rhs.list { + if x.String() == y.String() { + found = true + break + } + } + if !found { + ps = append(ps, x) + } + } + lhs.list = ps + return nil +} + +func (lhs *NextHopSet) Replace(arg DefinedSet) error { + rhs, ok := arg.(*NextHopSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = rhs.list + return nil +} + +func (s *NextHopSet) List() []string { + list := make([]string, 0, len(s.list)) + for _, n := range s.list { + list = append(list, n.String()) + } + return list +} + +func (s *NextHopSet) ToConfig() []string { + return s.List() +} + +func (s *NextHopSet) String() string { + return "[ " + strings.Join(s.List(), ", ") + " ]" +} + +func (s *NextHopSet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewNextHopSetFromApiStruct(name string, list []net.IPNet) (*NextHopSet, error) { + return &NextHopSet{ + list: list, + }, nil +} + +func NewNextHopSet(c []string) (*NextHopSet, error) { + list := make([]net.IPNet, 0, len(c)) + for _, x := range c { + _, cidr, err := net.ParseCIDR(x) + if err != nil { + addr := net.ParseIP(x) + if addr == nil { + return nil, fmt.Errorf("invalid address or prefix: %s", x) + } + mask := net.CIDRMask(32, 32) + if addr.To4() == nil { + mask = net.CIDRMask(128, 128) + } + cidr = &net.IPNet{ + IP: addr, + Mask: mask, + } + } + list = append(list, *cidr) + } + return &NextHopSet{ + list: list, + }, nil +} + +type NeighborSet struct { + name string + list []net.IPNet +} + +func (s *NeighborSet) Name() string { + return s.name +} + +func (s *NeighborSet) Type() DefinedType { + return DEFINED_TYPE_NEIGHBOR +} + +func (lhs *NeighborSet) Append(arg DefinedSet) error { + rhs, ok := arg.(*NeighborSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = append(lhs.list, rhs.list...) + return nil +} + +func (lhs *NeighborSet) Remove(arg DefinedSet) error { + rhs, ok := arg.(*NeighborSet) + if !ok { + return fmt.Errorf("type cast failed") + } + ps := make([]net.IPNet, 0, len(lhs.list)) + for _, x := range lhs.list { + found := false + for _, y := range rhs.list { + if x.String() == y.String() { + found = true + break + } + } + if !found { + ps = append(ps, x) + } + } + lhs.list = ps + return nil +} + +func (lhs *NeighborSet) Replace(arg DefinedSet) error { + rhs, ok := arg.(*NeighborSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = rhs.list + return nil +} + +func (s *NeighborSet) List() []string { + list := make([]string, 0, len(s.list)) + for _, n := range s.list { + list = append(list, n.String()) + } + return list +} + +func (s *NeighborSet) ToConfig() *config.NeighborSet { + return &config.NeighborSet{ + NeighborSetName: s.name, + NeighborInfoList: s.List(), + } +} + +func (s *NeighborSet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *NeighborSet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewNeighborSetFromApiStruct(name string, list []net.IPNet) (*NeighborSet, error) { + return &NeighborSet{ + name: name, + list: list, + }, nil +} + +func NewNeighborSet(c config.NeighborSet) (*NeighborSet, error) { + name := c.NeighborSetName + if name == "" { + if len(c.NeighborInfoList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty neighbor set name") + } + list := make([]net.IPNet, 0, len(c.NeighborInfoList)) + for _, x := range c.NeighborInfoList { + _, cidr, err := net.ParseCIDR(x) + if err != nil { + addr := net.ParseIP(x) + if addr == nil { + return nil, fmt.Errorf("invalid address or prefix: %s", x) + } + mask := net.CIDRMask(32, 32) + if addr.To4() == nil { + mask = net.CIDRMask(128, 128) + } + cidr = &net.IPNet{ + IP: addr, + Mask: mask, + } + } + list = append(list, *cidr) + } + return &NeighborSet{ + name: name, + list: list, + }, nil +} + +type singleAsPathMatchMode int + +const ( + INCLUDE singleAsPathMatchMode = iota + LEFT_MOST + ORIGIN + ONLY +) + +type singleAsPathMatch struct { + asn uint32 + mode singleAsPathMatchMode +} + +func (lhs *singleAsPathMatch) Equal(rhs *singleAsPathMatch) bool { + return lhs.asn == rhs.asn && lhs.mode == rhs.mode +} + +func (lhs *singleAsPathMatch) String() string { + switch lhs.mode { + case INCLUDE: + return fmt.Sprintf("_%d_", lhs.asn) + case LEFT_MOST: + return fmt.Sprintf("^%d_", lhs.asn) + case ORIGIN: + return fmt.Sprintf("_%d$", lhs.asn) + case ONLY: + return fmt.Sprintf("^%d$", lhs.asn) + } + return "" +} + +func (m *singleAsPathMatch) Match(aspath []uint32) bool { + if len(aspath) == 0 { + return false + } + switch m.mode { + case INCLUDE: + for _, asn := range aspath { + if m.asn == asn { + return true + } + } + case LEFT_MOST: + if m.asn == aspath[0] { + return true + } + case ORIGIN: + if m.asn == aspath[len(aspath)-1] { + return true + } + case ONLY: + if len(aspath) == 1 && m.asn == aspath[0] { + return true + } + } + return false +} + +var ( + _regexpLeftMostRe = regexp.MustCompile(`^\^([0-9]+)_$`) + _regexpOriginRe = regexp.MustCompile(`^_([0-9]+)\$$`) + _regexpIncludeRe = regexp.MustCompile("^_([0-9]+)_$") + _regexpOnlyRe = regexp.MustCompile(`^\^([0-9]+)\$$`) +) + +func NewSingleAsPathMatch(arg string) *singleAsPathMatch { + switch { + case _regexpLeftMostRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpLeftMostRe.FindStringSubmatch(arg)[1], 10, 32) + return &singleAsPathMatch{ + asn: uint32(asn), + mode: LEFT_MOST, + } + case _regexpOriginRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpOriginRe.FindStringSubmatch(arg)[1], 10, 32) + return &singleAsPathMatch{ + asn: uint32(asn), + mode: ORIGIN, + } + case _regexpIncludeRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpIncludeRe.FindStringSubmatch(arg)[1], 10, 32) + return &singleAsPathMatch{ + asn: uint32(asn), + mode: INCLUDE, + } + case _regexpOnlyRe.MatchString(arg): + asn, _ := strconv.ParseUint(_regexpOnlyRe.FindStringSubmatch(arg)[1], 10, 32) + return &singleAsPathMatch{ + asn: uint32(asn), + mode: ONLY, + } + } + return nil +} + +type AsPathSet struct { + typ DefinedType + name string + list []*regexp.Regexp + singleList []*singleAsPathMatch +} + +func (s *AsPathSet) Name() string { + return s.name +} + +func (s *AsPathSet) Type() DefinedType { + return s.typ +} + +func (lhs *AsPathSet) Append(arg DefinedSet) error { + if lhs.Type() != arg.Type() { + return fmt.Errorf("can't append to different type of defined-set") + } + lhs.list = append(lhs.list, arg.(*AsPathSet).list...) + lhs.singleList = append(lhs.singleList, arg.(*AsPathSet).singleList...) + return nil +} + +func (lhs *AsPathSet) Remove(arg DefinedSet) error { + if lhs.Type() != arg.Type() { + return fmt.Errorf("can't append to different type of defined-set") + } + newList := make([]*regexp.Regexp, 0, len(lhs.list)) + for _, x := range lhs.list { + found := false + for _, y := range arg.(*AsPathSet).list { + if x.String() == y.String() { + found = true + break + } + } + if !found { + newList = append(newList, x) + } + } + lhs.list = newList + newSingleList := make([]*singleAsPathMatch, 0, len(lhs.singleList)) + for _, x := range lhs.singleList { + found := false + for _, y := range arg.(*AsPathSet).singleList { + if x.Equal(y) { + found = true + break + } + } + if !found { + newSingleList = append(newSingleList, x) + } + } + lhs.singleList = newSingleList + return nil +} + +func (lhs *AsPathSet) Replace(arg DefinedSet) error { + rhs, ok := arg.(*AsPathSet) + if !ok { + return fmt.Errorf("type cast failed") + } + lhs.list = rhs.list + lhs.singleList = rhs.singleList + return nil +} + +func (s *AsPathSet) List() []string { + list := make([]string, 0, len(s.list)+len(s.singleList)) + for _, exp := range s.singleList { + list = append(list, exp.String()) + } + for _, exp := range s.list { + list = append(list, exp.String()) + } + return list +} + +func (s *AsPathSet) ToConfig() *config.AsPathSet { + return &config.AsPathSet{ + AsPathSetName: s.name, + AsPathList: s.List(), + } +} + +func (s *AsPathSet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *AsPathSet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) { + name := c.AsPathSetName + if name == "" { + if len(c.AsPathList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty as-path set name") + } + list := make([]*regexp.Regexp, 0, len(c.AsPathList)) + singleList := make([]*singleAsPathMatch, 0, len(c.AsPathList)) + for _, x := range c.AsPathList { + if s := NewSingleAsPathMatch(x); s != nil { + singleList = append(singleList, s) + } else { + exp, err := regexp.Compile(strings.Replace(x, "_", ASPATH_REGEXP_MAGIC, -1)) + if err != nil { + return nil, fmt.Errorf("invalid regular expression: %s", x) + } + list = append(list, exp) + } + } + return &AsPathSet{ + typ: DEFINED_TYPE_AS_PATH, + name: name, + list: list, + singleList: singleList, + }, nil +} + +type regExpSet struct { + typ DefinedType + name string + list []*regexp.Regexp +} + +func (s *regExpSet) Name() string { + return s.name +} + +func (s *regExpSet) Type() DefinedType { + return s.typ +} + +func (lhs *regExpSet) Append(arg DefinedSet) error { + if lhs.Type() != arg.Type() { + return fmt.Errorf("can't append to different type of defined-set") + } + var list []*regexp.Regexp + switch lhs.Type() { + case DEFINED_TYPE_AS_PATH: + list = arg.(*AsPathSet).list + case DEFINED_TYPE_COMMUNITY: + list = arg.(*CommunitySet).list + case DEFINED_TYPE_EXT_COMMUNITY: + list = arg.(*ExtCommunitySet).list + case DEFINED_TYPE_LARGE_COMMUNITY: + list = arg.(*LargeCommunitySet).list + default: + return fmt.Errorf("invalid defined-set type: %d", lhs.Type()) + } + lhs.list = append(lhs.list, list...) + return nil +} + +func (lhs *regExpSet) Remove(arg DefinedSet) error { + if lhs.Type() != arg.Type() { + return fmt.Errorf("can't append to different type of defined-set") + } + var list []*regexp.Regexp + switch lhs.Type() { + case DEFINED_TYPE_AS_PATH: + list = arg.(*AsPathSet).list + case DEFINED_TYPE_COMMUNITY: + list = arg.(*CommunitySet).list + case DEFINED_TYPE_EXT_COMMUNITY: + list = arg.(*ExtCommunitySet).list + case DEFINED_TYPE_LARGE_COMMUNITY: + list = arg.(*LargeCommunitySet).list + default: + return fmt.Errorf("invalid defined-set type: %d", lhs.Type()) + } + ps := make([]*regexp.Regexp, 0, len(lhs.list)) + for _, x := range lhs.list { + found := false + for _, y := range list { + if x.String() == y.String() { + found = true + break + } + } + if !found { + ps = append(ps, x) + } + } + lhs.list = ps + return nil +} + +func (lhs *regExpSet) Replace(arg DefinedSet) error { + switch c := arg.(type) { + case *CommunitySet: + lhs.list = c.list + case *ExtCommunitySet: + lhs.list = c.list + case *LargeCommunitySet: + lhs.list = c.list + default: + return fmt.Errorf("type cast failed") + } + return nil +} + +type CommunitySet struct { + regExpSet +} + +func (s *CommunitySet) List() []string { + list := make([]string, 0, len(s.list)) + for _, exp := range s.list { + list = append(list, exp.String()) + } + return list +} + +func (s *CommunitySet) ToConfig() *config.CommunitySet { + return &config.CommunitySet{ + CommunitySetName: s.name, + CommunityList: s.List(), + } +} + +func (s *CommunitySet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *CommunitySet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +var _regexpCommunity = regexp.MustCompile(`(\d+):(\d+)`) + +func ParseCommunity(arg string) (uint32, error) { + i, err := strconv.ParseUint(arg, 10, 32) + if err == nil { + return uint32(i), nil + } + + elems := _regexpCommunity.FindStringSubmatch(arg) + if len(elems) == 3 { + fst, _ := strconv.ParseUint(elems[1], 10, 16) + snd, _ := strconv.ParseUint(elems[2], 10, 16) + return uint32(fst<<16 | snd), nil + } + for i, v := range bgp.WellKnownCommunityNameMap { + if arg == v { + return uint32(i), nil + } + } + return 0, fmt.Errorf("failed to parse %s as community", arg) +} + +func ParseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) { + var subtype bgp.ExtendedCommunityAttrSubType + var value string + elems := strings.SplitN(arg, ":", 2) + + isValidationState := func(s string) bool { + s = strings.ToLower(s) + r := s == bgp.VALIDATION_STATE_VALID.String() + r = r || s == bgp.VALIDATION_STATE_NOT_FOUND.String() + return r || s == bgp.VALIDATION_STATE_INVALID.String() + } + if len(elems) < 2 && (len(elems) < 1 && !isValidationState(elems[0])) { + return nil, fmt.Errorf("invalid ext-community (rt|soo|encap|lb): | valid | not-found | invalid") + } + if isValidationState(elems[0]) { + subtype = bgp.EC_SUBTYPE_ORIGIN_VALIDATION + value = elems[0] + } else { + switch strings.ToLower(elems[0]) { + case "rt": + subtype = bgp.EC_SUBTYPE_ROUTE_TARGET + case "soo": + subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN + case "encap": + subtype = bgp.EC_SUBTYPE_ENCAPSULATION + case "lb": + subtype = bgp.EC_SUBTYPE_LINK_BANDWIDTH + default: + return nil, fmt.Errorf("invalid ext-community (rt|soo|encap|lb): | valid | not-found | invalid") + } + value = elems[1] + } + return bgp.ParseExtendedCommunity(subtype, value) +} + +var _regexpCommunity2 = regexp.MustCompile(`^(\d+.)*\d+:\d+$`) + +func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) { + i, err := strconv.ParseUint(arg, 10, 32) + if err == nil { + return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)) + } + + if _regexpCommunity2.MatchString(arg) { + return regexp.Compile(fmt.Sprintf("^%s$", arg)) + } + + for i, v := range bgp.WellKnownCommunityNameMap { + if strings.Replace(strings.ToLower(arg), "_", "-", -1) == v { + return regexp.Compile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)) + } + } + + return regexp.Compile(arg) +} + +func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) { + var subtype bgp.ExtendedCommunityAttrSubType + elems := strings.SplitN(arg, ":", 2) + if len(elems) < 2 { + return subtype, nil, fmt.Errorf("invalid ext-community format([rt|soo|encap|lb]:)") + } + switch strings.ToLower(elems[0]) { + case "rt": + subtype = bgp.EC_SUBTYPE_ROUTE_TARGET + case "soo": + subtype = bgp.EC_SUBTYPE_ROUTE_ORIGIN + case "encap": + subtype = bgp.EC_SUBTYPE_ENCAPSULATION + case "lb": + subtype = bgp.EC_SUBTYPE_LINK_BANDWIDTH + default: + return subtype, nil, fmt.Errorf("unknown ext-community subtype. rt, soo, encap, lb is supported") + } + exp, err := ParseCommunityRegexp(elems[1]) + return subtype, exp, err +} + +func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) { + name := c.CommunitySetName + if name == "" { + if len(c.CommunityList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty community set name") + } + list := make([]*regexp.Regexp, 0, len(c.CommunityList)) + for _, x := range c.CommunityList { + exp, err := ParseCommunityRegexp(x) + if err != nil { + return nil, err + } + list = append(list, exp) + } + return &CommunitySet{ + regExpSet: regExpSet{ + typ: DEFINED_TYPE_COMMUNITY, + name: name, + list: list, + }, + }, nil +} + +type ExtCommunitySet struct { + regExpSet + subtypeList []bgp.ExtendedCommunityAttrSubType +} + +func (s *ExtCommunitySet) List() []string { + list := make([]string, 0, len(s.list)) + f := func(idx int, arg string) string { + switch s.subtypeList[idx] { + case bgp.EC_SUBTYPE_ROUTE_TARGET: + return fmt.Sprintf("rt:%s", arg) + case bgp.EC_SUBTYPE_ROUTE_ORIGIN: + return fmt.Sprintf("soo:%s", arg) + case bgp.EC_SUBTYPE_ENCAPSULATION: + return fmt.Sprintf("encap:%s", arg) + case bgp.EC_SUBTYPE_ORIGIN_VALIDATION: + return arg + case bgp.EC_SUBTYPE_LINK_BANDWIDTH: + return fmt.Sprintf("lb:%s", arg) + default: + return fmt.Sprintf("%d:%s", s.subtypeList[idx], arg) + } + } + for idx, exp := range s.list { + list = append(list, f(idx, exp.String())) + } + return list +} + +func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet { + return &config.ExtCommunitySet{ + ExtCommunitySetName: s.name, + ExtCommunityList: s.List(), + } +} + +func (s *ExtCommunitySet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *ExtCommunitySet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) { + name := c.ExtCommunitySetName + if name == "" { + if len(c.ExtCommunityList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty ext-community set name") + } + list := make([]*regexp.Regexp, 0, len(c.ExtCommunityList)) + subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.ExtCommunityList)) + for _, x := range c.ExtCommunityList { + subtype, exp, err := ParseExtCommunityRegexp(x) + if err != nil { + return nil, err + } + list = append(list, exp) + subtypeList = append(subtypeList, subtype) + } + return &ExtCommunitySet{ + regExpSet: regExpSet{ + typ: DEFINED_TYPE_EXT_COMMUNITY, + name: name, + list: list, + }, + subtypeList: subtypeList, + }, nil +} + +func (s *ExtCommunitySet) Append(arg DefinedSet) error { + err := s.regExpSet.Append(arg) + if err != nil { + return err + } + sList := arg.(*ExtCommunitySet).subtypeList + s.subtypeList = append(s.subtypeList, sList...) + return nil +} + +type LargeCommunitySet struct { + regExpSet +} + +func (s *LargeCommunitySet) List() []string { + list := make([]string, 0, len(s.list)) + for _, exp := range s.list { + list = append(list, exp.String()) + } + return list +} + +func (s *LargeCommunitySet) ToConfig() *config.LargeCommunitySet { + return &config.LargeCommunitySet{ + LargeCommunitySetName: s.name, + LargeCommunityList: s.List(), + } +} + +func (s *LargeCommunitySet) String() string { + return strings.Join(s.List(), "\n") +} + +func (s *LargeCommunitySet) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +var _regexpCommunityLarge = regexp.MustCompile(`\d+:\d+:\d+`) + +func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) { + if _regexpCommunityLarge.MatchString(arg) { + return regexp.Compile(fmt.Sprintf("^%s$", arg)) + } + exp, err := regexp.Compile(arg) + if err != nil { + return nil, fmt.Errorf("invalid large-community format: %v", err) + } + + return exp, nil +} + +func NewLargeCommunitySet(c config.LargeCommunitySet) (*LargeCommunitySet, error) { + name := c.LargeCommunitySetName + if name == "" { + if len(c.LargeCommunityList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("empty large community set name") + } + list := make([]*regexp.Regexp, 0, len(c.LargeCommunityList)) + for _, x := range c.LargeCommunityList { + exp, err := ParseLargeCommunityRegexp(x) + if err != nil { + return nil, err + } + list = append(list, exp) + } + return &LargeCommunitySet{ + regExpSet: regExpSet{ + typ: DEFINED_TYPE_LARGE_COMMUNITY, + name: name, + list: list, + }, + }, nil +} + +type Condition interface { + Name() string + Type() ConditionType + Evaluate(*Path, *PolicyOptions) bool + Set() DefinedSet +} + +type NextHopCondition struct { + set *NextHopSet +} + +func (c *NextHopCondition) Type() ConditionType { + return CONDITION_NEXT_HOP +} + +func (c *NextHopCondition) Set() DefinedSet { + return c.set +} + +func (c *NextHopCondition) Name() string { return "" } + +func (c *NextHopCondition) String() string { + return c.set.String() +} + +// compare next-hop ipaddress of this condition and source address of path +// and, subsequent comparisons are skipped if that matches the conditions. +// If NextHopSet's length is zero, return true. +func (c *NextHopCondition) Evaluate(path *Path, options *PolicyOptions) bool { + if len(c.set.list) == 0 { + return true + } + + nexthop := path.GetNexthop() + + // In cases where we advertise routes from iBGP to eBGP, we want to filter + // on the "original" nexthop. The current paths' nexthop has already been + // set and is ready to be advertised as per: + // https://tools.ietf.org/html/rfc4271#section-5.1.3 + if options != nil && options.OldNextHop != nil && + !options.OldNextHop.IsUnspecified() && !options.OldNextHop.Equal(nexthop) { + nexthop = options.OldNextHop + } + + if nexthop == nil { + return false + } + + for _, n := range c.set.list { + if n.Contains(nexthop) { + return true + } + } + + return false +} + +func NewNextHopCondition(c []string) (*NextHopCondition, error) { + if len(c) == 0 { + return nil, nil + } + + list, err := NewNextHopSet(c) + if err != nil { + return nil, nil + } + + return &NextHopCondition{ + set: list, + }, nil +} + +type PrefixCondition struct { + set *PrefixSet + option MatchOption +} + +func (c *PrefixCondition) Type() ConditionType { + return CONDITION_PREFIX +} + +func (c *PrefixCondition) Set() DefinedSet { + return c.set +} + +func (c *PrefixCondition) Option() MatchOption { + return c.option +} + +// compare prefixes in this condition and nlri of path and +// subsequent comparison is skipped if that matches the conditions. +// If PrefixList's length is zero, return true. +func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + pathAfi, _ := bgp.RouteFamilyToAfiSafi(path.GetRouteFamily()) + cAfi, _ := bgp.RouteFamilyToAfiSafi(c.set.family) + + if cAfi != pathAfi { + return false + } + + r := nlriToIPNet(path.GetNlri()) + if r == nil { + return false + } + ones, _ := r.Mask.Size() + masklen := uint8(ones) + result := false + if _, ps, _ := c.set.tree.Match(r); ps != nil { + for _, p := range ps.([]*Prefix) { + if p.MasklengthRangeMin <= masklen && masklen <= p.MasklengthRangeMax { + result = true + break + } + } + } + + if c.option == MATCH_OPTION_INVERT { + result = !result + } + + return result +} + +func (c *PrefixCondition) Name() string { return c.set.name } + +func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) { + if c.PrefixSet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &PrefixCondition{ + set: &PrefixSet{ + name: c.PrefixSet, + }, + option: o, + }, nil +} + +type NeighborCondition struct { + set *NeighborSet + option MatchOption +} + +func (c *NeighborCondition) Type() ConditionType { + return CONDITION_NEIGHBOR +} + +func (c *NeighborCondition) Set() DefinedSet { + return c.set +} + +func (c *NeighborCondition) Option() MatchOption { + return c.option +} + +// compare neighbor ipaddress of this condition and source address of path +// and, subsequent comparisons are skipped if that matches the conditions. +// If NeighborList's length is zero, return true. +func (c *NeighborCondition) Evaluate(path *Path, options *PolicyOptions) bool { + if len(c.set.list) == 0 { + return true + } + + neighbor := path.GetSource().Address + if options != nil && options.Info != nil && options.Info.Address != nil { + neighbor = options.Info.Address + } + + if neighbor == nil { + return false + } + result := false + for _, n := range c.set.list { + if n.Contains(neighbor) { + result = true + break + } + } + + if c.option == MATCH_OPTION_INVERT { + result = !result + } + + return result +} + +func (c *NeighborCondition) Name() string { return c.set.name } + +func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error) { + if c.NeighborSet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &NeighborCondition{ + set: &NeighborSet{ + name: c.NeighborSet, + }, + option: o, + }, nil +} + +type AsPathCondition struct { + set *AsPathSet + option MatchOption +} + +func (c *AsPathCondition) Type() ConditionType { + return CONDITION_AS_PATH +} + +func (c *AsPathCondition) Set() DefinedSet { + return c.set +} + +func (c *AsPathCondition) Option() MatchOption { + return c.option +} + +func (c *AsPathCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + if len(c.set.singleList) > 0 { + aspath := path.GetAsSeqList() + for _, m := range c.set.singleList { + result := m.Match(aspath) + if c.option == MATCH_OPTION_ALL && !result { + return false + } + if c.option == MATCH_OPTION_ANY && result { + return true + } + if c.option == MATCH_OPTION_INVERT && result { + return false + } + } + } + if len(c.set.list) > 0 { + aspath := path.GetAsString() + for _, r := range c.set.list { + result := r.MatchString(aspath) + if c.option == MATCH_OPTION_ALL && !result { + return false + } + if c.option == MATCH_OPTION_ANY && result { + return true + } + if c.option == MATCH_OPTION_INVERT && result { + return false + } + } + } + if c.option == MATCH_OPTION_ANY { + return false + } + return true +} + +func (c *AsPathCondition) Name() string { return c.set.name } + +func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) { + if c.AsPathSet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &AsPathCondition{ + set: &AsPathSet{ + name: c.AsPathSet, + }, + option: o, + }, nil +} + +type CommunityCondition struct { + set *CommunitySet + option MatchOption +} + +func (c *CommunityCondition) Type() ConditionType { + return CONDITION_COMMUNITY +} + +func (c *CommunityCondition) Set() DefinedSet { + return c.set +} + +func (c *CommunityCondition) Option() MatchOption { + return c.option +} + +func (c *CommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + cs := path.GetCommunities() + result := false + for _, x := range c.set.list { + result = false + for _, y := range cs { + if x.MatchString(fmt.Sprintf("%d:%d", y>>16, y&0x0000ffff)) { + result = true + break + } + } + if c.option == MATCH_OPTION_ALL && !result { + break + } + if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result { + break + } + } + if c.option == MATCH_OPTION_INVERT { + result = !result + } + return result +} + +func (c *CommunityCondition) Name() string { return c.set.name } + +func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, error) { + if c.CommunitySet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &CommunityCondition{ + set: &CommunitySet{ + regExpSet: regExpSet{ + name: c.CommunitySet, + }, + }, + option: o, + }, nil +} + +type ExtCommunityCondition struct { + set *ExtCommunitySet + option MatchOption +} + +func (c *ExtCommunityCondition) Type() ConditionType { + return CONDITION_EXT_COMMUNITY +} + +func (c *ExtCommunityCondition) Set() DefinedSet { + return c.set +} + +func (c *ExtCommunityCondition) Option() MatchOption { + return c.option +} + +func (c *ExtCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + es := path.GetExtCommunities() + result := false + for _, x := range es { + result = false + typ, subtype := x.GetTypes() + // match only with transitive community. see RFC7153 + if typ >= 0x3f { + continue + } + var xStr string + for idx, y := range c.set.list { + if subtype == c.set.subtypeList[idx] { + if len(xStr) == 0 { + // caching x.String() saves a lot of resources when matching against + // a lot of conditions, link hundreds of RTs. + xStr = x.String() + } + if y.MatchString(xStr) { + result = true + break + } + } + } + if c.option == MATCH_OPTION_ALL && !result { + break + } + if c.option == MATCH_OPTION_ANY && result { + break + } + } + if c.option == MATCH_OPTION_INVERT { + result = !result + } + return result +} + +func (c *ExtCommunityCondition) Name() string { return c.set.name } + +func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondition, error) { + if c.ExtCommunitySet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &ExtCommunityCondition{ + set: &ExtCommunitySet{ + regExpSet: regExpSet{ + name: c.ExtCommunitySet, + }, + }, + option: o, + }, nil +} + +type LargeCommunityCondition struct { + set *LargeCommunitySet + option MatchOption +} + +func (c *LargeCommunityCondition) Type() ConditionType { + return CONDITION_LARGE_COMMUNITY +} + +func (c *LargeCommunityCondition) Set() DefinedSet { + return c.set +} + +func (c *LargeCommunityCondition) Option() MatchOption { + return c.option +} + +func (c *LargeCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + result := false + cs := path.GetLargeCommunities() + for _, x := range c.set.list { + result = false + for _, y := range cs { + if x.MatchString(y.String()) { + result = true + break + } + } + if c.option == MATCH_OPTION_ALL && !result { + break + } + if (c.option == MATCH_OPTION_ANY || c.option == MATCH_OPTION_INVERT) && result { + break + } + } + if c.option == MATCH_OPTION_INVERT { + result = !result + } + return result +} + +func (c *LargeCommunityCondition) Name() string { return c.set.name } + +func NewLargeCommunityCondition(c config.MatchLargeCommunitySet) (*LargeCommunityCondition, error) { + if c.LargeCommunitySet == "" { + return nil, nil + } + o, err := NewMatchOption(c.MatchSetOptions) + if err != nil { + return nil, err + } + return &LargeCommunityCondition{ + set: &LargeCommunitySet{ + regExpSet: regExpSet{ + name: c.LargeCommunitySet, + }, + }, + option: o, + }, nil +} + +type AsPathLengthCondition struct { + length uint32 + operator AttributeComparison +} + +func (c *AsPathLengthCondition) Type() ConditionType { + return CONDITION_AS_PATH_LENGTH +} + +// compare AS_PATH length in the message's AS_PATH attribute with +// the one in condition. +func (c *AsPathLengthCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + + length := uint32(path.GetAsPathLen()) + result := false + switch c.operator { + case ATTRIBUTE_EQ: + result = c.length == length + case ATTRIBUTE_GE: + result = c.length <= length + case ATTRIBUTE_LE: + result = c.length >= length + } + + return result +} + +func (c *AsPathLengthCondition) Set() DefinedSet { + return nil +} + +func (c *AsPathLengthCondition) Name() string { return "" } + +func (c *AsPathLengthCondition) String() string { + return fmt.Sprintf("%s%d", c.operator, c.length) +} + +func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) { + if c.Value == 0 && c.Operator == "" { + return nil, nil + } + var op AttributeComparison + if i := c.Operator.ToInt(); i < 0 { + return nil, fmt.Errorf("invalid as path length operator: %s", c.Operator) + } else { + // take mod 3 because we have extended openconfig attribute-comparison + // for simple configuration. see config.AttributeComparison definition + op = AttributeComparison(i % 3) + } + return &AsPathLengthCondition{ + length: c.Value, + operator: op, + }, nil +} + +type RpkiValidationCondition struct { + result config.RpkiValidationResultType +} + +func (c *RpkiValidationCondition) Type() ConditionType { + return CONDITION_RPKI +} + +func (c *RpkiValidationCondition) Evaluate(path *Path, options *PolicyOptions) bool { + if options != nil && options.Validate != nil { + return c.result == options.Validate(path).Status + } + return false +} + +func (c *RpkiValidationCondition) Set() DefinedSet { + return nil +} + +func (c *RpkiValidationCondition) Name() string { return "" } + +func (c *RpkiValidationCondition) String() string { + return string(c.result) +} + +func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) { + if c == config.RpkiValidationResultType("") || c == config.RPKI_VALIDATION_RESULT_TYPE_NONE { + return nil, nil + } + return &RpkiValidationCondition{ + result: c, + }, nil +} + +type RouteTypeCondition struct { + typ config.RouteType +} + +func (c *RouteTypeCondition) Type() ConditionType { + return CONDITION_ROUTE_TYPE +} + +func (c *RouteTypeCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + switch c.typ { + case config.ROUTE_TYPE_LOCAL: + return path.IsLocal() + case config.ROUTE_TYPE_INTERNAL: + return !path.IsLocal() && path.IsIBGP() + case config.ROUTE_TYPE_EXTERNAL: + return !path.IsLocal() && !path.IsIBGP() + } + return false +} + +func (c *RouteTypeCondition) Set() DefinedSet { + return nil +} + +func (c *RouteTypeCondition) Name() string { return "" } + +func (c *RouteTypeCondition) String() string { + return string(c.typ) +} + +func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) { + if string(c) == "" || c == config.ROUTE_TYPE_NONE { + return nil, nil + } + if err := c.Validate(); err != nil { + return nil, err + } + return &RouteTypeCondition{ + typ: c, + }, nil +} + +type AfiSafiInCondition struct { + routeFamilies []bgp.RouteFamily +} + +func (c *AfiSafiInCondition) Type() ConditionType { + return CONDITION_AFI_SAFI_IN +} + +func (c *AfiSafiInCondition) Evaluate(path *Path, _ *PolicyOptions) bool { + for _, rf := range c.routeFamilies { + if path.GetRouteFamily() == rf { + return true + } + } + return false +} + +func (c *AfiSafiInCondition) Set() DefinedSet { + return nil +} + +func (c *AfiSafiInCondition) Name() string { return "" } + +func (c *AfiSafiInCondition) String() string { + tmp := make([]string, 0, len(c.routeFamilies)) + for _, afiSafi := range c.routeFamilies { + tmp = append(tmp, afiSafi.String()) + } + return strings.Join(tmp, " ") +} + +func NewAfiSafiInCondition(afiSafInConfig []config.AfiSafiType) (*AfiSafiInCondition, error) { + if afiSafInConfig == nil { + return nil, nil + } + + routeFamilies := make([]bgp.RouteFamily, 0, len(afiSafInConfig)) + for _, afiSafiValue := range afiSafInConfig { + if err := afiSafiValue.Validate(); err != nil { + return nil, err + } + rf, err := bgp.GetRouteFamily(string(afiSafiValue)) + if err != nil { + return nil, err + } + routeFamilies = append(routeFamilies, rf) + } + return &AfiSafiInCondition{ + routeFamilies: routeFamilies, + }, nil +} + +type Action interface { + Type() ActionType + Apply(*Path, *PolicyOptions) (*Path, error) + String() string +} + +type RoutingAction struct { + AcceptRoute bool +} + +func (a *RoutingAction) Type() ActionType { + return ACTION_ROUTING +} + +func (a *RoutingAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + if a.AcceptRoute { + return path, nil + } + return nil, nil +} + +func (a *RoutingAction) String() string { + action := "reject" + if a.AcceptRoute { + action = "accept" + } + return action +} + +func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) { + var accept bool + switch c { + case config.RouteDisposition(""), config.ROUTE_DISPOSITION_NONE: + return nil, nil + case config.ROUTE_DISPOSITION_ACCEPT_ROUTE: + accept = true + case config.ROUTE_DISPOSITION_REJECT_ROUTE: + accept = false + default: + return nil, fmt.Errorf("invalid route disposition") + } + return &RoutingAction{ + AcceptRoute: accept, + }, nil +} + +type CommunityAction struct { + action config.BgpSetCommunityOptionType + list []uint32 + removeList []*regexp.Regexp +} + +func RegexpRemoveCommunities(path *Path, exps []*regexp.Regexp) { + comms := path.GetCommunities() + newComms := make([]uint32, 0, len(comms)) + for _, comm := range comms { + c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff) + match := false + for _, exp := range exps { + if exp.MatchString(c) { + match = true + break + } + } + if !match { + newComms = append(newComms, comm) + } + } + path.SetCommunities(newComms, true) +} + +func RegexpRemoveExtCommunities(path *Path, exps []*regexp.Regexp, subtypes []bgp.ExtendedCommunityAttrSubType) { + comms := path.GetExtCommunities() + newComms := make([]bgp.ExtendedCommunityInterface, 0, len(comms)) + for _, comm := range comms { + match := false + typ, subtype := comm.GetTypes() + // match only with transitive community. see RFC7153 + if typ >= 0x3f { + continue + } + for idx, exp := range exps { + if subtype == subtypes[idx] && exp.MatchString(comm.String()) { + match = true + break + } + } + if !match { + newComms = append(newComms, comm) + } + } + path.SetExtCommunities(newComms, true) +} + +func RegexpRemoveLargeCommunities(path *Path, exps []*regexp.Regexp) { + comms := path.GetLargeCommunities() + newComms := make([]*bgp.LargeCommunity, 0, len(comms)) + for _, comm := range comms { + c := comm.String() + match := false + for _, exp := range exps { + if exp.MatchString(c) { + match = true + break + } + } + if !match { + newComms = append(newComms, comm) + } + } + path.SetLargeCommunities(newComms, true) +} + +func (a *CommunityAction) Type() ActionType { + return ACTION_COMMUNITY +} + +func (a *CommunityAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + switch a.action { + case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: + path.SetCommunities(a.list, false) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: + RegexpRemoveCommunities(path, a.removeList) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: + path.SetCommunities(a.list, true) + } + return path, nil +} + +func (a *CommunityAction) ToConfig() *config.SetCommunity { + cs := make([]string, 0, len(a.list)+len(a.removeList)) + for _, comm := range a.list { + c := fmt.Sprintf("%d:%d", comm>>16, comm&0x0000ffff) + cs = append(cs, c) + } + for _, exp := range a.removeList { + cs = append(cs, exp.String()) + } + return &config.SetCommunity{ + Options: string(a.action), + SetCommunityMethod: config.SetCommunityMethod{CommunitiesList: cs}, + } +} + +func (a *CommunityAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +// TODO: this is not efficient use of regexp, probably slow +var _regexpCommunityReplaceString = regexp.MustCompile(`[\^\$]`) + +func (a *CommunityAction) String() string { + list := a.ToConfig().SetCommunityMethod.CommunitiesList + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") + return fmt.Sprintf("%s[%s]", a.action, l) +} + +func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) { + a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)] + if !ok { + if len(c.SetCommunityMethod.CommunitiesList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("invalid option name: %s", c.Options) + } + var list []uint32 + var removeList []*regexp.Regexp + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + removeList = make([]*regexp.Regexp, 0, len(c.SetCommunityMethod.CommunitiesList)) + } else { + list = make([]uint32, 0, len(c.SetCommunityMethod.CommunitiesList)) + } + for _, x := range c.SetCommunityMethod.CommunitiesList { + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + exp, err := ParseCommunityRegexp(x) + if err != nil { + return nil, err + } + removeList = append(removeList, exp) + } else { + comm, err := ParseCommunity(x) + if err != nil { + return nil, err + } + list = append(list, comm) + } + } + return &CommunityAction{ + action: a, + list: list, + removeList: removeList, + }, nil +} + +type ExtCommunityAction struct { + action config.BgpSetCommunityOptionType + list []bgp.ExtendedCommunityInterface + removeList []*regexp.Regexp + subtypeList []bgp.ExtendedCommunityAttrSubType +} + +func (a *ExtCommunityAction) Type() ActionType { + return ACTION_EXT_COMMUNITY +} + +func (a *ExtCommunityAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + switch a.action { + case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: + path.SetExtCommunities(a.list, false) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: + RegexpRemoveExtCommunities(path, a.removeList, a.subtypeList) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: + path.SetExtCommunities(a.list, true) + } + return path, nil +} + +func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity { + cs := make([]string, 0, len(a.list)+len(a.removeList)) + f := func(idx int, arg string) string { + switch a.subtypeList[idx] { + case bgp.EC_SUBTYPE_ROUTE_TARGET: + return fmt.Sprintf("rt:%s", arg) + case bgp.EC_SUBTYPE_ROUTE_ORIGIN: + return fmt.Sprintf("soo:%s", arg) + case bgp.EC_SUBTYPE_ENCAPSULATION: + return fmt.Sprintf("encap:%s", arg) + case bgp.EC_SUBTYPE_LINK_BANDWIDTH: + return fmt.Sprintf("lb:%s", arg) + case bgp.EC_SUBTYPE_ORIGIN_VALIDATION: + return arg + default: + return fmt.Sprintf("%d:%s", a.subtypeList[idx], arg) + } + } + for idx, c := range a.list { + cs = append(cs, f(idx, c.String())) + } + for idx, exp := range a.removeList { + cs = append(cs, f(idx, exp.String())) + } + return &config.SetExtCommunity{ + Options: string(a.action), + SetExtCommunityMethod: config.SetExtCommunityMethod{ + CommunitiesList: cs, + }, + } +} + +func (a *ExtCommunityAction) String() string { + list := a.ToConfig().SetExtCommunityMethod.CommunitiesList + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") + return fmt.Sprintf("%s[%s]", a.action, l) +} + +func (a *ExtCommunityAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) { + a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)] + if !ok { + if len(c.SetExtCommunityMethod.CommunitiesList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("invalid option name: %s", c.Options) + } + var list []bgp.ExtendedCommunityInterface + var removeList []*regexp.Regexp + subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.SetExtCommunityMethod.CommunitiesList)) + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + removeList = make([]*regexp.Regexp, 0, len(c.SetExtCommunityMethod.CommunitiesList)) + } else { + list = make([]bgp.ExtendedCommunityInterface, 0, len(c.SetExtCommunityMethod.CommunitiesList)) + } + for _, x := range c.SetExtCommunityMethod.CommunitiesList { + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + subtype, exp, err := ParseExtCommunityRegexp(x) + if err != nil { + return nil, err + } + removeList = append(removeList, exp) + subtypeList = append(subtypeList, subtype) + } else { + comm, err := ParseExtCommunity(x) + if err != nil { + return nil, err + } + list = append(list, comm) + _, subtype := comm.GetTypes() + subtypeList = append(subtypeList, subtype) + } + } + return &ExtCommunityAction{ + action: a, + list: list, + removeList: removeList, + subtypeList: subtypeList, + }, nil +} + +type LargeCommunityAction struct { + action config.BgpSetCommunityOptionType + list []*bgp.LargeCommunity + removeList []*regexp.Regexp +} + +func (a *LargeCommunityAction) Type() ActionType { + return ACTION_LARGE_COMMUNITY +} + +func (a *LargeCommunityAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + switch a.action { + case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD: + path.SetLargeCommunities(a.list, false) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE: + RegexpRemoveLargeCommunities(path, a.removeList) + case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE: + path.SetLargeCommunities(a.list, true) + } + return path, nil +} + +func (a *LargeCommunityAction) ToConfig() *config.SetLargeCommunity { + cs := make([]string, 0, len(a.list)+len(a.removeList)) + for _, comm := range a.list { + cs = append(cs, comm.String()) + } + for _, exp := range a.removeList { + cs = append(cs, exp.String()) + } + return &config.SetLargeCommunity{ + SetLargeCommunityMethod: config.SetLargeCommunityMethod{CommunitiesList: cs}, + Options: config.BgpSetCommunityOptionType(a.action), + } +} + +func (a *LargeCommunityAction) String() string { + list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList + l := _regexpCommunityReplaceString.ReplaceAllString(strings.Join(list, ", "), "") + return fmt.Sprintf("%s[%s]", a.action, l) +} + +func (a *LargeCommunityAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +func NewLargeCommunityAction(c config.SetLargeCommunity) (*LargeCommunityAction, error) { + a, ok := CommunityOptionValueMap[strings.ToLower(string(c.Options))] + if !ok { + if len(c.SetLargeCommunityMethod.CommunitiesList) == 0 { + return nil, nil + } + return nil, fmt.Errorf("invalid option name: %s", c.Options) + } + var list []*bgp.LargeCommunity + var removeList []*regexp.Regexp + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + removeList = make([]*regexp.Regexp, 0, len(c.SetLargeCommunityMethod.CommunitiesList)) + } else { + list = make([]*bgp.LargeCommunity, 0, len(c.SetLargeCommunityMethod.CommunitiesList)) + } + for _, x := range c.SetLargeCommunityMethod.CommunitiesList { + if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE { + exp, err := ParseLargeCommunityRegexp(x) + if err != nil { + return nil, err + } + removeList = append(removeList, exp) + } else { + comm, err := bgp.ParseLargeCommunity(x) + if err != nil { + return nil, err + } + list = append(list, comm) + } + } + return &LargeCommunityAction{ + action: a, + list: list, + removeList: removeList, + }, nil + +} + +type MedAction struct { + value int64 + action MedActionType +} + +func (a *MedAction) Type() ActionType { + return ACTION_MED +} + +func (a *MedAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + var err error + switch a.action { + case MED_ACTION_MOD: + err = path.SetMed(a.value, false) + case MED_ACTION_REPLACE: + err = path.SetMed(a.value, true) + } + if err != nil { + return path, err + } + return path, nil +} + +func (a *MedAction) ToConfig() config.BgpSetMedType { + if a.action == MED_ACTION_MOD && a.value > 0 { + return config.BgpSetMedType(fmt.Sprintf("+%d", a.value)) + } + return config.BgpSetMedType(fmt.Sprintf("%d", a.value)) +} + +func (a *MedAction) String() string { + return string(a.ToConfig()) +} + +func (a *MedAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +var _regexpParseMedAction = regexp.MustCompile(`^(\+|\-)?(\d+)$`) + +func NewMedAction(c config.BgpSetMedType) (*MedAction, error) { + if string(c) == "" { + return nil, nil + } + + elems := _regexpParseMedAction.FindStringSubmatch(string(c)) + if len(elems) != 3 { + return nil, fmt.Errorf("invalid med action format") + } + action := MED_ACTION_REPLACE + switch elems[1] { + case "+", "-": + action = MED_ACTION_MOD + } + value, _ := strconv.ParseInt(string(c), 10, 64) + return &MedAction{ + value: value, + action: action, + }, nil +} + +func NewMedActionFromApiStruct(action MedActionType, value int64) *MedAction { + return &MedAction{action: action, value: value} +} + +type LocalPrefAction struct { + value uint32 +} + +func (a *LocalPrefAction) Type() ActionType { + return ACTION_LOCAL_PREF +} + +func (a *LocalPrefAction) Apply(path *Path, _ *PolicyOptions) (*Path, error) { + path.setPathAttr(bgp.NewPathAttributeLocalPref(a.value)) + return path, nil +} + +func (a *LocalPrefAction) ToConfig() uint32 { + return a.value +} + +func (a *LocalPrefAction) String() string { + return fmt.Sprintf("%d", a.value) +} + +func (a *LocalPrefAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +func NewLocalPrefAction(value uint32) (*LocalPrefAction, error) { + if value == 0 { + return nil, nil + } + return &LocalPrefAction{ + value: value, + }, nil +} + +type AsPathPrependAction struct { + asn uint32 + useLeftMost bool + repeat uint8 +} + +func (a *AsPathPrependAction) Type() ActionType { + return ACTION_AS_PATH_PREPEND +} + +func (a *AsPathPrependAction) Apply(path *Path, option *PolicyOptions) (*Path, error) { + var asn uint32 + if a.useLeftMost { + aspath := path.GetAsSeqList() + if len(aspath) == 0 { + return path, nil + } + asn = aspath[0] + if asn == 0 { + return path, nil + } + } else { + asn = a.asn + } + + confed := option != nil && option.Info != nil && option.Info.Confederation + path.PrependAsn(asn, a.repeat, confed) + + return path, nil +} + +func (a *AsPathPrependAction) ToConfig() *config.SetAsPathPrepend { + return &config.SetAsPathPrepend{ + RepeatN: uint8(a.repeat), + As: func() string { + if a.useLeftMost { + return "last-as" + } + return fmt.Sprintf("%d", a.asn) + }(), + } +} + +func (a *AsPathPrependAction) String() string { + c := a.ToConfig() + return fmt.Sprintf("prepend %s %d times", c.As, c.RepeatN) +} + +func (a *AsPathPrependAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +// NewAsPathPrependAction creates AsPathPrependAction object. +// If ASN cannot be parsed, nil will be returned. +func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) { + a := &AsPathPrependAction{ + repeat: action.RepeatN, + } + switch action.As { + case "": + if a.repeat == 0 { + return nil, nil + } + return nil, fmt.Errorf("specify as to prepend") + case "last-as": + a.useLeftMost = true + default: + asn, err := strconv.ParseUint(action.As, 10, 32) + if err != nil { + return nil, fmt.Errorf("AS number string invalid") + } + a.asn = uint32(asn) + } + return a, nil +} + +type NexthopAction struct { + value net.IP + self bool + unchanged bool +} + +func (a *NexthopAction) Type() ActionType { + return ACTION_NEXTHOP +} + +func (a *NexthopAction) Apply(path *Path, options *PolicyOptions) (*Path, error) { + if a.self { + if options != nil && options.Info != nil && options.Info.LocalAddress != nil { + path.SetNexthop(options.Info.LocalAddress) + } + return path, nil + } + if a.unchanged { + if options != nil && options.OldNextHop != nil { + path.SetNexthop(options.OldNextHop) + } + return path, nil + } + path.SetNexthop(a.value) + return path, nil +} + +func (a *NexthopAction) ToConfig() config.BgpNextHopType { + if a.self { + return config.BgpNextHopType("self") + } + if a.unchanged { + return config.BgpNextHopType("unchanged") + } + return config.BgpNextHopType(a.value.String()) +} + +func (a *NexthopAction) String() string { + return string(a.ToConfig()) +} + +func (a *NexthopAction) MarshalJSON() ([]byte, error) { + return json.Marshal(a.ToConfig()) +} + +func NewNexthopAction(c config.BgpNextHopType) (*NexthopAction, error) { + switch strings.ToLower(string(c)) { + case "": + return nil, nil + case "self": + return &NexthopAction{ + self: true, + }, nil + case "unchanged": + return &NexthopAction{ + unchanged: true, + }, nil + } + addr := net.ParseIP(string(c)) + if addr == nil { + return nil, fmt.Errorf("invalid ip address format: %s", string(c)) + } + return &NexthopAction{ + value: addr, + }, nil +} + +type Statement struct { + Name string + Conditions []Condition + RouteAction Action + ModActions []Action +} + +// evaluate each condition in the statement according to MatchSetOptions +func (s *Statement) Evaluate(p *Path, options *PolicyOptions) bool { + for _, c := range s.Conditions { + if !c.Evaluate(p, options) { + return false + } + } + return true +} + +func (s *Statement) Apply(logger log.Logger, path *Path, options *PolicyOptions) (RouteType, *Path) { + result := s.Evaluate(path, options) + if result { + if len(s.ModActions) != 0 { + // apply all modification actions + path = path.Clone(path.IsWithdraw) + for _, action := range s.ModActions { + var err error + path, err = action.Apply(path, options) + if err != nil { + logger.Warn("action failed", + log.Fields{ + "Topic": "policy", + "Error": err}) + } + } + } + //Routing action + if s.RouteAction == nil || reflect.ValueOf(s.RouteAction).IsNil() { + return ROUTE_TYPE_NONE, path + } + p, _ := s.RouteAction.Apply(path, options) + if p == nil { + return ROUTE_TYPE_REJECT, path + } + return ROUTE_TYPE_ACCEPT, path + } + return ROUTE_TYPE_NONE, path +} + +func (s *Statement) ToConfig() *config.Statement { + return &config.Statement{ + Name: s.Name, + Conditions: func() config.Conditions { + cond := config.Conditions{} + for _, c := range s.Conditions { + switch v := c.(type) { + case *PrefixCondition: + cond.MatchPrefixSet = config.MatchPrefixSet{PrefixSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()} + case *NeighborCondition: + cond.MatchNeighborSet = config.MatchNeighborSet{NeighborSet: v.set.Name(), MatchSetOptions: v.option.ConvertToMatchSetOptionsRestrictedType()} + case *AsPathLengthCondition: + cond.BgpConditions.AsPathLength = config.AsPathLength{Operator: config.IntToAttributeComparisonMap[int(v.operator)], Value: v.length} + case *AsPathCondition: + cond.BgpConditions.MatchAsPathSet = config.MatchAsPathSet{AsPathSet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]} + case *CommunityCondition: + cond.BgpConditions.MatchCommunitySet = config.MatchCommunitySet{CommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]} + case *ExtCommunityCondition: + cond.BgpConditions.MatchExtCommunitySet = config.MatchExtCommunitySet{ExtCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]} + case *LargeCommunityCondition: + cond.BgpConditions.MatchLargeCommunitySet = config.MatchLargeCommunitySet{LargeCommunitySet: v.set.Name(), MatchSetOptions: config.IntToMatchSetOptionsTypeMap[int(v.option)]} + case *NextHopCondition: + cond.BgpConditions.NextHopInList = v.set.List() + case *RpkiValidationCondition: + cond.BgpConditions.RpkiValidationResult = v.result + case *RouteTypeCondition: + cond.BgpConditions.RouteType = v.typ + case *AfiSafiInCondition: + res := make([]config.AfiSafiType, 0, len(v.routeFamilies)) + for _, rf := range v.routeFamilies { + res = append(res, config.AfiSafiType(rf.String())) + } + cond.BgpConditions.AfiSafiInList = res + } + } + return cond + }(), + Actions: func() config.Actions { + act := config.Actions{} + if s.RouteAction != nil && !reflect.ValueOf(s.RouteAction).IsNil() { + a := s.RouteAction.(*RoutingAction) + if a.AcceptRoute { + act.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE + } else { + act.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE + } + } else { + act.RouteDisposition = config.ROUTE_DISPOSITION_NONE + } + for _, a := range s.ModActions { + switch v := a.(type) { + case *AsPathPrependAction: + act.BgpActions.SetAsPathPrepend = *v.ToConfig() + case *CommunityAction: + act.BgpActions.SetCommunity = *v.ToConfig() + case *ExtCommunityAction: + act.BgpActions.SetExtCommunity = *v.ToConfig() + case *LargeCommunityAction: + act.BgpActions.SetLargeCommunity = *v.ToConfig() + case *MedAction: + act.BgpActions.SetMed = v.ToConfig() + case *LocalPrefAction: + act.BgpActions.SetLocalPref = v.ToConfig() + case *NexthopAction: + act.BgpActions.SetNextHop = v.ToConfig() + } + } + return act + }(), + } +} + +func (s *Statement) MarshalJSON() ([]byte, error) { + return json.Marshal(s.ToConfig()) +} + +type opType int + +const ( + ADD opType = iota + REMOVE + REPLACE +) + +func (lhs *Statement) mod(op opType, rhs *Statement) error { + cs := make([]Condition, len(lhs.Conditions)) + copy(cs, lhs.Conditions) + ra := lhs.RouteAction + as := make([]Action, len(lhs.ModActions)) + copy(as, lhs.ModActions) + for _, x := range rhs.Conditions { + var c Condition + i := 0 + for idx, y := range lhs.Conditions { + if x.Type() == y.Type() { + c = y + i = idx + break + } + } + switch op { + case ADD: + if c != nil { + return fmt.Errorf("condition %d is already set", x.Type()) + } + if cs == nil { + cs = make([]Condition, 0, len(rhs.Conditions)) + } + cs = append(cs, x) + case REMOVE: + if c == nil { + return fmt.Errorf("condition %d is not set", x.Type()) + } + cs = append(cs[:i], cs[i+1:]...) + if len(cs) == 0 { + cs = nil + } + case REPLACE: + if c == nil { + return fmt.Errorf("condition %d is not set", x.Type()) + } + cs[i] = x + } + } + if rhs.RouteAction != nil && !reflect.ValueOf(rhs.RouteAction).IsNil() { + switch op { + case ADD: + if lhs.RouteAction != nil && !reflect.ValueOf(lhs.RouteAction).IsNil() { + return fmt.Errorf("route action is already set") + } + ra = rhs.RouteAction + case REMOVE: + if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() { + return fmt.Errorf("route action is not set") + } + ra = nil + case REPLACE: + if lhs.RouteAction == nil || reflect.ValueOf(lhs.RouteAction).IsNil() { + return fmt.Errorf("route action is not set") + } + ra = rhs.RouteAction + } + } + for _, x := range rhs.ModActions { + var a Action + i := 0 + for idx, y := range lhs.ModActions { + if x.Type() == y.Type() { + a = y + i = idx + break + } + } + switch op { + case ADD: + if a != nil { + return fmt.Errorf("action %d is already set", x.Type()) + } + if as == nil { + as = make([]Action, 0, len(rhs.ModActions)) + } + as = append(as, x) + case REMOVE: + if a == nil { + return fmt.Errorf("action %d is not set", x.Type()) + } + as = append(as[:i], as[i+1:]...) + if len(as) == 0 { + as = nil + } + case REPLACE: + if a == nil { + return fmt.Errorf("action %d is not set", x.Type()) + } + as[i] = x + } + } + lhs.Conditions = cs + lhs.RouteAction = ra + lhs.ModActions = as + return nil +} + +func (lhs *Statement) Add(rhs *Statement) error { + return lhs.mod(ADD, rhs) +} + +func (lhs *Statement) Remove(rhs *Statement) error { + return lhs.mod(REMOVE, rhs) +} + +func (lhs *Statement) Replace(rhs *Statement) error { + return lhs.mod(REPLACE, rhs) +} + +func NewStatement(c config.Statement) (*Statement, error) { + if c.Name == "" { + return nil, fmt.Errorf("empty statement name") + } + var ra Action + var as []Action + var cs []Condition + var err error + cfs := []func() (Condition, error){ + func() (Condition, error) { + return NewPrefixCondition(c.Conditions.MatchPrefixSet) + }, + func() (Condition, error) { + return NewNeighborCondition(c.Conditions.MatchNeighborSet) + }, + func() (Condition, error) { + return NewAsPathLengthCondition(c.Conditions.BgpConditions.AsPathLength) + }, + func() (Condition, error) { + return NewRpkiValidationCondition(c.Conditions.BgpConditions.RpkiValidationResult) + }, + func() (Condition, error) { + return NewRouteTypeCondition(c.Conditions.BgpConditions.RouteType) + }, + func() (Condition, error) { + return NewAsPathCondition(c.Conditions.BgpConditions.MatchAsPathSet) + }, + func() (Condition, error) { + return NewCommunityCondition(c.Conditions.BgpConditions.MatchCommunitySet) + }, + func() (Condition, error) { + return NewExtCommunityCondition(c.Conditions.BgpConditions.MatchExtCommunitySet) + }, + func() (Condition, error) { + return NewLargeCommunityCondition(c.Conditions.BgpConditions.MatchLargeCommunitySet) + }, + func() (Condition, error) { + return NewNextHopCondition(c.Conditions.BgpConditions.NextHopInList) + }, + func() (Condition, error) { + return NewAfiSafiInCondition(c.Conditions.BgpConditions.AfiSafiInList) + }, + } + cs = make([]Condition, 0, len(cfs)) + for _, f := range cfs { + c, err := f() + if err != nil { + return nil, err + } + if !reflect.ValueOf(c).IsNil() { + cs = append(cs, c) + } + } + ra, err = NewRoutingAction(c.Actions.RouteDisposition) + if err != nil { + return nil, err + } + afs := []func() (Action, error){ + func() (Action, error) { + return NewCommunityAction(c.Actions.BgpActions.SetCommunity) + }, + func() (Action, error) { + return NewExtCommunityAction(c.Actions.BgpActions.SetExtCommunity) + }, + func() (Action, error) { + return NewLargeCommunityAction(c.Actions.BgpActions.SetLargeCommunity) + }, + func() (Action, error) { + return NewMedAction(c.Actions.BgpActions.SetMed) + }, + func() (Action, error) { + return NewLocalPrefAction(c.Actions.BgpActions.SetLocalPref) + }, + func() (Action, error) { + return NewAsPathPrependAction(c.Actions.BgpActions.SetAsPathPrepend) + }, + func() (Action, error) { + return NewNexthopAction(c.Actions.BgpActions.SetNextHop) + }, + } + as = make([]Action, 0, len(afs)) + for _, f := range afs { + a, err := f() + if err != nil { + return nil, err + } + if !reflect.ValueOf(a).IsNil() { + as = append(as, a) + } + } + return &Statement{ + Name: c.Name, + Conditions: cs, + RouteAction: ra, + ModActions: as, + }, nil +} + +type Policy struct { + Name string + Statements []*Statement +} + +// Compare path with a policy's condition in stored order in the policy. +// If a condition match, then this function stops evaluation and +// subsequent conditions are skipped. +func (p *Policy) Apply(logger log.Logger, path *Path, options *PolicyOptions) (RouteType, *Path) { + for _, stmt := range p.Statements { + var result RouteType + result, path = stmt.Apply(logger, path, options) + if result != ROUTE_TYPE_NONE { + return result, path + } + } + return ROUTE_TYPE_NONE, path +} + +func (p *Policy) ToConfig() *config.PolicyDefinition { + ss := make([]config.Statement, 0, len(p.Statements)) + for _, s := range p.Statements { + ss = append(ss, *s.ToConfig()) + } + return &config.PolicyDefinition{ + Name: p.Name, + Statements: ss, + } +} + +func (p *Policy) FillUp(m map[string]*Statement) error { + stmts := make([]*Statement, 0, len(p.Statements)) + for _, x := range p.Statements { + y, ok := m[x.Name] + if !ok { + return fmt.Errorf("not found statement %s", x.Name) + } + stmts = append(stmts, y) + } + p.Statements = stmts + return nil +} + +func (lhs *Policy) Add(rhs *Policy) error { + lhs.Statements = append(lhs.Statements, rhs.Statements...) + return nil +} + +func (lhs *Policy) Remove(rhs *Policy) error { + stmts := make([]*Statement, 0, len(lhs.Statements)) + for _, x := range lhs.Statements { + found := false + for _, y := range rhs.Statements { + if x.Name == y.Name { + found = true + break + } + } + if !found { + stmts = append(stmts, x) + } + } + lhs.Statements = stmts + return nil +} + +func (lhs *Policy) Replace(rhs *Policy) error { + lhs.Statements = rhs.Statements + return nil +} + +func (p *Policy) MarshalJSON() ([]byte, error) { + return json.Marshal(p.ToConfig()) +} + +func NewPolicy(c config.PolicyDefinition) (*Policy, error) { + if c.Name == "" { + return nil, fmt.Errorf("empty policy name") + } + var st []*Statement + stmts := c.Statements + if len(stmts) != 0 { + st = make([]*Statement, 0, len(stmts)) + for idx, stmt := range stmts { + if stmt.Name == "" { + stmt.Name = fmt.Sprintf("%s_stmt%d", c.Name, idx) + } + s, err := NewStatement(stmt) + if err != nil { + return nil, err + } + st = append(st, s) + } + } + return &Policy{ + Name: c.Name, + Statements: st, + }, nil +} + +type Policies []*Policy + +func (p Policies) Len() int { + return len(p) +} + +func (p Policies) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func (p Policies) Less(i, j int) bool { + return p[i].Name < p[j].Name +} + +type Assignment struct { + importPolicies []*Policy + defaultImportPolicy RouteType + exportPolicies []*Policy + defaultExportPolicy RouteType +} + +type RoutingPolicy struct { + definedSetMap DefinedSetMap + policyMap map[string]*Policy + statementMap map[string]*Statement + assignmentMap map[string]*Assignment + mu sync.RWMutex + logger log.Logger +} + +func (r *RoutingPolicy) ApplyPolicy(id string, dir PolicyDirection, before *Path, options *PolicyOptions) *Path { + if before == nil { + return nil + } + + if before.IsWithdraw { + return before + } + result := ROUTE_TYPE_NONE + after := before + + r.mu.RLock() + defer r.mu.RUnlock() + + for _, p := range r.getPolicy(id, dir) { + result, after = p.Apply(r.logger, after, options) + if result != ROUTE_TYPE_NONE { + break + } + } + if result == ROUTE_TYPE_NONE { + result = r.getDefaultPolicy(id, dir) + } + switch result { + case ROUTE_TYPE_ACCEPT: + return after + default: + return nil + } +} + +func (r *RoutingPolicy) getPolicy(id string, dir PolicyDirection) []*Policy { + a, ok := r.assignmentMap[id] + if !ok { + return nil + } + switch dir { + case POLICY_DIRECTION_IMPORT: + return a.importPolicies + case POLICY_DIRECTION_EXPORT: + return a.exportPolicies + default: + return nil + } +} + +func (r *RoutingPolicy) getDefaultPolicy(id string, dir PolicyDirection) RouteType { + a, ok := r.assignmentMap[id] + if !ok { + return ROUTE_TYPE_NONE + } + switch dir { + case POLICY_DIRECTION_IMPORT: + return a.defaultImportPolicy + case POLICY_DIRECTION_EXPORT: + return a.defaultExportPolicy + default: + return ROUTE_TYPE_NONE + } + +} + +func (r *RoutingPolicy) setPolicy(id string, dir PolicyDirection, policies []*Policy) error { + a, ok := r.assignmentMap[id] + if !ok { + a = &Assignment{} + } + switch dir { + case POLICY_DIRECTION_IMPORT: + a.importPolicies = policies + case POLICY_DIRECTION_EXPORT: + a.exportPolicies = policies + } + r.assignmentMap[id] = a + return nil +} + +func (r *RoutingPolicy) setDefaultPolicy(id string, dir PolicyDirection, typ RouteType) error { + a, ok := r.assignmentMap[id] + if !ok { + a = &Assignment{} + } + switch dir { + case POLICY_DIRECTION_IMPORT: + a.defaultImportPolicy = typ + case POLICY_DIRECTION_EXPORT: + a.defaultExportPolicy = typ + } + r.assignmentMap[id] = a + return nil +} + +func (r *RoutingPolicy) getAssignmentFromConfig(dir PolicyDirection, a config.ApplyPolicy) ([]*Policy, RouteType, error) { + var names []string + var cdef config.DefaultPolicyType + def := ROUTE_TYPE_ACCEPT + c := a.Config + switch dir { + case POLICY_DIRECTION_IMPORT: + names = c.ImportPolicyList + cdef = c.DefaultImportPolicy + case POLICY_DIRECTION_EXPORT: + names = c.ExportPolicyList + cdef = c.DefaultExportPolicy + default: + return nil, def, fmt.Errorf("invalid policy direction") + } + if cdef == config.DEFAULT_POLICY_TYPE_REJECT_ROUTE { + def = ROUTE_TYPE_REJECT + } + ps := make([]*Policy, 0, len(names)) + seen := make(map[string]bool) + for _, name := range names { + p, ok := r.policyMap[name] + if !ok { + return nil, def, fmt.Errorf("not found policy %s", name) + } + if seen[name] { + return nil, def, fmt.Errorf("duplicated policy %s", name) + } + seen[name] = true + ps = append(ps, p) + } + return ps, def, nil +} + +func (r *RoutingPolicy) validateCondition(v Condition) (err error) { + switch v.Type() { + case CONDITION_PREFIX: + m := r.definedSetMap[DEFINED_TYPE_PREFIX] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found prefix set %s", v.Name()) + } else { + c := v.(*PrefixCondition) + c.set = i.(*PrefixSet) + } + case CONDITION_NEIGHBOR: + m := r.definedSetMap[DEFINED_TYPE_NEIGHBOR] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found neighbor set %s", v.Name()) + } else { + c := v.(*NeighborCondition) + c.set = i.(*NeighborSet) + } + case CONDITION_AS_PATH: + m := r.definedSetMap[DEFINED_TYPE_AS_PATH] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found as path set %s", v.Name()) + } else { + c := v.(*AsPathCondition) + c.set = i.(*AsPathSet) + } + case CONDITION_COMMUNITY: + m := r.definedSetMap[DEFINED_TYPE_COMMUNITY] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found community set %s", v.Name()) + } else { + c := v.(*CommunityCondition) + c.set = i.(*CommunitySet) + } + case CONDITION_EXT_COMMUNITY: + m := r.definedSetMap[DEFINED_TYPE_EXT_COMMUNITY] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found ext-community set %s", v.Name()) + } else { + c := v.(*ExtCommunityCondition) + c.set = i.(*ExtCommunitySet) + } + case CONDITION_LARGE_COMMUNITY: + m := r.definedSetMap[DEFINED_TYPE_LARGE_COMMUNITY] + if i, ok := m[v.Name()]; !ok { + return fmt.Errorf("not found large-community set %s", v.Name()) + } else { + c := v.(*LargeCommunityCondition) + c.set = i.(*LargeCommunitySet) + } + case CONDITION_NEXT_HOP: + case CONDITION_AFI_SAFI_IN: + case CONDITION_AS_PATH_LENGTH: + case CONDITION_RPKI: + } + return nil +} + +func (r *RoutingPolicy) inUse(d DefinedSet) bool { + name := d.Name() + for _, p := range r.policyMap { + for _, s := range p.Statements { + for _, c := range s.Conditions { + if c.Set() != nil && c.Set().Name() == name { + return true + } + } + } + } + return false +} + +func (r *RoutingPolicy) statementInUse(x *Statement) bool { + for _, p := range r.policyMap { + for _, y := range p.Statements { + if x.Name == y.Name { + return true + } + } + } + return false +} + +func (r *RoutingPolicy) reload(c config.RoutingPolicy) error { + dmap := make(map[DefinedType]map[string]DefinedSet) + dmap[DEFINED_TYPE_PREFIX] = make(map[string]DefinedSet) + d := c.DefinedSets + for _, x := range d.PrefixSets { + y, err := NewPrefixSet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty prefix set") + } + dmap[DEFINED_TYPE_PREFIX][y.Name()] = y + } + dmap[DEFINED_TYPE_NEIGHBOR] = make(map[string]DefinedSet) + for _, x := range d.NeighborSets { + y, err := NewNeighborSet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty neighbor set") + } + dmap[DEFINED_TYPE_NEIGHBOR][y.Name()] = y + } + // dmap[DEFINED_TYPE_TAG] = make(map[string]DefinedSet) + // for _, x := range c.DefinedSets.TagSets{ + // y, err := NewTagSet(x) + // if err != nil { + // return nil, err + // } + // dmap[DEFINED_TYPE_TAG][y.Name()] = y + // } + bd := c.DefinedSets.BgpDefinedSets + dmap[DEFINED_TYPE_AS_PATH] = make(map[string]DefinedSet) + for _, x := range bd.AsPathSets { + y, err := NewAsPathSet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty as path set") + } + dmap[DEFINED_TYPE_AS_PATH][y.Name()] = y + } + dmap[DEFINED_TYPE_COMMUNITY] = make(map[string]DefinedSet) + for _, x := range bd.CommunitySets { + y, err := NewCommunitySet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty community set") + } + dmap[DEFINED_TYPE_COMMUNITY][y.Name()] = y + } + dmap[DEFINED_TYPE_EXT_COMMUNITY] = make(map[string]DefinedSet) + for _, x := range bd.ExtCommunitySets { + y, err := NewExtCommunitySet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty ext-community set") + } + dmap[DEFINED_TYPE_EXT_COMMUNITY][y.Name()] = y + } + dmap[DEFINED_TYPE_LARGE_COMMUNITY] = make(map[string]DefinedSet) + for _, x := range bd.LargeCommunitySets { + y, err := NewLargeCommunitySet(x) + if err != nil { + return err + } + if y == nil { + return fmt.Errorf("empty large-community set") + } + dmap[DEFINED_TYPE_LARGE_COMMUNITY][y.Name()] = y + } + + pmap := make(map[string]*Policy) + smap := make(map[string]*Statement) + for _, x := range c.PolicyDefinitions { + y, err := NewPolicy(x) + if err != nil { + return err + } + if _, ok := pmap[y.Name]; ok { + return fmt.Errorf("duplicated policy name. policy name must be unique") + } + pmap[y.Name] = y + for _, s := range y.Statements { + _, ok := smap[s.Name] + if ok { + return fmt.Errorf("duplicated statement name. statement name must be unique") + } + smap[s.Name] = s + } + } + + // hacky + oldMap := r.definedSetMap + r.definedSetMap = dmap + for _, y := range pmap { + for _, s := range y.Statements { + for _, c := range s.Conditions { + if err := r.validateCondition(c); err != nil { + r.definedSetMap = oldMap + return err + } + } + } + } + + r.definedSetMap = dmap + r.policyMap = pmap + r.statementMap = smap + r.assignmentMap = make(map[string]*Assignment) + // allow all routes coming in and going out by default + r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_IMPORT, ROUTE_TYPE_ACCEPT) + r.setDefaultPolicy(GLOBAL_RIB_NAME, POLICY_DIRECTION_EXPORT, ROUTE_TYPE_ACCEPT) + return nil +} + +func (r *RoutingPolicy) GetDefinedSet(typ DefinedType, name string) (*config.DefinedSets, error) { + dl, err := func() (DefinedSetList, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + set, ok := r.definedSetMap[typ] + if !ok { + return nil, fmt.Errorf("invalid defined-set type: %d", typ) + } + + var dl DefinedSetList + for _, s := range set { + dl = append(dl, s) + } + return dl, nil + }() + if err != nil { + return nil, err + } + + sort.Sort(dl) + + sets := &config.DefinedSets{ + PrefixSets: make([]config.PrefixSet, 0), + NeighborSets: make([]config.NeighborSet, 0), + BgpDefinedSets: config.BgpDefinedSets{ + CommunitySets: make([]config.CommunitySet, 0), + ExtCommunitySets: make([]config.ExtCommunitySet, 0), + LargeCommunitySets: make([]config.LargeCommunitySet, 0), + AsPathSets: make([]config.AsPathSet, 0), + }, + } + for _, s := range dl { + if name != "" && s.Name() != name { + continue + } + switch v := s.(type) { + case *PrefixSet: + sets.PrefixSets = append(sets.PrefixSets, *v.ToConfig()) + case *NeighborSet: + sets.NeighborSets = append(sets.NeighborSets, *v.ToConfig()) + case *CommunitySet: + sets.BgpDefinedSets.CommunitySets = append(sets.BgpDefinedSets.CommunitySets, *v.ToConfig()) + case *ExtCommunitySet: + sets.BgpDefinedSets.ExtCommunitySets = append(sets.BgpDefinedSets.ExtCommunitySets, *v.ToConfig()) + case *LargeCommunitySet: + sets.BgpDefinedSets.LargeCommunitySets = append(sets.BgpDefinedSets.LargeCommunitySets, *v.ToConfig()) + case *AsPathSet: + sets.BgpDefinedSets.AsPathSets = append(sets.BgpDefinedSets.AsPathSets, *v.ToConfig()) + } + } + return sets, nil +} + +func (r *RoutingPolicy) AddDefinedSet(s DefinedSet) error { + r.mu.Lock() + defer r.mu.Unlock() + + if m, ok := r.definedSetMap[s.Type()]; !ok { + return fmt.Errorf("invalid defined-set type: %d", s.Type()) + } else { + if d, ok := m[s.Name()]; ok { + if err := d.Append(s); err != nil { + return err + } + } else { + m[s.Name()] = s + } + } + return nil +} + +func (r *RoutingPolicy) DeleteDefinedSet(a DefinedSet, all bool) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + if m, ok := r.definedSetMap[a.Type()]; !ok { + err = fmt.Errorf("invalid defined-set type: %d", a.Type()) + } else { + d, ok := m[a.Name()] + if !ok { + return fmt.Errorf("not found defined-set: %s", a.Name()) + } + if all { + if r.inUse(d) { + err = fmt.Errorf("can't delete. defined-set %s is in use", a.Name()) + } else { + delete(m, a.Name()) + } + } else { + err = d.Remove(a) + } + } + return err +} + +func (r *RoutingPolicy) GetStatement(name string) []*config.Statement { + r.mu.RLock() + defer r.mu.RUnlock() + + l := make([]*config.Statement, 0, len(r.statementMap)) + for _, st := range r.statementMap { + if name != "" && name != st.Name { + continue + } + l = append(l, st.ToConfig()) + } + return l +} + +func (r *RoutingPolicy) AddStatement(st *Statement) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + for _, c := range st.Conditions { + if err = r.validateCondition(c); err != nil { + return + } + } + m := r.statementMap + name := st.Name + if d, ok := m[name]; ok { + err = d.Add(st) + } else { + m[name] = st + } + + return err +} + +func (r *RoutingPolicy) DeleteStatement(st *Statement, all bool) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + m := r.statementMap + name := st.Name + if d, ok := m[name]; ok { + if all { + if r.statementInUse(d) { + err = fmt.Errorf("can't delete. statement %s is in use", name) + } else { + delete(m, name) + } + } else { + err = d.Remove(st) + } + } else { + err = fmt.Errorf("not found statement: %s", name) + } + return err +} + +func (r *RoutingPolicy) GetPolicy(name string) []*config.PolicyDefinition { + ps := func() Policies { + r.mu.RLock() + defer r.mu.RUnlock() + + var ps Policies + for _, p := range r.policyMap { + if name != "" && name != p.Name { + continue + } + ps = append(ps, p) + } + return ps + }() + + sort.Sort(ps) + + l := make([]*config.PolicyDefinition, 0, len(ps)) + for _, p := range ps { + l = append(l, p.ToConfig()) + } + return l +} + +func (r *RoutingPolicy) AddPolicy(x *Policy, refer bool) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + for _, st := range x.Statements { + for _, c := range st.Conditions { + if err = r.validateCondition(c); err != nil { + return + } + } + } + + pMap := r.policyMap + sMap := r.statementMap + name := x.Name + y, ok := pMap[name] + if refer { + err = x.FillUp(sMap) + } else { + for _, st := range x.Statements { + if _, ok := sMap[st.Name]; ok { + err = fmt.Errorf("statement %s already defined", st.Name) + return + } + sMap[st.Name] = st + } + } + if ok { + err = y.Add(x) + } else { + pMap[name] = x + } + + return err +} + +func (r *RoutingPolicy) DeletePolicy(x *Policy, all, preserve bool, activeId []string) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + pMap := r.policyMap + sMap := r.statementMap + name := x.Name + y, ok := pMap[name] + if !ok { + err = fmt.Errorf("not found policy: %s", name) + return + } + inUse := func(ids []string) bool { + for _, id := range ids { + for _, dir := range []PolicyDirection{POLICY_DIRECTION_EXPORT, POLICY_DIRECTION_EXPORT} { + for _, y := range r.getPolicy(id, dir) { + if x.Name == y.Name { + return true + } + } + } + } + return false + } + + if all { + if inUse(activeId) { + err = fmt.Errorf("can't delete. policy %s is in use", name) + return + } + r.logger.Debug("delete policy", + log.Fields{ + "Topic": "Policy", + "Key": name}) + delete(pMap, name) + } else { + err = y.Remove(x) + } + if err == nil && !preserve { + for _, st := range y.Statements { + if !r.statementInUse(st) { + r.logger.Debug("delete unused statement", + log.Fields{ + "Topic": "Policy", + "Key": st.Name}) + delete(sMap, st.Name) + } + } + } + return err +} + +func (r *RoutingPolicy) GetPolicyAssignment(id string, dir PolicyDirection) (RouteType, []*Policy, error) { + r.mu.RLock() + defer r.mu.RUnlock() + + rt := r.getDefaultPolicy(id, dir) + l := make([]*Policy, 0) + l = append(l, r.getPolicy(id, dir)...) + return rt, l, nil +} + +func (r *RoutingPolicy) AddPolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + ps := make([]*Policy, 0, len(policies)) + seen := make(map[string]bool) + for _, x := range policies { + p, ok := r.policyMap[x.Name] + if !ok { + err = fmt.Errorf("not found policy %s", x.Name) + return + } + if seen[x.Name] { + err = fmt.Errorf("duplicated policy %s", x.Name) + return + } + seen[x.Name] = true + ps = append(ps, p) + } + cur := r.getPolicy(id, dir) + if cur == nil { + err = r.setPolicy(id, dir, ps) + } else { + seen = make(map[string]bool) + ps = append(cur, ps...) + for _, x := range ps { + if seen[x.Name] { + err = fmt.Errorf("duplicated policy %s", x.Name) + return + } + seen[x.Name] = true + } + err = r.setPolicy(id, dir, ps) + } + if err == nil && def != ROUTE_TYPE_NONE { + err = r.setDefaultPolicy(id, dir, def) + } + return err +} + +func (r *RoutingPolicy) DeletePolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, all bool) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + ps := make([]*Policy, 0, len(policies)) + seen := make(map[string]bool) + for _, x := range policies { + p, ok := r.policyMap[x.Name] + if !ok { + err = fmt.Errorf("not found policy %s", x.Name) + return + } + if seen[x.Name] { + err = fmt.Errorf("duplicated policy %s", x.Name) + return + } + seen[x.Name] = true + ps = append(ps, p) + } + cur := r.getPolicy(id, dir) + + if all { + err = r.setPolicy(id, dir, nil) + if err != nil { + return + } + err = r.setDefaultPolicy(id, dir, ROUTE_TYPE_NONE) + } else { + l := len(cur) - len(ps) + if l < 0 { + // try to remove more than the assigned policies... + l = len(cur) + } + n := make([]*Policy, 0, l) + for _, y := range cur { + found := false + for _, x := range ps { + if x.Name == y.Name { + found = true + break + } + } + if !found { + n = append(n, y) + } + } + err = r.setPolicy(id, dir, n) + } + return err +} + +func (r *RoutingPolicy) SetPolicyAssignment(id string, dir PolicyDirection, policies []*config.PolicyDefinition, def RouteType) (err error) { + r.mu.Lock() + defer r.mu.Unlock() + + ps := make([]*Policy, 0, len(policies)) + seen := make(map[string]bool) + for _, x := range policies { + p, ok := r.policyMap[x.Name] + if !ok { + err = fmt.Errorf("not found policy %s", x.Name) + return + } + if seen[x.Name] { + err = fmt.Errorf("duplicated policy %s", x.Name) + return + } + seen[x.Name] = true + ps = append(ps, p) + } + r.getPolicy(id, dir) + err = r.setPolicy(id, dir, ps) + if err == nil && def != ROUTE_TYPE_NONE { + err = r.setDefaultPolicy(id, dir, def) + } + return err +} + +func (r *RoutingPolicy) Initialize() error { + r.mu.Lock() + defer r.mu.Unlock() + + if err := r.reload(config.RoutingPolicy{}); err != nil { + r.logger.Error("failed to create routing policy", + log.Fields{ + "Topic": "Policy", + "Error": err}) + return err + } + return nil +} + +func (r *RoutingPolicy) setPeerPolicy(id string, c config.ApplyPolicy) { + for _, dir := range []PolicyDirection{POLICY_DIRECTION_IMPORT, POLICY_DIRECTION_EXPORT} { + ps, def, err := r.getAssignmentFromConfig(dir, c) + if err != nil { + r.logger.Error("failed to get policy info", + log.Fields{ + "Topic": "Policy", + "Dir": dir, + "Error": err}) + continue + } + r.setDefaultPolicy(id, dir, def) + r.setPolicy(id, dir, ps) + } +} + +func (r *RoutingPolicy) SetPeerPolicy(peerId string, c config.ApplyPolicy) error { + r.mu.Lock() + defer r.mu.Unlock() + + r.setPeerPolicy(peerId, c) + return nil +} + +func (r *RoutingPolicy) Reset(rp *config.RoutingPolicy, ap map[string]config.ApplyPolicy) error { + if rp == nil { + return fmt.Errorf("routing Policy is nil in call to Reset") + } + + r.mu.Lock() + defer r.mu.Unlock() + + if err := r.reload(*rp); err != nil { + r.logger.Error("failed to create routing policy", + log.Fields{ + "Topic": "Policy", + "Error": err}) + return err + } + + for id, c := range ap { + r.setPeerPolicy(id, c) + } + return nil +} + +func NewRoutingPolicy(logger log.Logger) *RoutingPolicy { + return &RoutingPolicy{ + definedSetMap: make(map[DefinedType]map[string]DefinedSet), + policyMap: make(map[string]*Policy), + statementMap: make(map[string]*Statement), + assignmentMap: make(map[string]*Assignment), + logger: logger, + } +} + +func CanImportToVrf(v *Vrf, path *Path) bool { + f := func(arg []bgp.ExtendedCommunityInterface) []string { + ret := make([]string, 0, len(arg)) + for _, a := range arg { + ret = append(ret, fmt.Sprintf("RT:%s", a.String())) + } + return ret + } + set, _ := NewExtCommunitySet(config.ExtCommunitySet{ + ExtCommunitySetName: v.Name, + ExtCommunityList: f(v.ImportRt), + }) + matchSet := config.MatchExtCommunitySet{ + ExtCommunitySet: v.Name, + MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY, + } + c, _ := NewExtCommunityCondition(matchSet) + c.set = set + return c.Evaluate(path, nil) +} + +type PolicyAssignment struct { + Name string + Type PolicyDirection + Policies []*Policy + Default RouteType +} + +var _regexpMedActionType = regexp.MustCompile(`([+-]?)(\d+)`) + +func toStatementApi(s *config.Statement) *api.Statement { + cs := &api.Conditions{} + o, _ := NewMatchOption(s.Conditions.MatchPrefixSet.MatchSetOptions) + if s.Conditions.MatchPrefixSet.PrefixSet != "" { + cs.PrefixSet = &api.MatchSet{ + Type: api.MatchSet_Type(o), + Name: s.Conditions.MatchPrefixSet.PrefixSet, + } + } + if s.Conditions.MatchNeighborSet.NeighborSet != "" { + o, _ := NewMatchOption(s.Conditions.MatchNeighborSet.MatchSetOptions) + cs.NeighborSet = &api.MatchSet{ + Type: api.MatchSet_Type(o), + Name: s.Conditions.MatchNeighborSet.NeighborSet, + } + } + if s.Conditions.BgpConditions.AsPathLength.Operator != "" { + cs.AsPathLength = &api.AsPathLength{ + Length: s.Conditions.BgpConditions.AsPathLength.Value, + Type: api.AsPathLength_Type(s.Conditions.BgpConditions.AsPathLength.Operator.ToInt()), + } + } + if s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet != "" { + cs.AsPathSet = &api.MatchSet{ + Type: api.MatchSet_Type(s.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions.ToInt()), + Name: s.Conditions.BgpConditions.MatchAsPathSet.AsPathSet, + } + } + if s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet != "" { + cs.CommunitySet = &api.MatchSet{ + Type: api.MatchSet_Type(s.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions.ToInt()), + Name: s.Conditions.BgpConditions.MatchCommunitySet.CommunitySet, + } + } + if s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet != "" { + cs.ExtCommunitySet = &api.MatchSet{ + Type: api.MatchSet_Type(s.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions.ToInt()), + Name: s.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet, + } + } + if s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet != "" { + cs.LargeCommunitySet = &api.MatchSet{ + Type: api.MatchSet_Type(s.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions.ToInt()), + Name: s.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet, + } + } + if s.Conditions.BgpConditions.RouteType != "" { + cs.RouteType = api.Conditions_RouteType(s.Conditions.BgpConditions.RouteType.ToInt()) + } + if len(s.Conditions.BgpConditions.NextHopInList) > 0 { + cs.NextHopInList = s.Conditions.BgpConditions.NextHopInList + } + if s.Conditions.BgpConditions.AfiSafiInList != nil { + afiSafiIn := make([]*api.Family, 0) + for _, afiSafiType := range s.Conditions.BgpConditions.AfiSafiInList { + if mapped, ok := bgp.AddressFamilyValueMap[string(afiSafiType)]; ok { + afi, safi := bgp.RouteFamilyToAfiSafi(mapped) + afiSafiIn = append(afiSafiIn, &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}) + } + } + cs.AfiSafiIn = afiSafiIn + } + cs.RpkiResult = int32(s.Conditions.BgpConditions.RpkiValidationResult.ToInt()) + as := &api.Actions{ + RouteAction: func() api.RouteAction { + switch s.Actions.RouteDisposition { + case config.ROUTE_DISPOSITION_ACCEPT_ROUTE: + return api.RouteAction_ACCEPT + case config.ROUTE_DISPOSITION_REJECT_ROUTE: + return api.RouteAction_REJECT + } + return api.RouteAction_NONE + }(), + Community: func() *api.CommunityAction { + if len(s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList) == 0 { + return nil + } + return &api.CommunityAction{ + Type: api.CommunityAction_Type(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetCommunity.Options)]), + Communities: s.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList} + }(), + Med: func() *api.MedAction { + medStr := strings.TrimSpace(string(s.Actions.BgpActions.SetMed)) + if len(medStr) == 0 { + return nil + } + matches := _regexpMedActionType.FindStringSubmatch(medStr) + if len(matches) == 0 { + return nil + } + action := api.MedAction_REPLACE + switch matches[1] { + case "+", "-": + action = api.MedAction_MOD + } + value, err := strconv.ParseInt(matches[1]+matches[2], 10, 64) + if err != nil { + return nil + } + return &api.MedAction{ + Value: value, + Type: action, + } + }(), + AsPrepend: func() *api.AsPrependAction { + if len(s.Actions.BgpActions.SetAsPathPrepend.As) == 0 { + return nil + } + var asn uint64 + useleft := false + if s.Actions.BgpActions.SetAsPathPrepend.As != "last-as" { + asn, _ = strconv.ParseUint(s.Actions.BgpActions.SetAsPathPrepend.As, 10, 32) + } else { + useleft = true + } + return &api.AsPrependAction{ + Asn: uint32(asn), + Repeat: uint32(s.Actions.BgpActions.SetAsPathPrepend.RepeatN), + UseLeftMost: useleft, + } + }(), + ExtCommunity: func() *api.CommunityAction { + if len(s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList) == 0 { + return nil + } + return &api.CommunityAction{ + Type: api.CommunityAction_Type(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetExtCommunity.Options)]), + Communities: s.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList, + } + }(), + LargeCommunity: func() *api.CommunityAction { + if len(s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList) == 0 { + return nil + } + return &api.CommunityAction{ + Type: api.CommunityAction_Type(config.BgpSetCommunityOptionTypeToIntMap[config.BgpSetCommunityOptionType(s.Actions.BgpActions.SetLargeCommunity.Options)]), + Communities: s.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList, + } + }(), + Nexthop: func() *api.NexthopAction { + if len(string(s.Actions.BgpActions.SetNextHop)) == 0 { + return nil + } + + if string(s.Actions.BgpActions.SetNextHop) == "self" { + return &api.NexthopAction{ + Self: true, + } + } + if string(s.Actions.BgpActions.SetNextHop) == "unchanged" { + return &api.NexthopAction{ + Unchanged: true, + } + } + return &api.NexthopAction{ + Address: string(s.Actions.BgpActions.SetNextHop), + } + }(), + LocalPref: func() *api.LocalPrefAction { + if s.Actions.BgpActions.SetLocalPref == 0 { + return nil + } + return &api.LocalPrefAction{Value: s.Actions.BgpActions.SetLocalPref} + }(), + } + return &api.Statement{ + Name: s.Name, + Conditions: cs, + Actions: as, + } +} + +func NewAPIPolicyFromTableStruct(p *Policy) *api.Policy { + return ToPolicyApi(p.ToConfig()) +} + +func ToPolicyApi(p *config.PolicyDefinition) *api.Policy { + return &api.Policy{ + Name: p.Name, + Statements: func() []*api.Statement { + l := make([]*api.Statement, 0) + for _, s := range p.Statements { + l = append(l, toStatementApi(&s)) + } + return l + }(), + } +} + +func NewAPIPolicyAssignmentFromTableStruct(t *PolicyAssignment) *api.PolicyAssignment { + return &api.PolicyAssignment{ + Direction: func() api.PolicyDirection { + switch t.Type { + case POLICY_DIRECTION_IMPORT: + return api.PolicyDirection_IMPORT + case POLICY_DIRECTION_EXPORT: + return api.PolicyDirection_EXPORT + } + return api.PolicyDirection_UNKNOWN + }(), + DefaultAction: func() api.RouteAction { + switch t.Default { + case ROUTE_TYPE_ACCEPT: + return api.RouteAction_ACCEPT + case ROUTE_TYPE_REJECT: + return api.RouteAction_REJECT + } + return api.RouteAction_NONE + }(), + Name: t.Name, + Policies: func() []*api.Policy { + l := make([]*api.Policy, 0) + for _, p := range t.Policies { + l = append(l, NewAPIPolicyFromTableStruct(p)) + } + return l + }(), + } +} + +func NewAPIRoutingPolicyFromConfigStruct(c *config.RoutingPolicy) (*api.RoutingPolicy, error) { + definedSets, err := config.NewAPIDefinedSetsFromConfigStruct(&c.DefinedSets) + if err != nil { + return nil, err + } + policies := make([]*api.Policy, 0, len(c.PolicyDefinitions)) + for _, policy := range c.PolicyDefinitions { + policies = append(policies, ToPolicyApi(&policy)) + } + + return &api.RoutingPolicy{ + DefinedSets: definedSets, + Policies: policies, + }, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/roa.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/roa.go new file mode 100644 index 000000000..d7d25944e --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/roa.go @@ -0,0 +1,299 @@ +// Copyright (C) 2016-2019 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "net" + "sort" + + "github.com/k-sone/critbitgo" + "github.com/osrg/gobgp/v3/internal/pkg/config" + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +type ROA struct { + Family int + Network *net.IPNet + MaxLen uint8 + AS uint32 + Src string +} + +func NewROA(family int, prefixByte []byte, prefixLen uint8, maxLen uint8, as uint32, src string) *ROA { + p := make([]byte, len(prefixByte)) + bits := net.IPv4len * 8 + if family == bgp.AFI_IP6 { + bits = net.IPv6len * 8 + } + copy(p, prefixByte) + return &ROA{ + Family: family, + Network: &net.IPNet{ + IP: p, + Mask: net.CIDRMask(int(prefixLen), bits), + }, + MaxLen: maxLen, + AS: as, + Src: src, + } +} + +func (r *ROA) Equal(roa *ROA) bool { + if r.MaxLen == roa.MaxLen && r.Src == roa.Src && r.AS == roa.AS { + return true + } + return false +} + +type roaBucket struct { + network *net.IPNet + entries []*ROA +} + +func (r *roaBucket) GetEntries() []*ROA { + return r.entries +} + +type ROATable struct { + trees map[bgp.RouteFamily]*critbitgo.Net + logger log.Logger +} + +func NewROATable(logger log.Logger) *ROATable { + m := make(map[bgp.RouteFamily]*critbitgo.Net) + m[bgp.RF_IPv4_UC] = critbitgo.NewNet() + m[bgp.RF_IPv6_UC] = critbitgo.NewNet() + return &ROATable{ + trees: m, + logger: logger, + } +} + +func (rt *ROATable) roa2tree(roa *ROA) *critbitgo.Net { + tree := rt.trees[bgp.RF_IPv4_UC] + if roa.Family == bgp.AFI_IP6 { + tree = rt.trees[bgp.RF_IPv6_UC] + } + return tree +} + +func (rt *ROATable) getBucket(roa *ROA) *roaBucket { + tree := rt.roa2tree(roa) + b, ok, _ := tree.Get(roa.Network) + if !ok { + b := &roaBucket{ + network: roa.Network, + entries: make([]*ROA, 0), + } + tree.Add(roa.Network, b) + return b + } + return b.(*roaBucket) +} + +func (rt *ROATable) Add(roa *ROA) { + b := rt.getBucket(roa) + for _, r := range b.entries { + if r.Equal(roa) { + // we already have the same one + return + } + } + b.entries = append(b.entries, roa) + sort.Slice(b.entries, func(i, j int) bool { + r1 := b.entries[i] + r2 := b.entries[j] + + if r1.MaxLen < r2.MaxLen { + return true + } else if r1.MaxLen > r2.MaxLen { + return false + } + + if r1.AS < r2.AS { + return true + } + return false + }) +} + +func (rt *ROATable) Delete(roa *ROA) { + tree := rt.roa2tree(roa) + if b, ok, _ := tree.Get(roa.Network); ok { + bucket := b.(*roaBucket) + for i, r := range bucket.entries { + if r.Equal(roa) { + bucket.entries = append(bucket.entries[:i], bucket.entries[i+1:]...) + return + } + } + } + rt.logger.Info("Can't withdraw a ROA", + log.Fields{ + "Topic": "rpki", + "Network": roa.Network.String(), + "AS": roa.AS, + "Max Length": roa.MaxLen}) +} + +func (rt *ROATable) DeleteAll(network string) { + for _, tree := range rt.trees { + deleteNetworks := make([]*net.IPNet, 0, tree.Size()) + tree.Walk(nil, func(n *net.IPNet, v interface{}) bool { + b, _ := v.(*roaBucket) + newEntries := make([]*ROA, 0, len(b.entries)) + for _, r := range b.entries { + if r.Src != network { + newEntries = append(newEntries, r) + } + } + if len(newEntries) > 0 { + b.entries = newEntries + } else { + deleteNetworks = append(deleteNetworks, n) + } + return true + }) + for _, key := range deleteNetworks { + tree.Delete(key) + } + } +} + +func (rt *ROATable) Validate(path *Path) *Validation { + if path.IsWithdraw || path.IsEOR() { + // RPKI isn't enabled or invalid path + return nil + } + tree, ok := rt.trees[path.GetRouteFamily()] + if !ok { + return nil + } + + ownAs := path.OriginInfo().source.LocalAS + asPath := path.GetAsPath() + var as uint32 + + validation := &Validation{ + Status: config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND, + Reason: RPKI_VALIDATION_REASON_TYPE_NONE, + Matched: make([]*ROA, 0), + UnmatchedLength: make([]*ROA, 0), + UnmatchedAs: make([]*ROA, 0), + } + + if asPath == nil || len(asPath.Value) == 0 { + as = ownAs + } else { + param := asPath.Value[len(asPath.Value)-1] + switch param.GetType() { + case bgp.BGP_ASPATH_ATTR_TYPE_SEQ: + asList := param.GetAS() + if len(asList) == 0 { + as = ownAs + } else { + as = asList[len(asList)-1] + } + case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + as = ownAs + default: + return validation + } + } + + r := nlriToIPNet(path.GetNlri()) + prefixLen, _ := r.Mask.Size() + var bucket *roaBucket + tree.WalkMatch(r, func(r *net.IPNet, v interface{}) bool { + bucket, _ = v.(*roaBucket) + for _, r := range bucket.entries { + if prefixLen <= int(r.MaxLen) { + if r.AS != 0 && r.AS == as { + validation.Matched = append(validation.Matched, r) + } else { + validation.UnmatchedAs = append(validation.UnmatchedAs, r) + } + } else { + validation.UnmatchedLength = append(validation.UnmatchedLength, r) + } + } + return true + }) + + if len(validation.Matched) != 0 { + validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_VALID + validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE + } else if len(validation.UnmatchedAs) != 0 { + validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID + validation.Reason = RPKI_VALIDATION_REASON_TYPE_AS + } else if len(validation.UnmatchedLength) != 0 { + validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_INVALID + validation.Reason = RPKI_VALIDATION_REASON_TYPE_LENGTH + } else { + validation.Status = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND + validation.Reason = RPKI_VALIDATION_REASON_TYPE_NONE + } + + return validation +} + +func (rt *ROATable) Info(family bgp.RouteFamily) (map[string]uint32, map[string]uint32) { + records := make(map[string]uint32) + prefixes := make(map[string]uint32) + + if tree, ok := rt.trees[family]; ok { + tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool { + b, _ := v.(*roaBucket) + tmpRecords := make(map[string]uint32) + for _, roa := range b.entries { + tmpRecords[roa.Src]++ + } + + for src, r := range tmpRecords { + if r > 0 { + records[src] += r + prefixes[src]++ + } + } + return true + }) + } + return records, prefixes +} + +func (rt *ROATable) List(family bgp.RouteFamily) ([]*ROA, error) { + var rfList []bgp.RouteFamily + switch family { + case bgp.RF_IPv4_UC: + rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC} + case bgp.RF_IPv6_UC: + rfList = []bgp.RouteFamily{bgp.RF_IPv6_UC} + default: + rfList = []bgp.RouteFamily{bgp.RF_IPv4_UC, bgp.RF_IPv6_UC} + } + l := make([]*ROA, 0) + for _, rf := range rfList { + if tree, ok := rt.trees[rf]; ok { + tree.Walk(nil, func(_ *net.IPNet, v interface{}) bool { + b, _ := v.(*roaBucket) + l = append(l, b.entries...) + return true + }) + } + } + return l, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table.go new file mode 100644 index 000000000..072e895f2 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table.go @@ -0,0 +1,507 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "fmt" + "math/bits" + "net" + "strings" + "unsafe" + + "github.com/k-sone/critbitgo" + + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +type LookupOption uint8 + +const ( + LOOKUP_EXACT LookupOption = iota + LOOKUP_LONGER + LOOKUP_SHORTER +) + +type LookupPrefix struct { + Prefix string + LookupOption +} + +type TableSelectOption struct { + ID string + AS uint32 + LookupPrefixes []*LookupPrefix + VRF *Vrf + adj bool + Best bool + MultiPath bool +} + +type Table struct { + routeFamily bgp.RouteFamily + destinations map[string]*Destination + logger log.Logger +} + +func NewTable(logger log.Logger, rf bgp.RouteFamily, dsts ...*Destination) *Table { + t := &Table{ + routeFamily: rf, + destinations: make(map[string]*Destination), + logger: logger, + } + for _, dst := range dsts { + t.setDestination(dst) + } + return t +} + +func (t *Table) GetRoutefamily() bgp.RouteFamily { + return t.routeFamily +} + +func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path { + pathList := make([]*Path, 0) + for _, dest := range t.destinations { + for _, p := range dest.knownPathList { + var rd bgp.RouteDistinguisherInterface + nlri := p.GetNlri() + switch v := nlri.(type) { + case *bgp.LabeledVPNIPAddrPrefix: + rd = v.RD + case *bgp.LabeledVPNIPv6AddrPrefix: + rd = v.RD + case *bgp.EVPNNLRI: + rd = v.RD() + case *bgp.MUPNLRI: + rd = v.RD() + default: + return pathList + } + if p.IsLocal() && vrf.Rd.String() == rd.String() { + pathList = append(pathList, p.Clone(true)) + break + } + } + } + return pathList +} + +func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path { + pathList := make([]*Path, 0) + if t.routeFamily != bgp.RF_RTC_UC { + return pathList + } + for _, target := range vrf.ImportRt { + lhs := target.String() + for _, dest := range t.destinations { + nlri := dest.GetNlri().(*bgp.RouteTargetMembershipNLRI) + rhs := nlri.RouteTarget.String() + if lhs == rhs && isLastTargetUser(vrfs, target) { + for _, p := range dest.knownPathList { + if p.IsLocal() { + pathList = append(pathList, p.Clone(true)) + break + } + } + } + } + } + return pathList +} + +func (t *Table) deleteDest(dest *Destination) { + count := 0 + for _, v := range dest.localIdMap.bitmap { + count += bits.OnesCount64(v) + } + if len(dest.localIdMap.bitmap) != 0 && count != 1 { + return + } + destinations := t.GetDestinations() + delete(destinations, t.tableKey(dest.GetNlri())) + if len(destinations) == 0 { + t.destinations = make(map[string]*Destination) + } +} + +func (t *Table) validatePath(path *Path) { + if path == nil { + t.logger.Error("path is nil", + log.Fields{ + "Topic": "Table", + "Key": t.routeFamily}) + } + if path.GetRouteFamily() != t.routeFamily { + t.logger.Error("Invalid path. RouteFamily mismatch", + log.Fields{ + "Topic": "Table", + "Key": t.routeFamily, + "Prefix": path.GetNlri().String(), + "ReceivedRf": path.GetRouteFamily().String()}) + } + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil { + pathParam := attr.(*bgp.PathAttributeAsPath).Value + for _, as := range pathParam { + _, y := as.(*bgp.As4PathParam) + if !y { + t.logger.Fatal("AsPathParam must be converted to As4PathParam", + log.Fields{ + "Topic": "Table", + "Key": t.routeFamily, + "As": as}) + } + } + } + if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH); attr != nil { + t.logger.Fatal("AS4_PATH must be converted to AS_PATH", + log.Fields{ + "Topic": "Table", + "Key": t.routeFamily}) + } + if path.GetNlri() == nil { + t.logger.Fatal("path's nlri is nil", + log.Fields{ + "Topic": "Table", + "Key": t.routeFamily}) + } +} + +func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface, size int) *Destination { + dest := t.GetDestination(nlri) + // If destination for given prefix does not exist we create it. + if dest == nil { + t.logger.Debug("create Destination", + log.Fields{ + "Topic": "Table", + "Nlri": nlri}) + dest = NewDestination(nlri, size) + t.setDestination(dest) + } + return dest +} + +func (t *Table) GetDestinations() map[string]*Destination { + return t.destinations +} +func (t *Table) setDestinations(destinations map[string]*Destination) { + t.destinations = destinations +} +func (t *Table) GetDestination(nlri bgp.AddrPrefixInterface) *Destination { + dest, ok := t.destinations[t.tableKey(nlri)] + if ok { + return dest + } else { + return nil + } +} + +func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error) { + results := make([]*Destination, 0, len(t.GetDestinations())) + switch t.routeFamily { + case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS: + _, prefix, err := net.ParseCIDR(key) + if err != nil { + return nil, fmt.Errorf("error parsing cidr %s: %v", key, err) + } + ones, bits := prefix.Mask.Size() + + r := critbitgo.NewNet() + for _, dst := range t.GetDestinations() { + r.Add(nlriToIPNet(dst.nlri), dst) + } + p := &net.IPNet{ + IP: prefix.IP, + Mask: net.CIDRMask((ones>>3)<<3, bits), + } + mask := 0 + div := 0 + if ones%8 != 0 { + mask = 8 - ones&0x7 + div = ones >> 3 + } + r.WalkPrefix(p, func(n *net.IPNet, v interface{}) bool { + if mask != 0 && n.IP[div]>>mask != p.IP[div]>>mask { + return true + } + l, _ := n.Mask.Size() + + if ones > l { + return true + } + results = append(results, v.(*Destination)) + return true + }) + default: + for _, dst := range t.GetDestinations() { + results = append(results, dst) + } + } + return results, nil +} + +func (t *Table) GetEvpnDestinationsWithRouteType(typ string) ([]*Destination, error) { + var routeType uint8 + switch strings.ToLower(typ) { + case "a-d": + routeType = bgp.EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY + case "macadv": + routeType = bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT + case "multicast": + routeType = bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG + case "esi": + routeType = bgp.EVPN_ETHERNET_SEGMENT_ROUTE + case "prefix": + routeType = bgp.EVPN_IP_PREFIX + default: + return nil, fmt.Errorf("unsupported evpn route type: %s", typ) + } + destinations := t.GetDestinations() + results := make([]*Destination, 0, len(destinations)) + switch t.routeFamily { + case bgp.RF_EVPN: + for _, dst := range destinations { + if nlri, ok := dst.nlri.(*bgp.EVPNNLRI); !ok { + return nil, fmt.Errorf("invalid evpn nlri type detected: %T", dst.nlri) + } else if nlri.RouteType == routeType { + results = append(results, dst) + } + } + default: + for _, dst := range destinations { + results = append(results, dst) + } + } + return results, nil +} + +func (t *Table) setDestination(dst *Destination) { + t.destinations[t.tableKey(dst.nlri)] = dst +} + +func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string { + switch T := nlri.(type) { + case *bgp.IPAddrPrefix: + b := make([]byte, 5) + copy(b, T.Prefix.To4()) + b[4] = T.Length + return *(*string)(unsafe.Pointer(&b)) + case *bgp.IPv6AddrPrefix: + b := make([]byte, 17) + copy(b, T.Prefix.To16()) + b[16] = T.Length + return *(*string)(unsafe.Pointer(&b)) + } + return nlri.String() +} + +func (t *Table) Bests(id string, as uint32) []*Path { + paths := make([]*Path, 0, len(t.destinations)) + for _, dst := range t.destinations { + path := dst.GetBestPath(id, as) + if path != nil { + paths = append(paths, path) + } + } + return paths +} + +func (t *Table) MultiBests(id string) [][]*Path { + paths := make([][]*Path, 0, len(t.destinations)) + for _, dst := range t.destinations { + path := dst.GetMultiBestPath(id) + if path != nil { + paths = append(paths, path) + } + } + return paths +} + +func (t *Table) GetKnownPathList(id string, as uint32) []*Path { + paths := make([]*Path, 0, len(t.destinations)) + for _, dst := range t.destinations { + paths = append(paths, dst.GetKnownPathList(id, as)...) + } + return paths +} + +func (t *Table) Select(option ...TableSelectOption) (*Table, error) { + id := GLOBAL_RIB_NAME + var vrf *Vrf + adj := false + prefixes := make([]*LookupPrefix, 0, len(option)) + best := false + mp := false + as := uint32(0) + for _, o := range option { + if o.ID != "" { + id = o.ID + } + if o.VRF != nil { + vrf = o.VRF + } + adj = o.adj + prefixes = append(prefixes, o.LookupPrefixes...) + best = o.Best + mp = o.MultiPath + as = o.AS + } + dOption := DestinationSelectOption{ID: id, AS: as, VRF: vrf, adj: adj, Best: best, MultiPath: mp} + r := &Table{ + routeFamily: t.routeFamily, + destinations: make(map[string]*Destination), + } + + if len(prefixes) != 0 { + switch t.routeFamily { + case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: + f := func(prefixStr string) bool { + var nlri bgp.AddrPrefixInterface + if t.routeFamily == bgp.RF_IPv4_UC { + nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, prefixStr) + } else { + nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, prefixStr) + } + if dst := t.GetDestination(nlri); dst != nil { + if d := dst.Select(dOption); d != nil { + r.setDestination(d) + return true + } + } + return false + } + + for _, p := range prefixes { + key := p.Prefix + switch p.LookupOption { + case LOOKUP_LONGER: + ds, err := t.GetLongerPrefixDestinations(key) + if err != nil { + return nil, err + } + for _, dst := range ds { + if d := dst.Select(dOption); d != nil { + r.setDestination(d) + } + } + case LOOKUP_SHORTER: + addr, prefix, err := net.ParseCIDR(key) + if err != nil { + return nil, err + } + ones, _ := prefix.Mask.Size() + for i := ones; i >= 0; i-- { + _, prefix, _ := net.ParseCIDR(fmt.Sprintf("%s/%d", addr.String(), i)) + f(prefix.String()) + } + default: + if host := net.ParseIP(key); host != nil { + masklen := 32 + if t.routeFamily == bgp.RF_IPv6_UC { + masklen = 128 + } + for i := masklen; i >= 0; i-- { + _, prefix, err := net.ParseCIDR(fmt.Sprintf("%s/%d", key, i)) + if err != nil { + return nil, err + } + if f(prefix.String()) { + break + } + } + } else { + f(key) + } + } + } + case bgp.RF_EVPN: + for _, p := range prefixes { + // Uses LookupPrefix.Prefix as EVPN Route Type string + ds, err := t.GetEvpnDestinationsWithRouteType(p.Prefix) + if err != nil { + return nil, err + } + for _, dst := range ds { + if d := dst.Select(dOption); d != nil { + r.setDestination(d) + } + } + } + default: + return nil, fmt.Errorf("route filtering is not supported for this family") + } + } else { + for _, dst := range t.GetDestinations() { + if d := dst.Select(dOption); d != nil { + r.setDestination(d) + } + } + } + return r, nil +} + +type TableInfo struct { + NumDestination int + NumPath int + NumAccepted int +} + +type TableInfoOptions struct { + ID string + AS uint32 + VRF *Vrf +} + +func (t *Table) Info(option ...TableInfoOptions) *TableInfo { + var numD, numP int + + id := GLOBAL_RIB_NAME + var vrf *Vrf + as := uint32(0) + + for _, o := range option { + if o.ID != "" { + id = o.ID + } + if o.VRF != nil { + vrf = o.VRF + } + as = o.AS + } + + for _, d := range t.destinations { + paths := d.GetKnownPathList(id, as) + n := len(paths) + + if vrf != nil { + ps := make([]*Path, 0, len(paths)) + for _, p := range paths { + if CanImportToVrf(vrf, p) { + ps = append(ps, p.ToLocal()) + } + } + n = len(ps) + } + if n != 0 { + numD++ + numP += n + } + } + return &TableInfo{ + NumDestination: numD, + NumPath: numP, + } +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table_manager.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table_manager.go new file mode 100644 index 000000000..6ac58c8c8 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table_manager.go @@ -0,0 +1,365 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "bytes" + "fmt" + "net" + "time" + + farm "github.com/dgryski/go-farm" + + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +const ( + GLOBAL_RIB_NAME = "global" +) + +func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time) []*Path { + update := m.Body.(*bgp.BGPUpdate) + + if y, f := update.IsEndOfRib(); y { + // this message has no normal updates or withdrawals. + return []*Path{NewEOR(f)} + } + + adds := make([]bgp.AddrPrefixInterface, 0, len(update.NLRI)) + for _, nlri := range update.NLRI { + adds = append(adds, nlri) + } + + dels := make([]bgp.AddrPrefixInterface, 0, len(update.WithdrawnRoutes)) + for _, nlri := range update.WithdrawnRoutes { + dels = append(dels, nlri) + } + + attrs := make([]bgp.PathAttributeInterface, 0, len(update.PathAttributes)) + var reach *bgp.PathAttributeMpReachNLRI + for _, attr := range update.PathAttributes { + switch a := attr.(type) { + case *bgp.PathAttributeMpReachNLRI: + reach = a + case *bgp.PathAttributeMpUnreachNLRI: + l := make([]bgp.AddrPrefixInterface, 0, len(a.Value)) + l = append(l, a.Value...) + dels = append(dels, l...) + default: + // update msg may not contain next_hop (type:3) in attr + // due to it uses MpReachNLRI and it also has empty update.NLRI + attrs = append(attrs, attr) + } + } + + listLen := len(adds) + len(dels) + if reach != nil { + listLen += len(reach.Value) + } + + var hash uint32 + if len(adds) > 0 || reach != nil { + total := bytes.NewBuffer(make([]byte, 0)) + for _, a := range attrs { + b, _ := a.Serialize() + total.Write(b) + } + hash = farm.Hash32(total.Bytes()) + } + + pathList := make([]*Path, 0, listLen) + for _, nlri := range adds { + p := NewPath(peerInfo, nlri, false, attrs, timestamp, false) + p.SetHash(hash) + pathList = append(pathList, p) + } + if reach != nil { + reachAttrs := make([]bgp.PathAttributeInterface, len(attrs)+1) + copy(reachAttrs, attrs) + // we sort attributes when creating a bgp message from paths + reachAttrs[len(reachAttrs)-1] = reach + + for _, nlri := range reach.Value { + // when build path from reach + // reachAttrs might not contain next_hop if `attrs` does not have one + // this happens when a MP peer send update to gobgp + // However nlri is always populated because how we build the path + // path.info{nlri: nlri} + p := NewPath(peerInfo, nlri, false, reachAttrs, timestamp, false) + p.SetHash(hash) + pathList = append(pathList, p) + } + } + for _, nlri := range dels { + p := NewPath(peerInfo, nlri, true, []bgp.PathAttributeInterface{}, timestamp, false) + pathList = append(pathList, p) + } + return pathList +} + +type TableManager struct { + Tables map[bgp.RouteFamily]*Table + Vrfs map[string]*Vrf + rfList []bgp.RouteFamily + logger log.Logger +} + +func NewTableManager(logger log.Logger, rfList []bgp.RouteFamily) *TableManager { + t := &TableManager{ + Tables: make(map[bgp.RouteFamily]*Table), + Vrfs: make(map[string]*Vrf), + rfList: rfList, + logger: logger, + } + for _, rf := range rfList { + t.Tables[rf] = NewTable(logger, rf) + } + return t +} + +func (manager *TableManager) GetRFlist() []bgp.RouteFamily { + return manager.rfList +} + +func (manager *TableManager) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface, info *PeerInfo) ([]*Path, error) { + if _, ok := manager.Vrfs[name]; ok { + return nil, fmt.Errorf("vrf %s already exists", name) + } + manager.logger.Debug("add vrf", + log.Fields{ + "Topic": "Vrf", + "Key": name, + "Rd": rd, + "ImportRt": importRt, + "ExportRt": exportRt}) + manager.Vrfs[name] = &Vrf{ + Name: name, + Id: id, + Rd: rd, + ImportRt: importRt, + ExportRt: exportRt, + } + msgs := make([]*Path, 0, len(importRt)) + nexthop := "0.0.0.0" + for _, target := range importRt { + nlri := bgp.NewRouteTargetMembershipNLRI(info.AS, target) + pattr := make([]bgp.PathAttributeInterface, 0, 2) + pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP)) + pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) + msgs = append(msgs, NewPath(info, nlri, false, pattr, time.Now(), false)) + } + return msgs, nil +} + +func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) { + if _, ok := manager.Vrfs[name]; !ok { + return nil, fmt.Errorf("vrf %s not found", name) + } + msgs := make([]*Path, 0) + vrf := manager.Vrfs[name] + for _, t := range manager.Tables { + msgs = append(msgs, t.deletePathsByVrf(vrf)...) + } + manager.logger.Debug("delete vrf", + log.Fields{ + "Topic": "Vrf", + "Key": vrf.Name, + "Rd": vrf.Rd, + "ImportRt": vrf.ImportRt, + "ExportRt": vrf.ExportRt, + "MplsLabel": vrf.MplsLabel}) + delete(manager.Vrfs, name) + rtcTable := manager.Tables[bgp.RF_RTC_UC] + msgs = append(msgs, rtcTable.deleteRTCPathsByVrf(vrf, manager.Vrfs)...) + return msgs, nil +} + +func (manager *TableManager) update(newPath *Path) *Update { + t := manager.Tables[newPath.GetRouteFamily()] + t.validatePath(newPath) + dst := t.getOrCreateDest(newPath.GetNlri(), 64) + u := dst.Calculate(manager.logger, newPath) + if len(dst.knownPathList) == 0 { + t.deleteDest(dst) + } + return u +} + +func (manager *TableManager) Update(newPath *Path) []*Update { + if newPath == nil || newPath.IsEOR() { + return nil + } + + // Except for a special case with EVPN, we'll have one destination. + updates := make([]*Update, 0, 1) + family := newPath.GetRouteFamily() + if _, ok := manager.Tables[family]; ok { + updates = append(updates, manager.update(newPath)) + + if family == bgp.RF_EVPN { + for _, p := range manager.handleMacMobility(newPath) { + updates = append(updates, manager.update(p)) + } + } + } + return updates +} + +// EVPN MAC MOBILITY HANDLING +// +// RFC7432 15. MAC Mobility +// +// A PE receiving a MAC/IP Advertisement route for a MAC address with a +// different Ethernet segment identifier and a higher sequence number +// than that which it had previously advertised withdraws its MAC/IP +// Advertisement route. +// ...... +// If the PE is the originator of the MAC route and it receives the same +// MAC address with the same sequence number that it generated, it will +// compare its own IP address with the IP address of the remote PE and +// will select the lowest IP. If its own route is not the best one, it +// will withdraw the route. +func (manager *TableManager) handleMacMobility(path *Path) []*Path { + pathList := make([]*Path, 0) + nlri := path.GetNlri().(*bgp.EVPNNLRI) + if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT { + return nil + } + for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, 0, []bgp.RouteFamily{bgp.RF_EVPN}) { + if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT { + continue + } + f := func(p *Path) (bgp.EthernetSegmentIdentifier, uint32, net.HardwareAddr, int, net.IP) { + nlri := p.GetNlri().(*bgp.EVPNNLRI) + d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute) + ecs := p.GetExtCommunities() + seq := -1 + for _, ec := range ecs { + if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY { + seq = int(ec.(*bgp.MacMobilityExtended).Sequence) + break + } + } + return d.ESI, d.ETag, d.MacAddress, seq, p.info.source.Address + } + e1, et1, m1, s1, i1 := f(path) + e2, et2, m2, s2, i2 := f(path2) + if et1 == et2 && bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) { + if s1 > s2 || s1 == s2 && bytes.Compare(i1, i2) < 0 { + pathList = append(pathList, path2.Clone(true)) + } + } + } + return pathList +} + +func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table { + l := make([]*Table, 0, len(manager.Tables)) + if len(list) == 0 { + for _, v := range manager.Tables { + l = append(l, v) + } + return l + } + for _, f := range list { + if t, ok := manager.Tables[f]; ok { + l = append(l, t) + } + } + return l +} + +func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int { + count := 0 + for _, t := range manager.tables(rfList...) { + count += len(t.GetDestinations()) + } + return count +} + +func (manager *TableManager) GetBestPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path { + if SelectionOptions.DisableBestPathSelection { + // Note: If best path selection disabled, there is no best path. + return nil + } + paths := make([]*Path, 0, manager.getDestinationCount(rfList)) + for _, t := range manager.tables(rfList...) { + paths = append(paths, t.Bests(id, as)...) + } + return paths +} + +func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteFamily) [][]*Path { + if !UseMultiplePaths.Enabled || SelectionOptions.DisableBestPathSelection { + // Note: If multi path not enabled or best path selection disabled, + // there is no best multi path. + return nil + } + paths := make([][]*Path, 0, manager.getDestinationCount(rfList)) + for _, t := range manager.tables(rfList...) { + paths = append(paths, t.MultiBests(id)...) + } + return paths +} + +func (manager *TableManager) GetPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path { + paths := make([]*Path, 0, manager.getDestinationCount(rfList)) + for _, t := range manager.tables(rfList...) { + paths = append(paths, t.GetKnownPathList(id, as)...) + } + return paths +} + +func (manager *TableManager) GetPathListWithNexthop(id string, rfList []bgp.RouteFamily, nexthop net.IP) []*Path { + paths := make([]*Path, 0, manager.getDestinationCount(rfList)) + for _, rf := range rfList { + if t, ok := manager.Tables[rf]; ok { + for _, path := range t.GetKnownPathList(id, 0) { + if path.GetNexthop().Equal(nexthop) { + paths = append(paths, path) + } + } + } + } + return paths +} + +func (manager *TableManager) GetPathListWithSource(id string, rfList []bgp.RouteFamily, source *PeerInfo) []*Path { + paths := make([]*Path, 0, manager.getDestinationCount(rfList)) + for _, rf := range rfList { + if t, ok := manager.Tables[rf]; ok { + for _, path := range t.GetKnownPathList(id, 0) { + if path.GetSource().Equal(source) { + paths = append(paths, path) + } + } + } + } + return paths +} + +func (manager *TableManager) GetDestination(path *Path) *Destination { + if path == nil { + return nil + } + family := path.GetRouteFamily() + t, ok := manager.Tables[family] + if !ok { + return nil + } + return t.GetDestination(path.GetNlri()) +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/vrf.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/vrf.go new file mode 100644 index 000000000..f60765fa6 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/table/vrf.go @@ -0,0 +1,55 @@ +// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation. +// +// 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 table + +import ( + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +type Vrf struct { + Name string + Id uint32 + Rd bgp.RouteDistinguisherInterface + ImportRt []bgp.ExtendedCommunityInterface + ExportRt []bgp.ExtendedCommunityInterface + MplsLabel uint32 +} + +func (v *Vrf) Clone() *Vrf { + f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface { + l := make([]bgp.ExtendedCommunityInterface, 0, len(rt)) + return append(l, rt...) + } + return &Vrf{ + Name: v.Name, + Id: v.Id, + Rd: v.Rd, + ImportRt: f(v.ImportRt), + ExportRt: f(v.ExportRt), + MplsLabel: v.MplsLabel, + } +} + +func isLastTargetUser(vrfs map[string]*Vrf, target bgp.ExtendedCommunityInterface) bool { + for _, vrf := range vrfs { + for _, rt := range vrf.ImportRt { + if target.String() == rt.String() { + return false + } + } + } + return true +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/version/version.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/version/version.go new file mode 100644 index 000000000..1838e05ed --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/version/version.go @@ -0,0 +1,51 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// 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 version + +import "fmt" + +const MAJOR uint = 3 +const MINOR uint = 8 +const PATCH uint = 0 + +var COMMIT string = "" +var IDENTIFIER string = "" +var METADATA string = "" + +func Version() string { + var suffix string = "" + if len(IDENTIFIER) > 0 { + suffix = fmt.Sprintf("-%s", IDENTIFIER) + } + + if len(COMMIT) > 0 || len(METADATA) > 0 { + suffix = suffix + "+" + } + + if len(COMMIT) > 0 { + suffix = fmt.Sprintf("%s"+"commit.%s", suffix, COMMIT) + + } + + if len(METADATA) > 0 { + if len(COMMIT) > 0 { + suffix = suffix + "." + } + suffix = suffix + METADATA + } + + return fmt.Sprintf("%d.%d.%d%s", MAJOR, MINOR, PATCH, suffix) +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/afi_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/afi_string.go new file mode 100644 index 000000000..1cda4d159 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/afi_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type=afi"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[afiIP-1] + _ = x[afiIP6-2] + _ = x[afiEther-3] + _ = x[afiMax-4] +} + +const _afi_name = "afiIPafiIP6afiEtherafiMax" + +var _afi_index = [...]uint8{0, 5, 11, 19, 25} + +func (i afi) String() string { + i -= 1 + if i >= afi(len(_afi_index)-1) { + return "afi(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _afi_name[_afi_index[i]:_afi_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/apitype_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/apitype_string.go new file mode 100644 index 000000000..f8fffd594 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/apitype_string.go @@ -0,0 +1,272 @@ +// Code generated by "stringer -type=APIType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[interfaceAdd-0] + _ = x[interfaceDelete-1] + _ = x[interfaceAddressAdd-2] + _ = x[interfaceAddressDelete-3] + _ = x[interfaceUp-4] + _ = x[interfaceDown-5] + _ = x[_interfaceSetMaster-6] + _ = x[_interfaceSetProtoDown-7] + _ = x[RouteAdd-8] + _ = x[RouteDelete-9] + _ = x[_routeNotifyOwner-10] + _ = x[redistributeAdd-11] + _ = x[_redistributeDelete-12] + _ = x[_redistributeDefaultAdd-13] + _ = x[_redistributeDefaultDelete-14] + _ = x[routerIDAdd-15] + _ = x[_routerIDDelete-16] + _ = x[routerIDUpdate-17] + _ = x[hello-18] + _ = x[_capabilities-19] + _ = x[nexthopRegister-20] + _ = x[nexthopUnregister-21] + _ = x[nexthopUpdate-22] + _ = x[_interfaceNBRAddressAdd-23] + _ = x[_interfaceNBRAddressDelete-24] + _ = x[_interfaceBFDDestUpdate-25] + _ = x[_importRouteRegister-26] + _ = x[_importRouteUnregister-27] + _ = x[_importCheckUpdate-28] + _ = x[_bfdDestRegister-29] + _ = x[_bfdDestDeregister-30] + _ = x[_bfdDestUpdate-31] + _ = x[_bfdDestReplay-32] + _ = x[redistributeRouteAdd-33] + _ = x[redistributeRouteDel-34] + _ = x[_vrfUnregister-35] + _ = x[_vrfAdd-36] + _ = x[_vrfDelete-37] + _ = x[vrfLabel-38] + _ = x[_interfaceVRFUpdate-39] + _ = x[_bfdClientRegister-40] + _ = x[_bfdClientDeregister-41] + _ = x[_interfaceEnableRADV-42] + _ = x[_interfaceDisableRADV-43] + _ = x[ipv4NexthopLookupMRIB-44] + _ = x[_interfaceLinkParams-45] + _ = x[_mplsLabelsAdd-46] + _ = x[_mplsLabelsDelete-47] + _ = x[_mplsLabelsReplace-48] + _ = x[_srPolicySet-49] + _ = x[_srPolicyDelete-50] + _ = x[_srPolicyNotifyStatus-51] + _ = x[_ipmrRouteStats-52] + _ = x[labelManagerConnect-53] + _ = x[labelManagerConnectAsync-54] + _ = x[getLabelChunk-55] + _ = x[releaseLabelChunk-56] + _ = x[_fecRegister-57] + _ = x[_fecUnregister-58] + _ = x[_fecUpdate-59] + _ = x[_advertiseDefaultGW-60] + _ = x[_advertiseSviMACIP-61] + _ = x[_advertiseSubnet-62] + _ = x[_advertiseAllVNI-63] + _ = x[_localESAdd-64] + _ = x[_localESDel-65] + _ = x[_remoteESVTEPAdd-66] + _ = x[_remoteESVTEPDel-67] + _ = x[_localESEVIAdd-68] + _ = x[_localESEVIDel-69] + _ = x[_vniAdd-70] + _ = x[_vniDel-71] + _ = x[_l3VNIAdd-72] + _ = x[_l3VNIDel-73] + _ = x[_remoteVTEPAdd-74] + _ = x[_remoteVTEPDel-75] + _ = x[_macIPAdd-76] + _ = x[_macIPDel-77] + _ = x[_ipPrefixRouteAdd-78] + _ = x[_ipPrefixRouteDel-79] + _ = x[_remoteMACIPAdd-80] + _ = x[_remoteMACIPDel-81] + _ = x[_duplicateAddrDetection-82] + _ = x[_pwAdd-83] + _ = x[_pwDelete-84] + _ = x[_pwSet-85] + _ = x[_pwUnset-86] + _ = x[_pwStatusUpdate-87] + _ = x[_ruleAdd-88] + _ = x[_ruleDelete-89] + _ = x[_ruleNotifyOwner-90] + _ = x[_tableManagerConnect-91] + _ = x[_getTableChunk-92] + _ = x[_releaseTableChunk-93] + _ = x[_ipSetCreate-94] + _ = x[_ipSetDestroy-95] + _ = x[_ipSetEntryAdd-96] + _ = x[_ipSetEntryDelete-97] + _ = x[_ipSetNotifyOwner-98] + _ = x[_ipSetEntryNotifyOwner-99] + _ = x[_ipTableAdd-100] + _ = x[_ipTableDelete-101] + _ = x[_ipTableNotifyOwner-102] + _ = x[_vxlanFloodControl-103] + _ = x[_vxlanSgAdd-104] + _ = x[_vxlanSgDel-105] + _ = x[_vxlanSgReplay-106] + _ = x[_mlagProcessUp-107] + _ = x[_mlagProcessDown-108] + _ = x[_mlagClientRegister-109] + _ = x[_mlagClientUnregister-110] + _ = x[_mlagClientForwardMsg-111] + _ = x[_nhgAdd-112] + _ = x[_nhgDel-113] + _ = x[_nhgNotifyOwner-114] + _ = x[_nhgEvpnRemoteNhAdd-115] + _ = x[_nhgEvpnRemoteNhDel-116] + _ = x[_srv6LocatorAdd-117] + _ = x[_srv6LocatorDelete-118] + _ = x[_srv6ManagerGetLocatorChunk-119] + _ = x[_srv6ManagerReleaseLocatorChunk-120] + _ = x[zebraError-121] + _ = x[_clientCapabilities-122] + _ = x[_opaqueMessage-123] + _ = x[_opaqueRegister-124] + _ = x[_opaqueUnregister-125] + _ = x[_neighDiscover-126] + _ = x[_RouteNotifyRequest-127] + _ = x[_ClientCloseNotify-128] + _ = x[_NhrpNeighAdded-129] + _ = x[_NhrpNeighRemoved-130] + _ = x[_NhrpNeighGet-131] + _ = x[_NhrpNeighRegister-132] + _ = x[_NhrpNeighUnregister-133] + _ = x[_NeighIPAdd-134] + _ = x[_NeighIPDel-135] + _ = x[_ConfigureArp-136] + _ = x[_GreGet-137] + _ = x[_GreUpdate-138] + _ = x[_GreSourceSet-139] + _ = x[BackwardIPv6RouteAdd-140] + _ = x[BackwardIPv6RouteDelete-141] + _ = x[zapi6Frr8dot2MinDifferentAPIType-26] + _ = x[zapi6Frr7dot3MinDifferentAPIType-49] + _ = x[zapi6Frr7dot2MinDifferentAPIType-48] + _ = x[zapi6Frr6MinDifferentAPIType-7] + _ = x[zapi5ClMinDifferentAPIType-19] + _ = x[zapi5MinDifferentAPIType-7] + _ = x[zapi4MinDifferentAPIType-6] + _ = x[zapi3MinDifferentAPIType-0] + _ = x[zapi6Frr8dot2RedistributeRouteAdd-30] + _ = x[zapi6Frr8dot2RedistributeRouteDel-31] + _ = x[zapi6Frr8dot2VrfLabel-35] + _ = x[zapi6Frr8dot2Ipv4NexthopLookupMRIB-41] + _ = x[zapi6Frr8dot2LabelManagerConnect-50] + _ = x[zapi6Frr8dot2LabelManagerConnectAsync-51] + _ = x[zapi6Frr8dot2GetLabelChunk-52] + _ = x[zapi6Frr8dot2ReleaseLabelChunk-53] + _ = x[zapi6Frr7dot3LabelManagerConnect-50] + _ = x[zapi6Frr7dot3LabelManagerConnectAsync-51] + _ = x[zapi6Frr7dot3GetLabelChunk-52] + _ = x[zapi6Frr7dot3ReleaseLabelChunk-53] + _ = x[zapi6Frr7dot2LabelManagerConnect-49] + _ = x[zapi6Frr7dot2LabelManagerConnectAsync-50] + _ = x[zapi6Frr7dot2GetLabelChunk-51] + _ = x[zapi6Frr7dot2ReleaseLabelChunk-52] + _ = x[zapi6Frr7RouteAdd-7] + _ = x[zapi6Frr7RouteDelete-8] + _ = x[zapi6Frr7RedistributAdd-10] + _ = x[zapi6Frr7RouterIDAdd-14] + _ = x[zapi6Frr7RouterIDUpdate-16] + _ = x[zapi6Frr7Hello-17] + _ = x[zapi6Frr7NexthopRegister-19] + _ = x[zapi6Frr7NexthopUnregister-20] + _ = x[zapi6Frr7NexthopUpdate-21] + _ = x[zapi6Frr7RedistributeRouteAdd-32] + _ = x[zapi6Frr7RedistributeRouteDel-33] + _ = x[zapi6Frr7VrfLabel-37] + _ = x[zapi6Frr7Ipv4NexthopLookupMRIB-43] + _ = x[zapi6Frr7LabelManagerConnect-48] + _ = x[zapi6Frr7LabelManagerConnectAsync-49] + _ = x[zapi6Frr7GetLabelChunk-50] + _ = x[zapi6Frr7ReleaseLabelChunk-51] + _ = x[zapi5ClIpv4NexthopLookupMRIB-42] + _ = x[zapi5ClLabelManagerConnect-47] + _ = x[zapi5ClGetLabelChunk-48] + _ = x[zapi5ClReleaseLabelChunk-49] + _ = x[zapi5RedistributAdd-14] + _ = x[zapi5RouterIDAdd-18] + _ = x[zapi5RouterIDUpdate-20] + _ = x[zapi5Hello-21] + _ = x[zapi5Frr5NexthopRegister-23] + _ = x[zapi5Frr5NexthopUnregister-24] + _ = x[zapi5Frr5NexthopUpdate-25] + _ = x[zapi5Frr5RedistributeRouteAdd-37] + _ = x[zapi5Frr5RedistributeRouteDel-38] + _ = x[zapi5Frr5VrfLabel-42] + _ = x[zapi5Frr5Ipv4NexthopLookupMRIB-47] + _ = x[zapi5Frr5LabelManagerConnect-52] + _ = x[zapi5Frr5LabelManagerConnectAsync-53] + _ = x[zapi5Frr5GetLabelChunk-54] + _ = x[zapi5Frr5ReleaseLabelChunk-55] + _ = x[zapi5Frr4NexthopRegister-22] + _ = x[zapi5Frr4NexthopUnregister-23] + _ = x[zapi5Frr4NexthopUpdate-24] + _ = x[zapi5Frr4RedistributeRouteAdd-36] + _ = x[zapi5Frr4RedistributeRouteDel-37] + _ = x[zapi5Frr4Ipv4NexthopLookupMRIB-45] + _ = x[zapi5Frr4LabelManagerConnect-50] + _ = x[zapi5Frr4GetLabelChunk-51] + _ = x[zapi5Frr4ReleaseLabelChunk-52] + _ = x[zapi4IPv4RouteAdd-6] + _ = x[zapi4IPv4RouteDelete-7] + _ = x[zapi4IPv6RouteAdd-8] + _ = x[zapi4IPv6RouteDelete-9] + _ = x[zapi4RedistributAdd-10] + _ = x[zapi4RouterIDAdd-14] + _ = x[zapi4RouterIDUpdate-16] + _ = x[zapi4Hello-17] + _ = x[zapi4NexthopRegister-18] + _ = x[zapi4NexthopUnregister-19] + _ = x[zapi4NexthopUpdate-20] + _ = x[zapi4RedistributeIPv4Add-32] + _ = x[zapi4RedistributeIPv4Del-33] + _ = x[zapi4RedistributeIPv6Add-34] + _ = x[zapi4RedistributeIPv6Del-35] + _ = x[zapi4LabelManagerConnect-52] + _ = x[zapi4GetLabelChunk-53] + _ = x[zapi4ReleaseLabelChunk-54] + _ = x[zapi3InterfaceAdd-1] + _ = x[zapi3InterfaceDelete-2] + _ = x[zapi3InterfaceAddressAdd-3] + _ = x[zapi3InterfaceAddressDelete-4] + _ = x[zapi3InterfaceUp-5] + _ = x[zapi3InterfaceDown-6] + _ = x[zapi3IPv4RouteAdd-7] + _ = x[zapi3IPv4RouteDelete-8] + _ = x[zapi3IPv6RouteAdd-9] + _ = x[zapi3IPv6RouteDelete-10] + _ = x[zapi3RedistributeAdd-11] + _ = x[zapi3IPv4NexthopLookup-15] + _ = x[zapi3IPv6NexthopLookup-16] + _ = x[zapi3IPv4ImportLookup-17] + _ = x[zapi3RouterIDAdd-20] + _ = x[zapi3RouterIDUpdate-22] + _ = x[zapi3Hello-23] + _ = x[zapi3Ipv4NexthopLookupMRIB-24] + _ = x[zapi3NexthopRegister-27] + _ = x[zapi3NexthopUnregister-28] + _ = x[zapi3NexthopUpdate-29] +} + +const _APIType_name = "interfaceAddinterfaceDeleteinterfaceAddressAddinterfaceAddressDeleteinterfaceUpinterfaceDown_interfaceSetMaster_interfaceSetProtoDownRouteAddRouteDelete_routeNotifyOwnerredistributeAdd_redistributeDelete_redistributeDefaultAdd_redistributeDefaultDeleterouterIDAdd_routerIDDeleterouterIDUpdatehello_capabilitiesnexthopRegisternexthopUnregisternexthopUpdate_interfaceNBRAddressAdd_interfaceNBRAddressDelete_interfaceBFDDestUpdate_importRouteRegister_importRouteUnregister_importCheckUpdate_bfdDestRegister_bfdDestDeregister_bfdDestUpdate_bfdDestReplayredistributeRouteAddredistributeRouteDel_vrfUnregister_vrfAdd_vrfDeletevrfLabel_interfaceVRFUpdate_bfdClientRegister_bfdClientDeregister_interfaceEnableRADV_interfaceDisableRADVipv4NexthopLookupMRIB_interfaceLinkParams_mplsLabelsAdd_mplsLabelsDelete_mplsLabelsReplace_srPolicySet_srPolicyDelete_srPolicyNotifyStatus_ipmrRouteStatslabelManagerConnectlabelManagerConnectAsyncgetLabelChunkreleaseLabelChunk_fecRegister_fecUnregister_fecUpdate_advertiseDefaultGW_advertiseSviMACIP_advertiseSubnet_advertiseAllVNI_localESAdd_localESDel_remoteESVTEPAdd_remoteESVTEPDel_localESEVIAdd_localESEVIDel_vniAdd_vniDel_l3VNIAdd_l3VNIDel_remoteVTEPAdd_remoteVTEPDel_macIPAdd_macIPDel_ipPrefixRouteAdd_ipPrefixRouteDel_remoteMACIPAdd_remoteMACIPDel_duplicateAddrDetection_pwAdd_pwDelete_pwSet_pwUnset_pwStatusUpdate_ruleAdd_ruleDelete_ruleNotifyOwner_tableManagerConnect_getTableChunk_releaseTableChunk_ipSetCreate_ipSetDestroy_ipSetEntryAdd_ipSetEntryDelete_ipSetNotifyOwner_ipSetEntryNotifyOwner_ipTableAdd_ipTableDelete_ipTableNotifyOwner_vxlanFloodControl_vxlanSgAdd_vxlanSgDel_vxlanSgReplay_mlagProcessUp_mlagProcessDown_mlagClientRegister_mlagClientUnregister_mlagClientForwardMsg_nhgAdd_nhgDel_nhgNotifyOwner_nhgEvpnRemoteNhAdd_nhgEvpnRemoteNhDel_srv6LocatorAdd_srv6LocatorDelete_srv6ManagerGetLocatorChunk_srv6ManagerReleaseLocatorChunkzebraError_clientCapabilities_opaqueMessage_opaqueRegister_opaqueUnregister_neighDiscover_RouteNotifyRequest_ClientCloseNotify_NhrpNeighAdded_NhrpNeighRemoved_NhrpNeighGet_NhrpNeighRegister_NhrpNeighUnregister_NeighIPAdd_NeighIPDel_ConfigureArp_GreGet_GreUpdate_GreSourceSetBackwardIPv6RouteAddBackwardIPv6RouteDelete" + +var _APIType_index = [...]uint16{0, 12, 27, 46, 68, 79, 92, 111, 133, 141, 152, 169, 184, 203, 226, 252, 263, 278, 292, 297, 310, 325, 342, 355, 378, 404, 427, 447, 469, 487, 503, 521, 535, 549, 569, 589, 603, 610, 620, 628, 647, 665, 685, 705, 726, 747, 767, 781, 798, 816, 828, 843, 864, 879, 898, 922, 935, 952, 964, 978, 988, 1007, 1025, 1041, 1057, 1068, 1079, 1095, 1111, 1125, 1139, 1146, 1153, 1162, 1171, 1185, 1199, 1208, 1217, 1234, 1251, 1266, 1281, 1304, 1310, 1319, 1325, 1333, 1348, 1356, 1367, 1383, 1403, 1417, 1435, 1447, 1460, 1474, 1491, 1508, 1530, 1541, 1555, 1574, 1592, 1603, 1614, 1628, 1642, 1658, 1677, 1698, 1719, 1726, 1733, 1748, 1767, 1786, 1801, 1819, 1846, 1877, 1887, 1906, 1920, 1935, 1952, 1966, 1985, 2003, 2018, 2035, 2048, 2066, 2086, 2097, 2108, 2121, 2128, 2138, 2151, 2171, 2194} + +func (i APIType) String() string { + if i >= APIType(len(_APIType_index)-1) { + return "APIType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _APIType_name[_APIType_index[i]:_APIType_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/linktype_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/linktype_string.go new file mode 100644 index 000000000..89e42b1c3 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/linktype_string.go @@ -0,0 +1,72 @@ +// Code generated by "stringer -type=linkType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[linkTypeUnknown-0] + _ = x[linkTypeEther-1] + _ = x[linkTypeEEther-2] + _ = x[linkTypeAX25-3] + _ = x[linkTypePRONET-4] + _ = x[linkTypeIeee802-5] + _ = x[linkTypeARCNET-6] + _ = x[linkTypeAPPLETLK-7] + _ = x[linkTypeDLCI-8] + _ = x[linkTypeATM-9] + _ = x[linkTypeMetricOM-10] + _ = x[linkTypeIeee1394-11] + _ = x[linkTypeEUI64-12] + _ = x[linkTypeINFINIBAND-13] + _ = x[linkTypeSLIP-14] + _ = x[linkTypeCSLIP-15] + _ = x[linkTypeSLIP6-16] + _ = x[linkTypeCSLIP6-17] + _ = x[linkTypeRSRVD-18] + _ = x[linkTypeADAPT-19] + _ = x[linkTypeROSE-20] + _ = x[linkTypeX25-21] + _ = x[linkTypePPP-22] + _ = x[linkTypeCHDLC-23] + _ = x[linkTypeLAPB-24] + _ = x[linkTypeRAWHDLC-25] + _ = x[linkTypeIPIP-26] + _ = x[linkTypeIPIP6-27] + _ = x[linkTypeFRAD-28] + _ = x[linkTypeSKIP-29] + _ = x[linkTypeLOOPBACK-30] + _ = x[linkTypeLOCALTLK-31] + _ = x[linkTypeFDDI-32] + _ = x[linkTypeSIT-33] + _ = x[linkTypeIPDDP-34] + _ = x[linkTypeIPGRE-35] + _ = x[linkTypeIP6GRE-36] + _ = x[linkTypePIMREG-37] + _ = x[linkTypeHIPPI-38] + _ = x[linkTypeECONET-39] + _ = x[linkTypeIRDA-40] + _ = x[linkTypeFCPP-41] + _ = x[linkTypeFCAL-42] + _ = x[linkTypeFCPL-43] + _ = x[linkTypeFCFABRIC-44] + _ = x[linkTypeIeee802Tr-45] + _ = x[linkTypeIeee80211-46] + _ = x[linkTypeIeee80211RadioTap-47] + _ = x[linkTypeIeee802154-48] + _ = x[linkTypeIeee802154Phy-49] +} + +const _linkType_name = "linkTypeUnknownlinkTypeEtherlinkTypeEEtherlinkTypeAX25linkTypePRONETlinkTypeIeee802linkTypeARCNETlinkTypeAPPLETLKlinkTypeDLCIlinkTypeATMlinkTypeMetricOMlinkTypeIeee1394linkTypeEUI64linkTypeINFINIBANDlinkTypeSLIPlinkTypeCSLIPlinkTypeSLIP6linkTypeCSLIP6linkTypeRSRVDlinkTypeADAPTlinkTypeROSElinkTypeX25linkTypePPPlinkTypeCHDLClinkTypeLAPBlinkTypeRAWHDLClinkTypeIPIPlinkTypeIPIP6linkTypeFRADlinkTypeSKIPlinkTypeLOOPBACKlinkTypeLOCALTLKlinkTypeFDDIlinkTypeSITlinkTypeIPDDPlinkTypeIPGRElinkTypeIP6GRElinkTypePIMREGlinkTypeHIPPIlinkTypeECONETlinkTypeIRDAlinkTypeFCPPlinkTypeFCALlinkTypeFCPLlinkTypeFCFABRIClinkTypeIeee802TrlinkTypeIeee80211linkTypeIeee80211RadioTaplinkTypeIeee802154linkTypeIeee802154Phy" + +var _linkType_index = [...]uint16{0, 15, 28, 42, 54, 68, 83, 97, 113, 125, 136, 152, 168, 181, 199, 211, 224, 237, 251, 264, 277, 289, 300, 311, 324, 336, 351, 363, 376, 388, 400, 416, 432, 444, 455, 468, 481, 495, 509, 522, 536, 548, 560, 572, 584, 600, 617, 634, 659, 677, 698} + +func (i linkType) String() string { + if i >= linkType(len(_linkType_index)-1) { + return "linkType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _linkType_name[_linkType_index[i]:_linkType_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/lsptype_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/lsptype_string.go new file mode 100644 index 000000000..5b9591809 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/lsptype_string.go @@ -0,0 +1,28 @@ +// Code generated by "stringer -type=lspTYPE"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[lspNone-0] + _ = x[lspStatic-1] + _ = x[lspLDP-2] + _ = x[lspBGP-3] + _ = x[lspSR-4] + _ = x[lspSHARP-5] +} + +const _lspTYPE_name = "lspNonelspStaticlspLDPlspBGPlspSRlspSHARP" + +var _lspTYPE_index = [...]uint8{0, 7, 16, 22, 28, 33, 41} + +func (i lspTYPE) String() string { + if i >= lspTYPE(len(_lspTYPE_index)-1) { + return "lspTYPE(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _lspTYPE_name[_lspTYPE_index[i]:_lspTYPE_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthopflag_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthopflag_string.go new file mode 100644 index 000000000..4c9964604 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthopflag_string.go @@ -0,0 +1,61 @@ +// Code generated by "stringer -type=nexthopFlag"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[nexthopFlagActive-1] + _ = x[nexthopFlagFIB-2] + _ = x[nexthopFlagRecursive-4] + _ = x[nexthopFlagOnlink-8] + _ = x[nexthopFlagDuplicate-16] + _ = x[nexthopFlagRnhFiltered-32] + _ = x[nexthopFlagHasBackup-64] + _ = x[nexthopFlagSRTE-128] + _ = x[zapi6Frr7dot3nexthopFlagMatched-16] + _ = x[zapi6Frr7dot3nexthopFlagDuplicate-32] + _ = x[zapi6Frr7dot3nexthopFlagRnhFiltered-64] + _ = x[zapi6Frr7nexthopFlagFiltered-32] + _ = x[zapi6Frr7nexthopFlagDuplicate-64] + _ = x[zapi6Frr7nexthopFlagEvpnRvtep-128] +} + +const ( + _nexthopFlag_name_0 = "nexthopFlagActivenexthopFlagFIB" + _nexthopFlag_name_1 = "nexthopFlagRecursive" + _nexthopFlag_name_2 = "nexthopFlagOnlink" + _nexthopFlag_name_3 = "nexthopFlagDuplicate" + _nexthopFlag_name_4 = "nexthopFlagRnhFiltered" + _nexthopFlag_name_5 = "nexthopFlagHasBackup" + _nexthopFlag_name_6 = "nexthopFlagSRTE" +) + +var ( + _nexthopFlag_index_0 = [...]uint8{0, 17, 31} +) + +func (i nexthopFlag) String() string { + switch { + case 1 <= i && i <= 2: + i -= 1 + return _nexthopFlag_name_0[_nexthopFlag_index_0[i]:_nexthopFlag_index_0[i+1]] + case i == 4: + return _nexthopFlag_name_1 + case i == 8: + return _nexthopFlag_name_2 + case i == 16: + return _nexthopFlag_name_3 + case i == 32: + return _nexthopFlag_name_4 + case i == 64: + return _nexthopFlag_name_5 + case i == 128: + return _nexthopFlag_name_6 + default: + return "nexthopFlag(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthoptype_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthoptype_string.go new file mode 100644 index 000000000..0c1c1a28d --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthoptype_string.go @@ -0,0 +1,37 @@ +// Code generated by "stringer -type=nexthopType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[nexthopTypeIFIndex-1] + _ = x[nexthopTypeIPv4-2] + _ = x[nexthopTypeIPv4IFIndex-3] + _ = x[nexthopTypeIPv6-4] + _ = x[nexthopTypeIPv6IFIndex-5] + _ = x[nexthopTypeBlackhole-6] + _ = x[nexthopTypeIFName-2] + _ = x[backwardNexthopTypeIPv4-3] + _ = x[backwardNexthopTypeIPv4IFIndex-4] + _ = x[nexthopTypeIPv4IFName-5] + _ = x[backwardNexthopTypeIPv6-6] + _ = x[backwardNexthopTypeIPv6IFIndex-7] + _ = x[nexthopTypeIPv6IFName-8] + _ = x[backwardNexthopTypeBlackhole-9] +} + +const _nexthopType_name = "nexthopTypeIFIndexnexthopTypeIPv4nexthopTypeIPv4IFIndexnexthopTypeIPv6nexthopTypeIPv6IFIndexnexthopTypeBlackholebackwardNexthopTypeIPv6IFIndexnexthopTypeIPv6IFNamebackwardNexthopTypeBlackhole" + +var _nexthopType_index = [...]uint8{0, 18, 33, 55, 70, 92, 112, 142, 163, 191} + +func (i nexthopType) String() string { + i -= 1 + if i >= nexthopType(len(_nexthopType_index)-1) { + return "nexthopType(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _nexthopType_name[_nexthopType_index[i]:_nexthopType_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmenable_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmenable_string.go new file mode 100644 index 000000000..03830b0c9 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmenable_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=ptmEnable"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ptmEnableOff-0] + _ = x[ptmEnableOn-1] + _ = x[ptmEnableUnspec-2] +} + +const _ptmEnable_name = "ptmEnableOffptmEnableOnptmEnableUnspec" + +var _ptmEnable_index = [...]uint8{0, 12, 23, 38} + +func (i ptmEnable) String() string { + if i >= ptmEnable(len(_ptmEnable_index)-1) { + return "ptmEnable(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ptmEnable_name[_ptmEnable_index[i]:_ptmEnable_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmstatus_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmstatus_string.go new file mode 100644 index 000000000..b6ce519c9 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmstatus_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -type=ptmStatus"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ptmStatusDown-0] + _ = x[ptmStatusUp-1] + _ = x[ptmStatusUnknown-2] +} + +const _ptmStatus_name = "ptmStatusDownptmStatusUpptmStatusUnknown" + +var _ptmStatus_index = [...]uint8{0, 13, 24, 40} + +func (i ptmStatus) String() string { + if i >= ptmStatus(len(_ptmStatus_index)-1) { + return "ptmStatus(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _ptmStatus_name[_ptmStatus_index[i]:_ptmStatus_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/routetype_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/routetype_string.go new file mode 100644 index 000000000..ee15413f4 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/routetype_string.go @@ -0,0 +1,75 @@ +// Code generated by "stringer -type=RouteType"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[routeSystem-0] + _ = x[routeKernel-1] + _ = x[routeConnect-2] + _ = x[RouteStatic-3] + _ = x[routeRIP-4] + _ = x[routeRIPNG-5] + _ = x[routeOSPF-6] + _ = x[routeOSPF6-7] + _ = x[routeISIS-8] + _ = x[RouteBGP-9] + _ = x[routePIM-10] + _ = x[routeEIGRP-11] + _ = x[routeNHRP-12] + _ = x[routeHSLS-13] + _ = x[routeOLSR-14] + _ = x[routeTABLE-15] + _ = x[routeLDP-16] + _ = x[routeVNC-17] + _ = x[routeVNCDirect-18] + _ = x[routeVNCDirectRH-19] + _ = x[routeBGPDirect-20] + _ = x[routeBGPDirectEXT-21] + _ = x[routeBABEL-22] + _ = x[routeSHARP-23] + _ = x[routePBR-24] + _ = x[routeBFD-25] + _ = x[routeOpenfabric-26] + _ = x[routeVRRP-27] + _ = x[routeNHG-28] + _ = x[routeSRTE-29] + _ = x[routeAll-30] + _ = x[routeMax-31] + _ = x[zapi5Frr4RouteAll-24] + _ = x[zapi5Frr5RouteAll-25] + _ = x[zapi6Frr6RouteAll-26] + _ = x[zapi6Frr7RouteAll-27] + _ = x[zapi6Frr7dot2RouteAll-28] + _ = x[zapi6Frr7dot3RouteAll-29] + _ = x[zapi4RouteNHRP-11] + _ = x[zapi4RouteHSLS-12] + _ = x[zapi4RouteOLSR-13] + _ = x[zapi4RouteTABLE-14] + _ = x[zapi4RouteLDP-15] + _ = x[zapi4RouteVNC-16] + _ = x[zapi4RouteVNCDirect-17] + _ = x[zapi4RouteVNCDirectRH-18] + _ = x[zapi4RouteBGPDixrect-19] + _ = x[zapi4RouteBGPDirectEXT-20] + _ = x[zapi4RouteAll-21] + _ = x[zapi3RouteHSLS-11] + _ = x[zapi3RouteOLSR-12] + _ = x[zapi3RouteBABEL-13] + _ = x[zapi3RouteNHRP-14] +} + +const _RouteType_name = "routeSystemrouteKernelrouteConnectRouteStaticrouteRIProuteRIPNGrouteOSPFrouteOSPF6routeISISRouteBGProutePIMrouteEIGRProuteNHRProuteHSLSrouteOLSRrouteTABLErouteLDProuteVNCrouteVNCDirectrouteVNCDirectRHrouteBGPDirectrouteBGPDirectEXTrouteBABELrouteSHARProutePBRrouteBFDrouteOpenfabricrouteVRRProuteNHGrouteSRTErouteAllrouteMax" + +var _RouteType_index = [...]uint16{0, 11, 22, 34, 45, 53, 63, 72, 82, 91, 99, 107, 117, 126, 135, 144, 154, 162, 170, 184, 200, 214, 231, 241, 251, 259, 267, 282, 291, 299, 308, 316, 324} + +func (i RouteType) String() string { + if i >= RouteType(len(_RouteType_index)-1) { + return "RouteType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _RouteType_name[_RouteType_index[i]:_RouteType_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/safi_string.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/safi_string.go new file mode 100644 index 000000000..9adc4ac5a --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/safi_string.go @@ -0,0 +1,36 @@ +// Code generated by "stringer -type=Safi"; DO NOT EDIT. + +package zebra + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[safiUnspec-0] + _ = x[SafiUnicast-1] + _ = x[safiMulticast-2] + _ = x[safiMplsVpn-3] + _ = x[safiEncap-4] + _ = x[safiEvpn-5] + _ = x[safiLabeledUnicast-6] + _ = x[safiFlowspec-7] + _ = x[safiMax-8] + _ = x[zapi4SafiMplsVpn-3] + _ = x[zapi3SafiMplsVpn-4] + _ = x[zapi4SafiEncap-5] + _ = x[zapi4SafiEvpn-6] + _ = x[zapi3SafiEncap-7] +} + +const _Safi_name = "safiUnspecSafiUnicastsafiMulticastsafiMplsVpnsafiEncapsafiEvpnsafiLabeledUnicastsafiFlowspecsafiMax" + +var _Safi_index = [...]uint8{0, 10, 21, 34, 45, 54, 62, 80, 92, 99} + +func (i Safi) String() string { + if i >= Safi(len(_Safi_index)-1) { + return "Safi(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Safi_name[_Safi_index[i]:_Safi_index[i+1]] +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi.go new file mode 100644 index 000000000..ddc5f6ed9 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi.go @@ -0,0 +1,3578 @@ +// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 zebra + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "math" + "net" + "regexp" + "strconv" + "strings" + "syscall" + + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +const ( + // MinZapiVer is minimum zebra api version which is referred in zclient + MinZapiVer uint8 = 2 + // MaxZapiVer is maximum zebra api version which is referredd in zclient + MaxZapiVer uint8 = 6 + // DefaultVrf is default vrf id is referredd in zclient and server + DefaultVrf = 0 +) + +const ( + headerMarker uint8 = 255 + frrHeaderMarker uint8 = 254 + interfaceNameSize = 20 + maxPathNum = 64 + maxMplsLabel = 16 +) + +// Internal Interface Status. +type interfaceStatus uint8 + +const ( + interfaceActive interfaceStatus = 0x01 + interfaceSub interfaceStatus = 0x02 + interfaceLinkDetection interfaceStatus = 0x04 + interfaceVrfLoopback interfaceStatus = 0x08 +) + +// Interface Link Layer Types. +// +//go:generate stringer -type=linkType +type linkType uint32 + +const ( + linkTypeUnknown linkType = iota + linkTypeEther + linkTypeEEther + linkTypeAX25 + linkTypePRONET + linkTypeIeee802 + linkTypeARCNET + linkTypeAPPLETLK + linkTypeDLCI + linkTypeATM + linkTypeMetricOM + linkTypeIeee1394 + linkTypeEUI64 + linkTypeINFINIBAND + linkTypeSLIP + linkTypeCSLIP + linkTypeSLIP6 + linkTypeCSLIP6 + linkTypeRSRVD + linkTypeADAPT + linkTypeROSE + linkTypeX25 + linkTypePPP + linkTypeCHDLC + linkTypeLAPB + linkTypeRAWHDLC + linkTypeIPIP + linkTypeIPIP6 + linkTypeFRAD + linkTypeSKIP + linkTypeLOOPBACK + linkTypeLOCALTLK + linkTypeFDDI + linkTypeSIT + linkTypeIPDDP + linkTypeIPGRE + linkTypeIP6GRE + linkTypePIMREG + linkTypeHIPPI + linkTypeECONET + linkTypeIRDA + linkTypeFCPP + linkTypeFCAL + linkTypeFCPL + linkTypeFCFABRIC + linkTypeIeee802Tr + linkTypeIeee80211 + linkTypeIeee80211RadioTap + linkTypeIeee802154 + linkTypeIeee802154Phy +) + +// HeaderSize returns suitable header size from version +func HeaderSize(version uint8) uint16 { + switch version { + case 3, 4: + return 8 + case 5, 6: + return 10 + } + return 6 // version == 2 +} + +// HeaderMarker returns suitable header marker from version +func HeaderMarker(version uint8) uint8 { + if version > 3 { + return frrHeaderMarker + } + return headerMarker +} + +func (t interfaceStatus) String() string { + ss := make([]string, 0, 3) + if t&interfaceActive > 0 { + ss = append(ss, "Active") + } + if t&interfaceSub > 0 { + ss = append(ss, "Sub") + } + if t&interfaceLinkDetection > 0 { + ss = append(ss, "LinkDetection") + } + if t&interfaceVrfLoopback > 0 { + ss = append(ss, "VrfLoopback") + } + return strings.Join(ss, "|") +} + +// Interface Connected Address Flags +type interfaceAddressFlag uint8 + +const ( + interfaceAddressSecondary interfaceAddressFlag = 0x01 + interfaceAddressPeer interfaceAddressFlag = 0x02 + interfaceAddressUnnumbered interfaceAddressFlag = 0x04 +) + +func (t interfaceAddressFlag) String() string { + ss := make([]string, 0, 3) + if t&interfaceAddressSecondary > 0 { + ss = append(ss, "SECONDARY") + } + if t&interfaceAddressPeer > 0 { + ss = append(ss, "PEER") + } + if t&interfaceAddressUnnumbered > 0 { + ss = append(ss, "UNNUMBERED") + } + return strings.Join(ss, "|") +} + +// Address Family IDentifier. +// +//go:generate stringer -type=afi +type afi uint8 + +const ( + afiIP afi = 1 + afiIP6 afi = 2 + afiEther afi = 3 + afiMax afi = 4 +) + +// Safi is Subsequent Address Family IDentifier. +// +//go:generate stringer -type=Safi +type Safi uint8 + +// Safi definition in Zebra of FRRouting 4.x, 5.x, 6.x, 7.x, and 8.x(lib/zebra.h) +const ( + safiUnspec Safi = iota // added in FRRouting version 7.2 (Zapi 6) + SafiUnicast + safiMulticast + safiMplsVpn + safiEncap + safiEvpn + safiLabeledUnicast + safiFlowspec // added in FRRouting version 5 (Zapi 5) + safiMax +) + +// Safi definition in Zebra of Quagga and FRRouting 3.x +const ( + zapi4SafiMplsVpn Safi = iota + safiMulticast + 1 // SafiRESERVED_3 in quagga + zapi3SafiMplsVpn // SafiRESERVED_4 in FRRouting 3.x + zapi4SafiEncap + zapi4SafiEvpn + zapi3SafiEncap // SafiMax in FRRouting 3.x +) + +var zapi3SafiMap = map[Safi]Safi{ + zapi3SafiMplsVpn: safiMplsVpn, + zapi3SafiEncap: safiEncap, +} +var zapi4SafiMap = map[Safi]Safi{ + zapi4SafiMplsVpn: safiMplsVpn, + zapi4SafiEncap: safiEncap, + zapi4SafiEvpn: safiEvpn, +} +var safiRouteFamilyIPv4Map = map[Safi]bgp.RouteFamily{ + safiUnspec: bgp.RF_OPAQUE, + SafiUnicast: bgp.RF_IPv4_UC, + safiMulticast: bgp.RF_IPv4_MC, + safiMplsVpn: bgp.RF_IPv4_VPN, + safiEncap: bgp.RF_IPv4_ENCAP, + safiLabeledUnicast: bgp.RF_IPv4_MPLS, + safiFlowspec: bgp.RF_FS_IPv4_UC, +} +var safiRouteFamilyIPv6Map = map[Safi]bgp.RouteFamily{ + safiUnspec: bgp.RF_OPAQUE, + SafiUnicast: bgp.RF_IPv6_UC, + safiMulticast: bgp.RF_IPv6_MC, + safiMplsVpn: bgp.RF_IPv6_VPN, + safiEncap: bgp.RF_IPv6_ENCAP, + safiLabeledUnicast: bgp.RF_IPv6_MPLS, + safiFlowspec: bgp.RF_FS_IPv6_UC, +} + +// APIType is referred in zclient_test. +// +//go:generate stringer -type=APIType +type APIType uint16 + +// For FRRouting version 8.1 (ZAPI version 6) +const ( + interfaceAdd APIType = iota // 0 // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + interfaceDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + interfaceAddressAdd // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + interfaceAddressDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + interfaceUp // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + interfaceDown // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3, 7.4, 7.5, 8.0, 8.1, 8.2 + _interfaceSetMaster + _interfaceSetProtoDown // Add in frr 7.2 + RouteAdd // RouteAdd is referred in zclient_test + RouteDelete // RouteDelete is referred in zclient_test + _routeNotifyOwner // 10 + redistributeAdd + _redistributeDelete + _redistributeDefaultAdd + _redistributeDefaultDelete + routerIDAdd + _routerIDDelete + routerIDUpdate + hello + _capabilities // added in frr5 + nexthopRegister // 20 + nexthopUnregister + nexthopUpdate + _interfaceNBRAddressAdd + _interfaceNBRAddressDelete + _interfaceBFDDestUpdate + _importRouteRegister // 25 in frr6, 26 in frr7.x, frr8&8.1, deleted in frr8.2 + _importRouteUnregister // 26 in frr6, 27 in frr7.x, frr8&8.1, deleted in frr8.2 + _importCheckUpdate // 27 in frr6, 28 in frr7.x, frr8&8.1, deleted in frr8.2 + _bfdDestRegister + _bfdDestDeregister // 30 + _bfdDestUpdate + _bfdDestReplay + redistributeRouteAdd // 33 // 30 in frr8.2 + redistributeRouteDel + _vrfUnregister + _vrfAdd + _vrfDelete + vrfLabel // added in frr5 + _interfaceVRFUpdate + _bfdClientRegister // 40 + _bfdClientDeregister + _interfaceEnableRADV + _interfaceDisableRADV // 43 // 50 in frr8.2 + ipv4NexthopLookupMRIB + _interfaceLinkParams + _mplsLabelsAdd + _mplsLabelsDelete + _mplsLabelsReplace // added in frr7.3 + _srPolicySet // added in frr7.5 + _srPolicyDelete // 50 // added in frr7.5 + _srPolicyNotifyStatus // added in frr7.5 + _ipmrRouteStats + labelManagerConnect // 53 // 50 in frr8.2 + labelManagerConnectAsync // added in frr5 + getLabelChunk + releaseLabelChunk + _fecRegister + _fecUnregister + _fecUpdate + _advertiseDefaultGW // 60 + _advertiseSviMACIP // added in frr7.1 + _advertiseSubnet + _advertiseAllVNI // 63 // 60 in frr8.2 + _localESAdd + _localESDel + _remoteESVTEPAdd // added in frr7.5 + _remoteESVTEPDel // added in frr7.5 + _localESEVIAdd // added in frr7.5 + _localESEVIDel // added in frr7.5 + _vniAdd // 70 + _vniDel + _l3VNIAdd + _l3VNIDel // 73 // 70 in frr8.2 + _remoteVTEPAdd + _remoteVTEPDel + _macIPAdd + _macIPDel + _ipPrefixRouteAdd + _ipPrefixRouteDel + _remoteMACIPAdd // 80 + _remoteMACIPDel + _duplicateAddrDetection + _pwAdd // 83 // 80 in frr8.2 + _pwDelete + _pwSet + _pwUnset + _pwStatusUpdate + _ruleAdd + _ruleDelete + _ruleNotifyOwner // 90 + _tableManagerConnect + _getTableChunk + _releaseTableChunk // 93 // 90 in frr8.2 + _ipSetCreate + _ipSetDestroy + _ipSetEntryAdd + _ipSetEntryDelete + _ipSetNotifyOwner + _ipSetEntryNotifyOwner + _ipTableAdd // 100 + _ipTableDelete + _ipTableNotifyOwner + _vxlanFloodControl // 103 // 100 in frr8.2 + _vxlanSgAdd + _vxlanSgDel + _vxlanSgReplay + _mlagProcessUp // added in frr7.3 + _mlagProcessDown // added in frr7.3 + _mlagClientRegister // added in frr7.3 + _mlagClientUnregister // 110 // added in frr7.3 + _mlagClientForwardMsg // added in frr7.3 + _nhgAdd // added in frr8 + _nhgDel // 113 // 110 in frr8.2 // added in frr8 + _nhgNotifyOwner // added in frr8 + _nhgEvpnRemoteNhAdd // added in frr8 + _nhgEvpnRemoteNhDel // added in frr8 + _srv6LocatorAdd // added in frr8.1 + _srv6LocatorDelete // added in frr8.1 + _srv6ManagerGetLocatorChunk // added in frr8.1 + _srv6ManagerReleaseLocatorChunk // 120 //added in frr8.1 + zebraError // added in frr7.3 + _clientCapabilities // added in frr7.4 + _opaqueMessage // 123 // 120 in frr8.2 // added in frr7.5 + _opaqueRegister // added in frr7.5 + _opaqueUnregister // added in frr7.5 + _neighDiscover // added in frr7.5 + _RouteNotifyRequest // added in frr8 + _ClientCloseNotify // added in frr8 + _NhrpNeighAdded // added in frr8 + _NhrpNeighRemoved // 130 // added in frr8 + _NhrpNeighGet // added in frr8 + _NhrpNeighRegister // added in frr8 + _NhrpNeighUnregister // 133// 130 in frr8.2 // added in frr8 + _NeighIPAdd // added in frr8 + _NeighIPDel // added in frr8 + _ConfigureArp // added in frr8 + _GreGet // added in frr8 + _GreUpdate // added in frr8 + _GreSourceSet // added in frr8 + // BackwardIPv6RouteAdd is referred in zclient_test + BackwardIPv6RouteAdd // quagga, frr3, frr4, frr5 + // BackwardIPv6RouteDelete is referred in zclient_test + BackwardIPv6RouteDelete // quagga, frr3, frr4, frr5 +) + +// Difference default version (frr8.1) and older version +const ( + zapi6Frr8dot2MinDifferentAPIType APIType = 26 //frr8.2(zapi6) + zapi6Frr7dot3MinDifferentAPIType APIType = 49 //frr7.3(zapi6) + zapi6Frr7dot2MinDifferentAPIType APIType = 48 //frr7.2(zapi6) + zapi6Frr6MinDifferentAPIType APIType = 7 //frr6&7.0&7.1(zapi6) + zapi5ClMinDifferentAPIType APIType = 19 //cumuluslinux3.7.7, zebra4.0+cl3u13(zapi5) + zapi5MinDifferentAPIType APIType = 7 //frr4&5(zapi5), frr6&7.0&7.1(zapi6) + zapi4MinDifferentAPIType APIType = 6 + zapi3MinDifferentAPIType APIType = 0 +) + +func minDifferentAPIType(version uint8, software Software) APIType { + if version < 4 { + return zapi3MinDifferentAPIType + } else if version == 4 { + return zapi4MinDifferentAPIType + } else if version == 5 && software.name == "cumulus" { + return zapi5ClMinDifferentAPIType + } else if version == 5 || + (version == 6 && software.name == "frr" && software.version < 7.2) { + return zapi5MinDifferentAPIType + } else if version == 6 && software.name == "frr" && software.version == 7.2 { + return zapi6Frr7dot2MinDifferentAPIType + } else if version == 6 && software.name == "frr" && software.version < 7.5 { + return zapi6Frr7dot3MinDifferentAPIType + } + return zapi6Frr8dot2MinDifferentAPIType +} + +const ( + zapi6Frr8dot2RedistributeRouteAdd APIType = 30 + zapi6Frr8dot2RedistributeRouteDel APIType = 31 + zapi6Frr8dot2VrfLabel APIType = 35 + zapi6Frr8dot2Ipv4NexthopLookupMRIB APIType = 41 + zapi6Frr8dot2LabelManagerConnect APIType = 50 + zapi6Frr8dot2LabelManagerConnectAsync APIType = 51 + zapi6Frr8dot2GetLabelChunk APIType = 52 + zapi6Frr8dot2ReleaseLabelChunk APIType = 53 +) + +var apiTypeZapi6Frr8dot2Map = map[APIType]APIType{ // frr8.2 + redistributeRouteAdd: zapi6Frr8dot2RedistributeRouteAdd, + redistributeRouteDel: zapi6Frr8dot2RedistributeRouteDel, + vrfLabel: zapi6Frr8dot2VrfLabel, + ipv4NexthopLookupMRIB: zapi6Frr8dot2Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi6Frr8dot2LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr8dot2LabelManagerConnectAsync, + getLabelChunk: zapi6Frr8dot2GetLabelChunk, + releaseLabelChunk: zapi6Frr8dot2ReleaseLabelChunk, +} + +const ( + zapi6Frr7dot3LabelManagerConnect APIType = 50 // difference from frr8.1 + zapi6Frr7dot3LabelManagerConnectAsync APIType = 51 // difference from frr8.1 + zapi6Frr7dot3GetLabelChunk APIType = 52 // difference from frr8.1 + zapi6Frr7dot3ReleaseLabelChunk APIType = 53 // difference from frr8.1 +) + +var apiTypeZapi6Frr7dot3Map = map[APIType]APIType{ + labelManagerConnect: zapi6Frr7dot3LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7dot3LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7dot3GetLabelChunk, + releaseLabelChunk: zapi6Frr7dot3ReleaseLabelChunk, +} + +const ( + zapi6Frr7dot2LabelManagerConnect APIType = 49 // difference from frr8.1 + zapi6Frr7dot2LabelManagerConnectAsync APIType = 50 // difference from frr8.1 + zapi6Frr7dot2GetLabelChunk APIType = 51 // difference from frr8.1 + zapi6Frr7dot2ReleaseLabelChunk APIType = 52 // difference from frr8.1 +) + +var apiTypeZapi6Frr7dot2Map = map[APIType]APIType{ + labelManagerConnect: zapi6Frr7dot2LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7dot2GetLabelChunk, + releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk, +} + +const ( // frr7.0, 7.1 + zapi6Frr7RouteAdd APIType = 7 + zapi6Frr7RouteDelete APIType = 8 + zapi6Frr7RedistributAdd APIType = 10 + zapi6Frr7RouterIDAdd APIType = 14 + zapi6Frr7RouterIDUpdate APIType = 16 + zapi6Frr7Hello APIType = 17 + zapi6Frr7NexthopRegister APIType = 19 + zapi6Frr7NexthopUnregister APIType = 20 + zapi6Frr7NexthopUpdate APIType = 21 + zapi6Frr7RedistributeRouteAdd APIType = 32 + zapi6Frr7RedistributeRouteDel APIType = 33 + zapi6Frr7VrfLabel APIType = 37 + zapi6Frr7Ipv4NexthopLookupMRIB APIType = 43 + zapi6Frr7LabelManagerConnect APIType = 48 + zapi6Frr7LabelManagerConnectAsync APIType = 49 + zapi6Frr7GetLabelChunk APIType = 50 + zapi6Frr7ReleaseLabelChunk APIType = 51 +) + +var apiTypeZapi6Frr7Map = map[APIType]APIType{ // frr7.0, 7.1 + RouteAdd: zapi6Frr7RouteAdd, + RouteDelete: zapi6Frr7RouteDelete, + redistributeAdd: zapi6Frr7RedistributAdd, + routerIDAdd: zapi6Frr7RouterIDAdd, + routerIDUpdate: zapi6Frr7RouterIDUpdate, + hello: zapi6Frr7Hello, + nexthopRegister: zapi6Frr7NexthopRegister, + nexthopUnregister: zapi6Frr7NexthopUnregister, + nexthopUpdate: zapi6Frr7NexthopUpdate, + redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd, + redistributeRouteDel: zapi6Frr7RedistributeRouteDel, + vrfLabel: zapi6Frr7VrfLabel, + ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi6Frr7LabelManagerConnect, + labelManagerConnectAsync: zapi6Frr7LabelManagerConnectAsync, + getLabelChunk: zapi6Frr7GetLabelChunk, + releaseLabelChunk: zapi6Frr7ReleaseLabelChunk, +} + +var apiTypeZapi6Frr6Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi6Frr7RedistributAdd, // same as frr7.0&7.1 + routerIDAdd: zapi6Frr7RouterIDAdd, // same as frr7.0&7.1 + routerIDUpdate: zapi6Frr7RouterIDUpdate, // same as frr7.0&7.1 + hello: zapi6Frr7Hello, // same as frr7.0&7.1 + nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1 + nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1 + nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1 + redistributeRouteAdd: redistributeRouteAdd, // same as frr7.2&7.3 + redistributeRouteDel: redistributeRouteDel, // same as frr7.2&7.3 + vrfLabel: vrfLabel, // same as frr7.2&7.3 + ipv4NexthopLookupMRIB: ipv4NexthopLookupMRIB, // same as frr7.2&7.3 + labelManagerConnect: zapi6Frr7dot2LabelManagerConnect, // same as frr7.2 + labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync, // same as frr7.2 + getLabelChunk: zapi6Frr7dot2GetLabelChunk, // same as frr7.2 + releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk, // same as frr7.2 +} + +const ( // For Cumulus Linux 3.7.7, zebra 4.0+cl3u13 (ZAPI version 5) + zapi5ClIpv4NexthopLookupMRIB APIType = 42 + zapi5ClLabelManagerConnect APIType = 47 + zapi5ClGetLabelChunk APIType = 48 + zapi5ClReleaseLabelChunk APIType = 49 +) + +var apiTypeZapi5ClMap = map[APIType]APIType{ + nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1 + nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1 + nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1 + redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd, // same as frr7.0&7.1 + redistributeRouteDel: zapi6Frr7RedistributeRouteDel, // same as frr7.0&7.1 + vrfLabel: zapi6Frr7VrfLabel, // same as frr7.0&7.1 + labelManagerConnect: zapi5ClLabelManagerConnect, + getLabelChunk: zapi5ClGetLabelChunk, + releaseLabelChunk: zapi5ClReleaseLabelChunk, +} + +const ( + zapi5RedistributAdd APIType = 14 + zapi5RouterIDAdd APIType = 18 + zapi5RouterIDUpdate APIType = 20 + zapi5Hello APIType = 21 + zapi5Frr5NexthopRegister APIType = 23 + zapi5Frr5NexthopUnregister APIType = 24 + zapi5Frr5NexthopUpdate APIType = 25 + zapi5Frr5RedistributeRouteAdd APIType = 37 + zapi5Frr5RedistributeRouteDel APIType = 38 + zapi5Frr5VrfLabel APIType = 42 + zapi5Frr5Ipv4NexthopLookupMRIB APIType = 47 + zapi5Frr5LabelManagerConnect APIType = 52 + zapi5Frr5LabelManagerConnectAsync APIType = 53 + zapi5Frr5GetLabelChunk APIType = 54 + zapi5Frr5ReleaseLabelChunk APIType = 55 +) + +var apiTypeZapi5Frr5Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi5RedistributAdd, + routerIDAdd: zapi5RouterIDAdd, + routerIDUpdate: zapi5RouterIDUpdate, + hello: zapi5Hello, + nexthopRegister: zapi5Frr5NexthopRegister, + nexthopUnregister: zapi5Frr5NexthopUnregister, + nexthopUpdate: zapi5Frr5NexthopUpdate, + redistributeRouteAdd: zapi5Frr5RedistributeRouteAdd, + redistributeRouteDel: zapi5Frr5RedistributeRouteDel, + vrfLabel: zapi5Frr5VrfLabel, + ipv4NexthopLookupMRIB: zapi5Frr5Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi5Frr5LabelManagerConnect, + labelManagerConnectAsync: zapi5Frr5LabelManagerConnectAsync, + getLabelChunk: zapi5Frr5GetLabelChunk, + releaseLabelChunk: zapi5Frr5ReleaseLabelChunk, +} + +const ( + zapi5Frr4NexthopRegister APIType = 22 + zapi5Frr4NexthopUnregister APIType = 23 + zapi5Frr4NexthopUpdate APIType = 24 + zapi5Frr4RedistributeRouteAdd APIType = 36 + zapi5Frr4RedistributeRouteDel APIType = 37 + zapi5Frr4Ipv4NexthopLookupMRIB APIType = 45 + zapi5Frr4LabelManagerConnect APIType = 50 + zapi5Frr4GetLabelChunk APIType = 51 + zapi5Frr4ReleaseLabelChunk APIType = 52 +) + +var apiTypeZapi5Frr4Map = map[APIType]APIType{ + RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1 + RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1 + redistributeAdd: zapi5RedistributAdd, + routerIDAdd: zapi5RouterIDAdd, + routerIDUpdate: zapi5RouterIDUpdate, + hello: zapi5Hello, + nexthopRegister: zapi5Frr4NexthopRegister, + nexthopUnregister: zapi5Frr4NexthopUnregister, + nexthopUpdate: zapi5Frr4NexthopUpdate, + redistributeRouteAdd: zapi5Frr4RedistributeRouteAdd, + redistributeRouteDel: zapi5Frr4RedistributeRouteDel, + ipv4NexthopLookupMRIB: zapi5Frr4Ipv4NexthopLookupMRIB, + labelManagerConnect: zapi5Frr4LabelManagerConnect, + getLabelChunk: zapi5Frr4GetLabelChunk, + releaseLabelChunk: zapi5Frr4ReleaseLabelChunk, +} + +const ( + zapi4IPv4RouteAdd APIType = 6 // deleted in zapi6 + zapi4IPv4RouteDelete APIType = 7 // deleted in zapi6 + zapi4IPv6RouteAdd APIType = 8 // deleted in zapi6 + zapi4IPv6RouteDelete APIType = 9 // deleted in zapi6 + zapi4RedistributAdd APIType = 10 + zapi4RouterIDAdd APIType = 14 + zapi4RouterIDUpdate APIType = 16 + zapi4Hello APIType = 17 + zapi4NexthopRegister APIType = 18 + zapi4NexthopUnregister APIType = 19 + zapi4NexthopUpdate APIType = 20 + zapi4RedistributeIPv4Add APIType = 32 // deleted in zapi6 + zapi4RedistributeIPv4Del APIType = 33 // deleted in zapi6 + zapi4RedistributeIPv6Add APIType = 34 // deleted in zapi6 + zapi4RedistributeIPv6Del APIType = 35 // deleted in zapi6 + zapi4LabelManagerConnect APIType = 52 + zapi4GetLabelChunk APIType = 53 + zapi4ReleaseLabelChunk APIType = 54 +) + +var apiTypeZapi4Map = map[APIType]APIType{ + RouteAdd: zapi4IPv4RouteAdd, // deleted in zapi5 + RouteDelete: zapi4IPv4RouteDelete, // deleted in zapi5 + redistributeAdd: zapi4RedistributAdd, + routerIDAdd: zapi4RouterIDAdd, + routerIDUpdate: zapi4RouterIDUpdate, + hello: zapi4Hello, + nexthopRegister: zapi4NexthopRegister, + nexthopUnregister: zapi4NexthopUnregister, + nexthopUpdate: zapi4NexthopUpdate, + redistributeRouteAdd: zapi4RedistributeIPv4Add, // deleted in zapi5 + redistributeRouteDel: zapi4RedistributeIPv4Del, // deleted in zapi5 + ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB, // same as frr7.0&7.1 + labelManagerConnect: zapi4LabelManagerConnect, + getLabelChunk: zapi4GetLabelChunk, + releaseLabelChunk: zapi4ReleaseLabelChunk, + BackwardIPv6RouteAdd: zapi4IPv6RouteAdd, + BackwardIPv6RouteDelete: zapi4IPv6RouteDelete, +} + +const ( + zapi3InterfaceAdd APIType = 1 + zapi3InterfaceDelete APIType = 2 + zapi3InterfaceAddressAdd APIType = 3 + zapi3InterfaceAddressDelete APIType = 4 + zapi3InterfaceUp APIType = 5 + zapi3InterfaceDown APIType = 6 + zapi3IPv4RouteAdd APIType = 7 // deleted in zapi5 + zapi3IPv4RouteDelete APIType = 8 // deleted in zapi5 + zapi3IPv6RouteAdd APIType = 9 // deleted in zapi5 + zapi3IPv6RouteDelete APIType = 10 // deleted in zapi5 + zapi3RedistributeAdd APIType = 11 + zapi3IPv4NexthopLookup APIType = 15 // zapi3(quagga) only + zapi3IPv6NexthopLookup APIType = 16 // zapi3(quagga) only + zapi3IPv4ImportLookup APIType = 17 // zapi3(quagga) only + zapi3RouterIDAdd APIType = 20 + zapi3RouterIDUpdate APIType = 22 + zapi3Hello APIType = 23 + zapi3Ipv4NexthopLookupMRIB APIType = 24 + zapi3NexthopRegister APIType = 27 + zapi3NexthopUnregister APIType = 28 + zapi3NexthopUpdate APIType = 29 +) + +var apiTypeZapi3Map = map[APIType]APIType{ + interfaceAdd: zapi3InterfaceAdd, + interfaceDelete: zapi3InterfaceDelete, + interfaceAddressAdd: zapi3InterfaceAddressAdd, + interfaceAddressDelete: zapi3InterfaceAddressDelete, + interfaceUp: zapi3InterfaceUp, + interfaceDown: zapi3InterfaceDown, + RouteAdd: zapi3IPv4RouteAdd, // deleted in zapi5 + RouteDelete: zapi3IPv4RouteDelete, // deleted in zapi5 + redistributeAdd: zapi3RedistributeAdd, + routerIDAdd: zapi3RouterIDAdd, + routerIDUpdate: zapi3RouterIDUpdate, + hello: zapi3Hello, + nexthopRegister: zapi3NexthopRegister, + nexthopUnregister: zapi3NexthopUnregister, + nexthopUpdate: zapi3NexthopUpdate, + BackwardIPv6RouteAdd: zapi3IPv6RouteAdd, + BackwardIPv6RouteDelete: zapi3IPv6RouteDelete, +} + +func (t APIType) doesNeedConversion(version uint8, software Software) bool { + if (version == 6 && software.name == "frr" && + software.version >= 7.5 && software.version < 8.2) || + t < minDifferentAPIType(version, software) { + return false + } + return true +} +func apiTypeMap(version uint8, software Software) map[APIType]APIType { + if version == 6 && software.name == "frr" && software.version >= 7.3 && software.version < 7.5 { + return apiTypeZapi6Frr7dot3Map + } else if version == 6 && software.name == "frr" && software.version == 7.2 { + return apiTypeZapi6Frr7dot2Map + } else if version == 6 && software.name == "frr" && software.version >= 7 && software.version < 7.2 { + return apiTypeZapi6Frr7Map + } else if version == 6 && software.name == "frr" && software.version >= 6 && software.version < 7 { + return apiTypeZapi6Frr6Map + } else if version == 5 { + if software.name == "frr" && software.version == 4 { + return apiTypeZapi5Frr4Map + } else if software.name == "cumulus" { + return apiTypeZapi5ClMap + } + return apiTypeZapi5Frr5Map + } else if version == 4 { + return apiTypeZapi4Map + } else if version < 4 { + return apiTypeZapi3Map + } + return apiTypeZapi6Frr8dot2Map +} + +// ToEach is referred in zclient_test +func (t APIType) ToEach(version uint8, software Software) APIType { + if !t.doesNeedConversion(version, software) { + return t + } + apiMap := apiTypeMap(version, software) + backward, ok := apiMap[t] + if !ok { + backward = zebraError // fail to convert and error value + } + return backward // success to convert +} +func (t APIType) toCommon(version uint8, software Software) APIType { + if !t.doesNeedConversion(version, software) { + return t + } + apiMap := apiTypeMap(version, software) + for common, backward := range apiMap { + if backward == t { + return common // success to convert + } + } + return zebraError // fail to convert and error value +} + +func (t APIType) addressFamily(version uint8) uint8 { + if version == 4 { + switch t { + case zapi4IPv4RouteAdd, zapi4IPv4RouteDelete, zapi4RedistributeIPv4Add, zapi4RedistributeIPv4Del, zapi6Frr7Ipv4NexthopLookupMRIB: + return syscall.AF_INET + case zapi4IPv6RouteAdd, zapi4IPv6RouteDelete, zapi4RedistributeIPv6Add, zapi4RedistributeIPv6Del: + return syscall.AF_INET6 + } + } else if version < 4 { + switch t { + case zapi3IPv4RouteAdd, zapi3IPv4RouteDelete, zapi3IPv4NexthopLookup, zapi3IPv4ImportLookup, zapi3Ipv4NexthopLookupMRIB: + return syscall.AF_INET + case zapi3IPv6RouteAdd, zapi3IPv6RouteDelete, zapi3IPv6NexthopLookup: + return syscall.AF_INET6 + } + } + return syscall.AF_UNSPEC +} + +// RouteType is referred in zclient. +// +//go:generate stringer -type=RouteType +type RouteType uint8 + +// For FRRouting version 7 (ZAPI version 6). +const ( + routeSystem RouteType = iota //0 + routeKernel + routeConnect + RouteStatic + routeRIP + routeRIPNG + routeOSPF + routeOSPF6 + routeISIS + RouteBGP + routePIM // 10 + routeEIGRP // FRRRouting version 4 (Zapi5) adds. + routeNHRP + routeHSLS + routeOLSR + routeTABLE + routeLDP + routeVNC + routeVNCDirect + routeVNCDirectRH + routeBGPDirect + routeBGPDirectEXT + routeBABEL + routeSHARP + routePBR // FRRRouting version 5 (Zapi5) adds. + routeBFD // FRRRouting version 6 (Zapi6) adds. + routeOpenfabric // FRRRouting version 7 (Zapi6) adds. + routeVRRP // FRRRouting version 7.2 (Zapi6) adds. + routeNHG // FRRRouting version 7.3 (Zapi6) adds. + routeSRTE // FRRRouting version 7.5 (Zapi6) adds. + routeAll + routeMax // max value for error +) +const ( + zapi5Frr4RouteAll RouteType = 24 + zapi5Frr5RouteAll RouteType = 25 + zapi6Frr6RouteAll RouteType = 26 + zapi6Frr7RouteAll RouteType = 27 + zapi6Frr7dot2RouteAll RouteType = 28 + zapi6Frr7dot3RouteAll RouteType = 29 +) + +func getRouteAll(version uint8, software Software) RouteType { + if version == 5 { + if software.name == "frr" && software.version == 4 { + return zapi5Frr4RouteAll + } + return zapi5Frr5RouteAll + } else if version == 6 { + if software.name == "frr" && software.version == 6 { + return zapi6Frr6RouteAll + } else if software.name == "frr" && software.version >= 7 && software.version < 7.2 { + return zapi6Frr7RouteAll + } else if software.name == "frr" && software.version >= 7.2 && software.version < 7.3 { + return zapi6Frr7dot2RouteAll + } else if software.name == "frr" && software.version >= 7.3 && software.version < 7.5 { + return zapi6Frr7dot3RouteAll + } + } + return routeAll +} + +// For FRRouting version 3.0 except common route type. +const ( + zapi4RouteNHRP RouteType = iota + routePIM + 1 + zapi4RouteHSLS + zapi4RouteOLSR + zapi4RouteTABLE + zapi4RouteLDP + zapi4RouteVNC + zapi4RouteVNCDirect + zapi4RouteVNCDirectRH + zapi4RouteBGPDixrect + zapi4RouteBGPDirectEXT + zapi4RouteAll +) + +var routeTypeZapi4Map = map[RouteType]RouteType{ + routeNHRP: zapi4RouteNHRP, + routeHSLS: zapi4RouteHSLS, + routeOLSR: zapi4RouteOLSR, + routeTABLE: zapi4RouteTABLE, + routeLDP: zapi4RouteLDP, + routeVNC: zapi4RouteVNC, + routeVNCDirect: zapi4RouteVNCDirect, + routeVNCDirectRH: zapi4RouteVNCDirectRH, + routeBGPDirect: zapi4RouteBGPDixrect, + routeBGPDirectEXT: zapi4RouteBGPDirectEXT, + routeAll: zapi4RouteAll, +} + +// For Quagga except common route type. +const ( + zapi3RouteHSLS RouteType = iota + routePIM + 1 + zapi3RouteOLSR + zapi3RouteBABEL + zapi3RouteNHRP // quagga 1.2.4 +) + +var routeTypeZapi3Map = map[RouteType]RouteType{ + routeHSLS: zapi3RouteHSLS, + routeOLSR: zapi3RouteOLSR, + routeBABEL: zapi3RouteBABEL, + routeNHRP: zapi3RouteNHRP, +} + +func (t RouteType) toEach(version uint8) RouteType { + if t <= routePIM || version > 4 { // not need to convert + return t + } + routeTypeMap := routeTypeZapi4Map + if version < 4 { + routeTypeMap = routeTypeZapi3Map + } + backward, ok := routeTypeMap[t] + if ok { + return backward // success to convert + } + return routeMax // fail to convert and error value +} + +var routeTypeValueMap = map[string]RouteType{ + "system": routeSystem, + "kernel": routeKernel, + "connect": routeConnect, // hack for backward compatibility + "directly-connected": routeConnect, + "static": RouteStatic, + "rip": routeRIP, + "ripng": routeRIPNG, + "ospf": routeOSPF, + "ospf3": routeOSPF6, + "isis": routeISIS, + "bgp": RouteBGP, + "pim": routePIM, + "eigrp": routeEIGRP, // added in frr4(zapi5) + "nhrp": routeNHRP, + "hsls": routeHSLS, + "olsr": routeOLSR, + "table": routeTABLE, + "ldp": routeLDP, + "vnc": routeVNC, + "vnc-direct": routeVNCDirect, + "vnc-rn": routeVNCDirectRH, + "bgp-direct": routeBGPDirect, + "bgp-direct-to-nve-groups": routeBGPDirectEXT, + "babel": routeBABEL, + "sharp": routeSHARP, + "pbr": routePBR, + "bfd": routeBFD, + "openfabric": routeOpenfabric, // added in frr7.0(zapi6) + "vrrp": routeVRRP, // added in frr7.2(zapi6) + "nhg": routeNHG, // added in frr7.3(zapi6) + "srte": routeSRTE, // added in frr7.5(zapi6) + "wildcard": routeAll, +} + +// RouteTypeFromString converts from string to route type +func RouteTypeFromString(typ string, version uint8, software Software) (RouteType, error) { + t, ok := routeTypeValueMap[typ] + if !ok { // failed to lookup RouteType from string + return t, fmt.Errorf("unknown route type: %s in version: %d (%s)", typ, version, software.string()) + } + t = t.toEach(version) //when lookup failes return routeMax + if t > getRouteAll(version, software) { + return t, fmt.Errorf("unknown route type: %d in version: %d (%s)", t, version, software.string()) + } + return t, nil // Success +} + +func addressByteLength(family uint8) (int, error) { + switch family { + case syscall.AF_INET: + return net.IPv4len, nil + case syscall.AF_INET6: + return net.IPv6len, nil + } + return 0, fmt.Errorf("unknown address family: %d", family) +} + +func ipFromFamily(family uint8, buf []byte) net.IP { + switch family { + case syscall.AF_INET: + return net.IP(buf).To4() + case syscall.AF_INET6: + return net.IP(buf).To16() + } + return nil +} + +// MESSAGE_FLAG is 32bit in frr7.5 and after frr7.5, 8bit in frr 7.4 and before frr7.4 +// MessageFlag is the type of API Message Flags. +type MessageFlag uint32 + +const ( // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6). + // MessageNexthop is referred in zclient + MessageNexthop MessageFlag = 0x01 + // MessageDistance is referred in zclient_test + MessageDistance MessageFlag = 0x02 + // MessageMetric is referred in zclient + MessageMetric MessageFlag = 0x04 + messageTag MessageFlag = 0x08 + // MessageMTU is referred in zclient_test + MessageMTU MessageFlag = 0x10 + messageSRCPFX MessageFlag = 0x20 + // MessageLabel is referred in zclient + MessageLabel MessageFlag = 0x40 // deleted in frr7.3 + messageBackupNexthops MessageFlag = 0x40 // added in frr7.4 + messageNhg MessageFlag = 0x80 // added in frr8 + messageTableID MessageFlag = 0x100 // frr8: 0x100, frr5&6&7.x: 0x80 + messageSRTE MessageFlag = 0x200 // frr8: 0x200, frr7.5: 0x100 + messageOpaque MessageFlag = 0x400 // introduced in frr8 +) + +const ( // For FRRouting. + messageIFIndex MessageFlag = 0x02 + zapi4MessageDistance MessageFlag = 0x04 + zapi4MessageMetric MessageFlag = 0x08 + zapi4MessageTag MessageFlag = 0x10 + zapi4MessageMTU MessageFlag = 0x20 + zapi4MessageSRCPFX MessageFlag = 0x40 +) + +const ( // For Quagga. + zapi3MessageMTU MessageFlag = 0x10 + zapi3MessageTag MessageFlag = 0x20 +) + +// ToEach is referred in zclient +func (f MessageFlag) ToEach(version uint8, software Software) MessageFlag { + if version > 4 { //zapi version 5, 6 + if f > messageNhg && (version == 5 || + (version == 6 && software.name == "frr" && software.version < 8)) { // except frr8 + return f >> 1 + } + return f + } + if version < 4 { //zapi version 3, 2 + switch f { + case MessageMTU: + return zapi3MessageMTU + case messageTag: + return zapi3MessageTag + } + } + switch f { //zapi version 4 + case MessageDistance, MessageMetric, messageTag, MessageMTU, messageSRCPFX: + return f << 1 + } + return f +} +func (f MessageFlag) string(version uint8, software Software) string { + var ss []string + if f&MessageNexthop > 0 { + ss = append(ss, "NEXTHOP") + } + if version < 4 && f&messageIFIndex > 0 { + ss = append(ss, "IFINDEX") + } + if f&MessageDistance.ToEach(version, software) > 0 { + ss = append(ss, "DISTANCE") + } + if f&MessageMetric.ToEach(version, software) > 0 { + ss = append(ss, "METRIC") + } + if f&MessageMTU.ToEach(version, software) > 0 { + ss = append(ss, "MTU") + } + if f&messageTag.ToEach(version, software) > 0 { + ss = append(ss, "TAG") + } + if version > 3 && f&messageSRCPFX.ToEach(version, software) > 0 { + ss = append(ss, "SRCPFX") + } + if version == 6 && software.name == "frr" && software.version >= 7.4 && f&messageBackupNexthops > 0 { // added in frr7.4, frr7.5 + ss = append(ss, "BACKUP_NEXTHOPS") + } else if version > 4 && f&MessageLabel > 0 { + ss = append(ss, "LABEL") + } + if version > 6 && software.name == "frr" && software.version >= 8 && f&messageNhg > 0 { // added in frr8 + ss = append(ss, "NHG") + } + if version > 5 && f&messageTableID > 0 { + ss = append(ss, "TABLEID") + } + if version == 6 && software.name == "frr" && software.version >= 7.5 && f&messageSRTE > 0 { // added in frr7.5 + ss = append(ss, "SRTE") + } + if version > 6 && software.name == "frr" && software.version >= 8 && f&messageOpaque > 0 { // added in frr8 + ss = append(ss, "OPAQUE") + } + return strings.Join(ss, "|") +} + +// Flag is Message Flag which is referred in zclient +type Flag uint64 + +const ( // For FRRouting version 7 (zebra API version 6), these are defined in lib/zclient.h + // FlagAllowRecursion is referred in zclient, and it is renamed from ZEBRA_FLAG_INTERNAL (https://github.com/FRRouting/frr/commit/4e8b02f4df5d6bcfde6390955b8feda2a17dc9bd) + FlagAllowRecursion Flag = 0x01 // quagga, frr3, frr4, frr5, frr6, frr7 + flagSelfRoute Flag = 0x02 // quagga, frr3, frr4, frr5, frr6, frr7 + // FlagIBGP is referred in zclient + FlagIBGP Flag = 0x04 + // FlagSelected referred in zclient_test + FlagSelected Flag = 0x08 + flagFIBOverride Flag = 0x10 + flagEvpnRoute Flag = 0x20 + flagRRUseDistance Flag = 0x40 + flagOnlink Flag = 0x80 // frr7.0 only, this vale is deleted in frr7.1 + flagTrapped Flag = 0x80 // added in frr8 + flagOffloaded Flag = 0x100 // added in frr8 + flagOffloadFailed Flag = 0x200 // added in frr8 +) + +// For Quagga (ZAPI v2, v3), FRR v3 (ZAPI v4), FRR v4, v5 (ZAPI v5), FRR v6 (ZAPI v6) for backward compatibility +const ( + flagBlackhole Flag = 0x04 // quagga, frr3 + flagStatic Flag = 0x40 // quagga, frr3, frr4, frr5, frr6 + flagReject Flag = 0x80 // quagga, frr3 + flagScopeLink Flag = 0x100 // frr4, frr5, frr6 +) + +// ToEach is referred in zclient +func (f Flag) ToEach(version uint8, software Software) Flag { + if (version == 6 && software.name == "frr" && software.version >= 7) || (f < FlagIBGP) || f > flagRRUseDistance { + return f + } + switch f { + case FlagIBGP, FlagSelected: // 0x04->0x08,0x08->0x10(quagga, frr3,4,5,6) + return f << 1 + case flagEvpnRoute, flagRRUseDistance: // 0x20->0x400,0x40->0x800(frr4,5,6) + return f << 5 + case flagFIBOverride: + if version < 4 { + return f << 1 // 0x10->0x20(quagga) + } + return f << 5 // 0x10->0x200(frr3, frr4, frr5, frr6) + } + return f +} + +// String is referred in zclient +func (f Flag) String(version uint8, software Software) string { + var ss []string + // common flag + if f&FlagAllowRecursion > 0 { + ss = append(ss, "FLAG_ALLOW_RECURSION") + } + if f&flagSelfRoute > 0 { + ss = append(ss, "FLAG_SELFROUTE") + } + if f&FlagIBGP.ToEach(version, software) > 0 { + ss = append(ss, "FLAG_IBGP") + } + if f&FlagSelected.ToEach(version, software) > 0 { + ss = append(ss, "FLAG_SELECTED") + } + if f&flagEvpnRoute.ToEach(version, software) > 0 { + ss = append(ss, "FLAG_EVPN_ROUTE") + } + if f&flagRRUseDistance.ToEach(version, software) > 0 { + ss = append(ss, "FLAG_RR_USE_DISTANCE") + } + if f&flagFIBOverride.ToEach(version, software) > 0 { + ss = append(ss, "FLAG_FIB_OVERRIDE") + } + if version == 6 && software.name == "frr" && software.version >= 7 && f&flagOnlink > 0 { // frr7.0 only + ss = append(ss, "FLAG_ONLINK") + } + if version == 6 && software.name == "frr" && software.version >= 8 && f&flagTrapped > 0 { // added in frr8 + ss = append(ss, "FLAG_TRAPPED") + } + if f&flagOffloaded > 0 { // added in frr8 + ss = append(ss, "FLAG_OFFLOADED") + } + if f&flagOffloadFailed > 0 { // added in frr8 + ss = append(ss, "FLAG_OFFLOADFAILED") + } + if (version < 6 || (version == 6 && software.name == "frr" && software.version < 7)) && f&flagStatic > 0 { + ss = append(ss, "FLAG_STATIC") // quagga, frr3, frr4, frr5, frr6 + } + if version < 5 && f&flagBlackhole > 0 { // quagga, frr3 + ss = append(ss, "FLAG_BLACKHOLE") + } + if version < 5 && f&flagReject > 0 { // quagga, frr3 + ss = append(ss, "FLAG_REJECT") + } + if (version == 5 || (version == 6 && software.name == "frr" && software.version < 7)) && f&flagScopeLink > 0 { + ss = append(ss, "FLAG_SCOPE_LINK") // frr4, frr5, frr6 + } + return strings.Join(ss, "|") +} + +// Nexthop Types. +// +//go:generate stringer -type=nexthopType +type nexthopType uint8 + +// For FRRouting. +const ( + _ nexthopType = iota + nexthopTypeIFIndex // 1 + nexthopTypeIPv4 // 2 + nexthopTypeIPv4IFIndex // 3 + nexthopTypeIPv6 // 4 + nexthopTypeIPv6IFIndex // 5 + nexthopTypeBlackhole // 6 +) + +// For Quagga. +const ( + nexthopTypeIFName nexthopType = iota + 2 // 2 + backwardNexthopTypeIPv4 // 3 + backwardNexthopTypeIPv4IFIndex // 4 + nexthopTypeIPv4IFName // 5 + backwardNexthopTypeIPv6 // 6 + backwardNexthopTypeIPv6IFIndex // 7 + nexthopTypeIPv6IFName // 8 + backwardNexthopTypeBlackhole // 9 +) + +var nexthopTypeMap = map[nexthopType]nexthopType{ + nexthopTypeIPv4: backwardNexthopTypeIPv4, // 2 -> 3 + nexthopTypeIPv4IFIndex: backwardNexthopTypeIPv4IFIndex, // 3 -> 4 + nexthopTypeIPv6: backwardNexthopTypeIPv6, // 4 -> 6 + nexthopTypeIPv6IFIndex: backwardNexthopTypeIPv6IFIndex, // 5 -> 7 + nexthopTypeBlackhole: backwardNexthopTypeBlackhole, // 6 -> 9 +} + +func (t nexthopType) toEach(version uint8) nexthopType { + if version > 3 { // frr + return t + } + if t == nexthopTypeIFIndex || t > nexthopTypeBlackhole { // 1 (common), 7, 8, 9 (out of map range) + return t + } + backward, ok := nexthopTypeMap[t] + if ok { + return backward // converted value + } + return nexthopType(0) // error for conversion +} + +func (t nexthopType) ipToIPIFIndex() nexthopType { + // process of nexthopTypeIPv[4|6] is same as nexthopTypeIPv[4|6]IFIndex + // in IPRouteBody of frr7.3 and NexthoUpdate of frr + if t == nexthopTypeIPv4 { + return nexthopTypeIPv4IFIndex + } else if t == nexthopTypeIPv6 { + return nexthopTypeIPv6IFIndex + } + return t +} +func (t nexthopType) ifNameToIFIndex() nexthopType { // quagga + if t == nexthopTypeIFName { + return nexthopTypeIFIndex + } else if t == nexthopTypeIPv4IFName { + return backwardNexthopTypeIPv4IFIndex + } else if t == nexthopTypeIPv6IFName { + return backwardNexthopTypeIPv6IFIndex + } + return t +} + +// Nexthop Flags. +// +//go:generate stringer -type=nexthopFlag +type nexthopFlag uint8 + +const ( + nexthopFlagActive nexthopFlag = 0x01 // This nexthop is alive. + nexthopFlagFIB nexthopFlag = 0x02 // FIB nexthop. + nexthopFlagRecursive nexthopFlag = 0x04 // Recursive nexthop. + nexthopFlagOnlink nexthopFlag = 0x08 // Nexthop should be installed onlink. + nexthopFlagDuplicate nexthopFlag = 0x10 // nexthop duplicates (frr8, 7.5, 7.4) + nexthopFlagRnhFiltered nexthopFlag = 0x20 // nexthop duplicates (frr8, 7.5, 7.4) + nexthopFlagHasBackup nexthopFlag = 0x40 // nexthop duplicates (frr8, 7.5, 7.4) + nexthopFlagSRTE nexthopFlag = 0x80 // nexthop duplicates (frr8, 7.5) +) +const ( + // Already matched vs a nexthop (frr7.3, 7.2, 7.1, 7, 6, 5, 4, 3) (zapi version >= 4) + zapi6Frr7dot3nexthopFlagMatched nexthopFlag = 0x10 + // nexthop duplicates (frr7.3, 7.2, 7.1) + zapi6Frr7dot3nexthopFlagDuplicate nexthopFlag = 0x20 + // nexthop duplicates (frr7.3, 7.2, 7.1) + zapi6Frr7dot3nexthopFlagRnhFiltered nexthopFlag = 0x40 +) +const ( + // rmap filtered (frr7, 6, 5, 4, 3)(zapi version >= 4) + zapi6Frr7nexthopFlagFiltered nexthopFlag = 0x20 + // nexthop duplicates (frr7, 6, 5, 4)(version >= 5) + zapi6Frr7nexthopFlagDuplicate nexthopFlag = 0x40 + // Evpn remote vtep nexthop (frr7, 6, 5, 4)(version >= 5) + zapi6Frr7nexthopFlagEvpnRvtep nexthopFlag = 0x80 +) + +// Interface PTM Enable Configuration. +// +//go:generate stringer -type=ptmEnable +type ptmEnable uint8 + +const ( + ptmEnableOff ptmEnable = 0 + ptmEnableOn ptmEnable = 1 + ptmEnableUnspec ptmEnable = 2 +) + +// PTM Status. +// +//go:generate stringer -type=ptmStatus +type ptmStatus uint8 + +const ( + ptmStatusDown ptmStatus = 0 + ptmStatusUp ptmStatus = 1 + ptmStatusUnknown ptmStatus = 2 +) + +const ( + defaultZebraSoftwareName string = "frr" + defaultZapi5SoftwareVersion float64 = 5 // FRR software version for Zapi5 + defaultZapi6SoftwareVersion float64 = 8.1 // FRR software version for Zapi6 +) + +// Software is zebra software (quagga, frr, cumulus) which is referred in zclient +type Software struct { + name string + version float64 +} + +// string returns combined string with name and version in Software structure +func (software *Software) string() string { + return fmt.Sprintf("%s%f", software.name, software.version) +} + +// NewSoftware is constructor of Software strucuture +func NewSoftware(version uint8, softwareName string) Software { + regex := regexp.MustCompile(`([a-z]*)(\d*\.?\d*)`) + regexResult := regex.FindAllStringSubmatch(softwareName, -1) + software := Software{regexResult[0][1], defaultZapi6SoftwareVersion} + var err error + software.version, err = strconv.ParseFloat(regexResult[0][2], 64) + if err != nil || (software.name != "cumulus" && version >= 5) { + software.name = defaultZebraSoftwareName + if version == 5 && software.version < 4 && software.version >= 6 { + software.version = defaultZapi5SoftwareVersion + } else if version == 6 && software.version < 6 { + software.version = defaultZapi6SoftwareVersion + } + } + return software +} + +// Client is zebra client which is referred in zclient +type Client struct { + outgoing chan *Message + incoming chan *Message + redistDefault RouteType + conn net.Conn + Version uint8 + Software Software + logger log.Logger +} + +// NewClient returns a Client instance (Client constructor) +func NewClient(logger log.Logger, network, address string, typ RouteType, version uint8, software Software, mplsLabelRangeSize uint32) (*Client, error) { + conn, err := net.Dial(network, address) + if err != nil { + return nil, err + } + outgoing := make(chan *Message) + incoming := make(chan *Message, 64) + if version < MinZapiVer { + version = MinZapiVer + } else if version > MaxZapiVer { + version = MaxZapiVer + } + c := &Client{ + outgoing: outgoing, + incoming: incoming, + redistDefault: typ, + conn: conn, + Version: version, + Software: software, + logger: logger, + } + + go func() { + for { + m, more := <-outgoing + if more { + b, err := m.serialize(software) + if err != nil { + logger.Warn(fmt.Sprintf("failed to serialize: %v", m), + log.Fields{ + "Topic": "Zebra"}) + continue + } + + _, err = conn.Write(b) + if err != nil { + logger.Error("failed to write", + log.Fields{ + "Topic": "Zebra", + "Error": err}) + closeChannel(outgoing) + return + } + } else { + logger.Debug("finish outgoing loop", + log.Fields{"Topic": "Zebra"}) + return + } + } + }() + + // Send Hello/RouterIDAdd messages to negotiate the Zebra message version. + c.SendHello() + c.SendRouterIDAdd() + + if mplsLabelRangeSize > 0 && c.SupportMpls() { + c.sendLabelManagerConnect(true) + } + + receiveSingleMsg := func() (*Message, error) { + headerBuf, err := readAll(conn, int(HeaderSize(version))) + if err != nil { + logger.Error("failed to read header", + log.Fields{ + "Topic": "Zebra", + "Error": err}) + return nil, err + } + + hd := &Header{} + err = hd.decodeFromBytes(headerBuf) + if c.Version != hd.Version { + logger.Warn(fmt.Sprintf("ZAPI version mismatch. configured version: %d, version of received message:%d", c.Version, hd.Version), + log.Fields{ + "Topic": "Zebra"}) + return nil, errors.New("ZAPI version mismatch") + } + if err != nil { + logger.Error("failed to decode header", + log.Fields{ + "Topic": "Zebra", + "Data": headerBuf, + "Error": err}) + return nil, err + } + + bodyBuf, err := readAll(conn, int(hd.Len-HeaderSize(version))) + if err != nil { + logger.Error("failed to read body", + log.Fields{ + "Topic": "Zebra", + "Header": hd, + "Error": err}) + return nil, err + } + + m, err := parseMessage(hd, bodyBuf, software) + if err != nil { + // Just outputting warnings (not error message) and ignore this + // error considering the case that body parser is not implemented yet. + logger.Warn("failed to decode body", + log.Fields{ + "Topic": "Zebra", + "Header": hd, + "Data": bodyBuf, + "Error": err}) + return nil, nil + } + logger.Debug("read message from zebra", + log.Fields{ + "Topic": "Zebra", + "Message": m}) + + return m, nil + } + + // Try to receive the first message from Zebra. + if m, err := receiveSingleMsg(); err != nil { + c.close() + // Return error explicitly in order to retry connection. + return nil, err + } else if m != nil { + incoming <- m + } + + // Start receive loop only when the first message successfully received. + go func() { + defer close(incoming) + for { + if m, err := receiveSingleMsg(); err != nil { + return + } else if m != nil { + incoming <- m + } + } + }() + + return c, nil +} + +func readAll(conn net.Conn, length int) ([]byte, error) { + buf := make([]byte, length) + _, err := io.ReadFull(conn, buf) + return buf, err +} + +// Receive return incoming channel message +func (c *Client) Receive() chan *Message { + return c.incoming +} + +func (c *Client) send(m *Message) { + defer func() { + if err := recover(); err != nil { + c.logger.Debug("recovered", + log.Fields{ + "Topic": "Zebra", + "Error": err}) + } + }() + c.logger.Debug("send command to zebra", + log.Fields{ + "Topic": "Zebra", + "Header": m.Header, + "Body": m.Body}) + c.outgoing <- m +} + +func (c *Client) sendCommand(command APIType, vrfID uint32, body Body) error { + m := &Message{ + Header: Header{ + Len: HeaderSize(c.Version), + Marker: HeaderMarker(c.Version), + Version: c.Version, + VrfID: vrfID, + Command: command.ToEach(c.Version, c.Software), + }, + Body: body, + } + c.send(m) + return nil +} + +// SendHello sends HELLO message to zebra daemon. +func (c *Client) SendHello() error { + if c.redistDefault > 0 { + body := &helloBody{ + redistDefault: c.redistDefault, + instance: 0, + } + return c.sendCommand(hello, DefaultVrf, body) + } + return nil +} + +// SendRouterIDAdd sends ROUTER_ID_ADD message to zebra daemon. +func (c *Client) SendRouterIDAdd() error { + bodies := make([]*routerIDUpdateBody, 0) + for _, afi := range []afi{afiIP, afiIP6} { + bodies = append(bodies, &routerIDUpdateBody{ + afi: afi, + }) + } + for _, body := range bodies { + c.sendCommand(routerIDAdd, DefaultVrf, body) + } + return nil +} + +// SendInterfaceAdd sends INTERFACE_ADD message to zebra daemon. +func (c *Client) SendInterfaceAdd() error { + return c.sendCommand(interfaceAdd, DefaultVrf, nil) +} + +// SendRedistribute sends REDISTRIBUTE message to zebra daemon. +func (c *Client) SendRedistribute(t RouteType, vrfID uint32) error { + if c.redistDefault != t { + bodies := make([]*redistributeBody, 0) + if c.Version <= 3 { + bodies = append(bodies, &redistributeBody{ + redist: t, + }) + } else { // Version >= 4 + for _, afi := range []afi{afiIP, afiIP6} { + bodies = append(bodies, &redistributeBody{ + afi: afi, + redist: t, + instance: 0, + }) + } + } + + for _, body := range bodies { + c.sendCommand(redistributeAdd, vrfID, body) + } + } + return nil +} + +// SendIPRoute sends ROUTE message to zebra daemon. +func (c *Client) SendIPRoute(vrfID uint32, body *IPRouteBody, isWithdraw bool) error { + routeFamily := body.RouteFamily(c.logger, c.Version, c.Software) + if vrfID == DefaultVrf && (routeFamily == bgp.RF_IPv4_VPN || routeFamily == bgp.RF_IPv6_VPN) { + return fmt.Errorf("RF_IPv4_VPN or RF_IPv6_VPN are not suitable for Default VRF (default forwarding table)") + } + command := RouteAdd + if isWithdraw { + command = RouteDelete + } + if c.Version < 5 && familyFromPrefix(body.Prefix.Prefix) == syscall.AF_INET6 { + command = BackwardIPv6RouteAdd + if isWithdraw { + command = BackwardIPv6RouteDelete + } + } + return c.sendCommand(command, vrfID, body) +} + +// SendNexthopRegister sends NEXTHOP_REGISTER message to zebra daemon. +func (c *Client) SendNexthopRegister(vrfID uint32, body *NexthopRegisterBody, isWithdraw bool) error { + // Note: NexthopRegister and NexthopUnregister messages are not + // supported in Zebra protocol version<3. + if c.Version < 3 { + return fmt.Errorf("NexthopRegister/NexthopUnregister are not supported in version: %d", c.Version) + } + command := nexthopRegister + if isWithdraw { + command = nexthopUnregister + } + return c.sendCommand(command, vrfID, body) +} + +// SupportMpls is referred in zclient. It returns bool value. +func (c *Client) SupportMpls() bool { + // Note: frr3&4 have LABEL_MANAGER_CONNECT& GET_LABEL_CHUNK. However + // Routes will not be installed via zebra of frr3&4 after call these APIs. + if c.Version < 5 || (c.Software.name == "frr" && c.Software.version == 4) { + return false // if frr4 or earlier are used + } + return true // if frr5 or later are used +} + +// Ref: zread_label_manager_connect in zebra/zserv.c of FRR3 (ZAPI4) +// Ref: zread_label_manager_connect in zebra/zapi_msg.c of FRR5&6 (ZAPI5&6) +func (c *Client) sendLabelManagerConnect(async bool) error { + if c.Version < 4 { + return fmt.Errorf("LabelManagerConnect is not supported in zebra API version: %d", c.Version) + } + command := labelManagerConnectAsync + // FRR version 4 (ZAPI version 5) and FRR version 3 (ZAPI version 4) + if !async || c.Version == 4 || (c.Version == 5 && c.Software.name == "frr" && c.Software.version < 5) { + command = labelManagerConnect + } + return c.sendCommand( + command, 0, + &labelManagerConnectBody{ + redistDefault: RouteBGP, + instance: 0, + }) +} + +// SendGetLabelChunk sends GET_LABEL_CHUNK message to zebra daemon. +func (c *Client) SendGetLabelChunk(body *GetLabelChunkBody) error { + if c.Version < 4 { + return fmt.Errorf("GetLabelChunk is not supported in version: %d", c.Version) + } + body.instance = 0 + body.proto = uint8(RouteBGP) + return c.sendCommand(getLabelChunk, 0, body) +} + +// SendVrfLabel sends VRF_LABEL message to zebra daemon. +func (c *Client) SendVrfLabel(label uint32, vrfID uint32) error { + // ZAPIv5 has ZEBRA_VRF_LABEL, however frr4 (ZAPIv5) doesn't have it. + if c.Version < 5 || (c.Version == 5 && c.Software.name == "frr" && c.Software.version < 5) { + return fmt.Errorf("VrfLabel is not supported in zebra API version: %d software: %s", c.Version, c.Software.string()) + } + body := &vrfLabelBody{ + label: label, + afi: afiIP, + labelType: lspBGP, + } + return c.sendCommand(vrfLabel, vrfID, body) +} + +// for avoiding double close +func closeChannel(ch chan *Message) bool { + select { + case _, ok := <-ch: + if ok { + close(ch) + return true + } + default: + } + return false +} + +func (c *Client) close() error { + closeChannel(c.outgoing) + return c.conn.Close() +} + +// SetLabelFlag is referred in zclient, this func sets label flag +func (c Client) SetLabelFlag(msgFlags *MessageFlag, nexthop *Nexthop) { + if c.Version == 6 && c.Software.name == "frr" { + nexthop.flags |= zapiNexthopFlagLabel + } else if c.Version > 4 { + *msgFlags |= MessageLabel + } +} + +// Header is header of zebra message. +type Header struct { + Len uint16 + Marker uint8 + Version uint8 + VrfID uint32 // ZAPI v4: 16bits, v5: 32bits + Command APIType +} + +func (h *Header) serialize() ([]byte, error) { + buf := make([]byte, HeaderSize(h.Version)) + binary.BigEndian.PutUint16(buf[0:2], h.Len) + buf[2] = h.Marker + buf[3] = h.Version + switch h.Version { + case 2: + binary.BigEndian.PutUint16(buf[4:6], uint16(h.Command)) + case 3, 4: + binary.BigEndian.PutUint16(buf[4:6], uint16(h.VrfID)) + binary.BigEndian.PutUint16(buf[6:8], uint16(h.Command)) + case 5, 6: + binary.BigEndian.PutUint32(buf[4:8], uint32(h.VrfID)) + binary.BigEndian.PutUint16(buf[8:10], uint16(h.Command)) + default: + return nil, fmt.Errorf("unsupported ZAPI version: %d", h.Version) + } + return buf, nil +} + +func (h *Header) decodeFromBytes(data []byte) error { + if uint16(len(data)) < 4 { + return fmt.Errorf("not all ZAPI message header") + } + h.Len = binary.BigEndian.Uint16(data[0:2]) + h.Marker = data[2] + h.Version = data[3] + if uint16(len(data)) < HeaderSize(h.Version) { + return fmt.Errorf("not all ZAPI message header") + } + switch h.Version { + case 2: + h.Command = APIType(binary.BigEndian.Uint16(data[4:6])) + case 3, 4: + h.VrfID = uint32(binary.BigEndian.Uint16(data[4:6])) + h.Command = APIType(binary.BigEndian.Uint16(data[6:8])) + case 5, 6: + h.VrfID = binary.BigEndian.Uint32(data[4:8]) + h.Command = APIType(binary.BigEndian.Uint16(data[8:10])) + default: + return fmt.Errorf("unsupported ZAPI version: %d", h.Version) + } + return nil +} + +// Body is an interface for zebra messages. +type Body interface { + decodeFromBytes([]byte, uint8, Software) error + serialize(uint8, Software) ([]byte, error) + string(uint8, Software) string +} + +type unknownBody struct { + Data []byte +} + +func (b *unknownBody) decodeFromBytes(data []byte, version uint8, software Software) error { + b.Data = data + return nil +} + +func (b *unknownBody) serialize(version uint8, software Software) ([]byte, error) { + return b.Data, nil +} + +func (b *unknownBody) string(version uint8, software Software) string { + return fmt.Sprintf("data: %v", b.Data) +} + +type helloBody struct { + redistDefault RouteType + instance uint16 + sessionID uint32 // frr7.4, 7.5, 8, 8.1, 8.2 + receiveNotify uint8 + synchronous uint8 // frr7.4, 7.5, 8, 8.1, 8.2 +} + +// Ref: zread_hello in zebra/zserv.c of Quagga1.2&FRR3 (ZAPI3&4) +// Ref: zread_hello in zebra/zapi_msg.c of FRR5&FRR6&FRR7&FRR7.1&FRR7.2&FRR7.3&FRR7.4&FRR7.5&FRR8 (ZAPI5&6) +func (b *helloBody) decodeFromBytes(data []byte, version uint8, software Software) error { + b.redistDefault = RouteType(data[0]) + if version > 3 { //frr + b.instance = binary.BigEndian.Uint16(data[1:3]) + if version == 6 && software.name == "frr" && software.version >= 7.4 { + b.sessionID = binary.BigEndian.Uint32(data[3:7]) + b.receiveNotify = data[7] + b.synchronous = data[8] + } else if version > 4 { + b.receiveNotify = data[3] + } + } + return nil +} + +// Ref: zebra_hello_send in lib/zclient.c of Quagga1.2&FRR3&FRR5&FRR6&FRR7&FRR7.1&FRR7.2&FRR7.3 (ZAPI3&4&5&6) +// Ref: zclient_send_hello in lib/zclient.c of FRR7.4&FRR7.5&FRR8 (ZAPI6) +func (b *helloBody) serialize(version uint8, software Software) ([]byte, error) { + if version < 4 { + return []byte{uint8(b.redistDefault)}, nil + } + var buf []byte + if version == 6 && software.name == "frr" && software.version >= 7.4 { + buf = make([]byte, 9) + } else if version > 4 { + buf = make([]byte, 4) + } else if version == 4 { + buf = make([]byte, 3) + } + buf[0] = uint8(b.redistDefault) + binary.BigEndian.PutUint16(buf[1:3], b.instance) + if version == 6 && software.name == "frr" && software.version >= 7.4 { + binary.BigEndian.PutUint32(buf[3:7], b.sessionID) + buf[7] = b.receiveNotify + buf[8] = b.synchronous + } else if version > 4 { + buf[3] = b.receiveNotify + } + return buf, nil +} + +func (b *helloBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "route_type: %s, instance :%d, sessionID: %d, receiveNotify: %d, synchronous: %d", + b.redistDefault.String(), b.instance, b.sessionID, b.receiveNotify, b.synchronous) +} + +type redistributeBody struct { + afi afi + redist RouteType + instance uint16 +} + +// Ref: zebra_redistribute_add in zebra/redistribute.c of Quagga1.2&FRR3&FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI3&4&5&6) +func (b *redistributeBody) decodeFromBytes(data []byte, version uint8, software Software) error { + if version < 4 { + b.redist = RouteType(data[0]) + } else { // version >= 4 + b.afi = afi(data[0]) + b.redist = RouteType(data[1]) + b.instance = binary.BigEndian.Uint16(data[2:4]) + } + return nil +} + +// Ref: zebra_redistribute_send in lib/zclient.c of Quagga1.2&FRR3&FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI3&4&5&6) +func (b *redistributeBody) serialize(version uint8, software Software) ([]byte, error) { + if version < 4 { + return []byte{uint8(b.redist)}, nil + } + buf := make([]byte, 4) + buf[0] = uint8(b.afi) + buf[1] = uint8(b.redist) + binary.BigEndian.PutUint16(buf[2:4], b.instance) + return buf, nil +} + +func (b *redistributeBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "afi: %s, route_type: %s, instance :%d", + b.afi.String(), b.redist.String(), b.instance) +} + +type linkParam struct { + status uint32 + teMetric uint32 + maxBw float32 + maxRsvBw float32 + unrsvBw [8]float32 + bwClassNum uint32 + adminGroup uint32 + remoteAS uint32 + remoteIP net.IP + aveDelay uint32 + minDelay uint32 + maxDelay uint32 + delayVar uint32 + pktLoss float32 + residualBw float32 + availableBw float32 + useBw float32 +} + +type interfaceUpdateBody struct { + name string + index uint32 + status interfaceStatus + flags uint64 + ptmEnable ptmEnable + ptmStatus ptmStatus + metric uint32 + speed uint32 + mtu uint32 + mtu6 uint32 + bandwidth uint32 + linkIfindex uint32 + linktype linkType + hardwareAddr net.HardwareAddr + linkParam linkParam +} + +// Ref: zebra_interface_if_set_value in lib/zclient.c of Quagga1.2&FRR3&FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI3&4&5&6) +func (b *interfaceUpdateBody) decodeFromBytes(data []byte, version uint8, software Software) error { + if len(data) < interfaceNameSize+33 { + return fmt.Errorf("lack of bytes. need %d but %d", interfaceNameSize+29, len(data)) + } + + b.name = strings.Trim(string(data[:interfaceNameSize]), "\u0000") + data = data[interfaceNameSize:] + b.index = binary.BigEndian.Uint32(data[0:4]) + b.status = interfaceStatus(data[4]) + b.flags = binary.BigEndian.Uint64(data[5:13]) + if version > 3 { + b.ptmEnable = ptmEnable(data[13]) + b.ptmStatus = ptmStatus(data[14]) + b.metric = binary.BigEndian.Uint32(data[15:19]) + b.speed = binary.BigEndian.Uint32(data[19:23]) + data = data[23:] + } else { + b.metric = binary.BigEndian.Uint32(data[13:17]) + data = data[17:] + } + b.mtu = binary.BigEndian.Uint32(data[0:4]) + b.mtu6 = binary.BigEndian.Uint32(data[4:8]) + b.bandwidth = binary.BigEndian.Uint32(data[8:12]) + data = data[12:] + + //frr 7.2 and later versions have link Ifindex + if version == 6 && software.name == "frr" && software.version >= 7.2 { + b.linkIfindex = binary.BigEndian.Uint32(data[:4]) + data = data[4:] + } + if version > 2 { + b.linktype = linkType(binary.BigEndian.Uint32(data[:4])) + data = data[4:] + } + l := binary.BigEndian.Uint32(data[:4]) // STREAM_GETL(s, ifp->hw_addr_len) + if l > 0 { + if len(data) < 4+int(l) { + return fmt.Errorf("lack of bytes in remain data. need %d but %d", 4+l, len(data)) + } + b.hardwareAddr = data[4 : 4+l] // STREAM_GET(ifp->hw_addr, s, MIN(ifp->hw_addr_len, INTERFACE_HWADDR_MAX)); + } + if version > 2 { + linkParam := data[4+l] // stream_getc(s) + if linkParam > 0 { // link_params_set_value + data = data[5+l:] + b.linkParam.status = binary.BigEndian.Uint32(data[0:4]) + b.linkParam.teMetric = binary.BigEndian.Uint32(data[4:8]) + b.linkParam.maxBw = math.Float32frombits(binary.BigEndian.Uint32(data[8:12])) + b.linkParam.maxRsvBw = math.Float32frombits(binary.BigEndian.Uint32(data[12:16])) + b.linkParam.bwClassNum = binary.BigEndian.Uint32(data[16:20]) + for i := uint32(0); i < b.linkParam.bwClassNum; i++ { + b.linkParam.unrsvBw[i] = math.Float32frombits(binary.BigEndian.Uint32(data[20+i*4 : 24+i*4])) + } + data = data[20+b.linkParam.bwClassNum*4:] + b.linkParam.adminGroup = binary.BigEndian.Uint32(data[0:4]) + b.linkParam.remoteAS = binary.BigEndian.Uint32(data[4:8]) + b.linkParam.remoteIP = data[8:12] + b.linkParam.aveDelay = binary.BigEndian.Uint32(data[12:16]) + b.linkParam.minDelay = binary.BigEndian.Uint32(data[16:20]) + b.linkParam.maxDelay = binary.BigEndian.Uint32(data[20:24]) + b.linkParam.delayVar = binary.BigEndian.Uint32(data[24:28]) + b.linkParam.pktLoss = math.Float32frombits(binary.BigEndian.Uint32(data[28:32])) + b.linkParam.residualBw = math.Float32frombits(binary.BigEndian.Uint32(data[32:36])) + b.linkParam.availableBw = math.Float32frombits(binary.BigEndian.Uint32(data[36:40])) + b.linkParam.useBw = math.Float32frombits(binary.BigEndian.Uint32(data[40:44])) + } + } + return nil +} + +func (b *interfaceUpdateBody) serialize(version uint8, software Software) ([]byte, error) { + return []byte{}, nil +} + +func (b *interfaceUpdateBody) string(version uint8, software Software) string { + s := fmt.Sprintf( + "name: %s, idx: %d, status: %s, flags: %s, ptm_enable: %s, ptm_status: %s, metric: %d, speed: %d, mtu: %d, mtu6: %d, bandwidth: %d, linktype: %s", + b.name, b.index, b.status.String(), intfflag2string(b.flags), b.ptmEnable.String(), b.ptmStatus.String(), b.metric, b.speed, b.mtu, b.mtu6, b.bandwidth, b.linktype.String()) + if len(b.hardwareAddr) > 0 { + return s + fmt.Sprintf(", mac: %s", b.hardwareAddr.String()) + } + return s +} + +type interfaceAddressUpdateBody struct { + index uint32 + flags interfaceAddressFlag + prefix net.IP + length uint8 + destination net.IP +} + +// Ref: zebra_interface_address_read in lib/zclient.c of Quagga1.2&FRR3&FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI3&4&5&6) +func (b *interfaceAddressUpdateBody) decodeFromBytes(data []byte, version uint8, software Software) error { + b.index = binary.BigEndian.Uint32(data[:4]) //STREAM_GETL(s, ifindex) + b.flags = interfaceAddressFlag(data[4]) //STREAM_GETC(s, ifc_flags) + family := data[5] //STREAM_GETC(s, d.family) + addrlen, err := addressByteLength(family) + if err != nil { + return err + } + b.prefix = data[6 : 6+addrlen] //zclient_stream_get_prefix //STREAM_GET(&p->u.prefix, s, plen); + b.length = data[6+addrlen] //zclient_stream_get_prefix //STREAM_GETC(s, c); + b.destination = data[7+addrlen : 7+addrlen*2] //STREAM_GET(&d.u.prefix, s, plen) + return nil +} + +func (b *interfaceAddressUpdateBody) serialize(version uint8, software Software) ([]byte, error) { + return []byte{}, nil +} + +func (b *interfaceAddressUpdateBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "idx: %d, flags: %s, addr: %s/%d", + b.index, b.flags.String(), b.prefix.String(), b.length) +} + +type routerIDUpdateBody struct { + length uint8 + prefix net.IP + afi afi +} + +// Ref: zebra_router_id_update_read in lib/zclient.c of Quagga1.2&FRR3&FRR5 (ZAPI3&4&5) +func (b *routerIDUpdateBody) decodeFromBytes(data []byte, version uint8, software Software) error { + family := data[0] + + addrlen, err := addressByteLength(family) + if err != nil { + return err + } + b.prefix = data[1 : 1+addrlen] //zclient_stream_get_prefix + b.length = data[1+addrlen] //zclient_stream_get_prefix + return nil +} + +// Ref: zclient_send_router_id_update in lib/zclient.c of FRR7.5 +func (b *routerIDUpdateBody) serialize(version uint8, software Software) ([]byte, error) { + if version == 6 && software.name == "frr" && software.version >= 7.5 { + return []byte{0x00, uint8(b.afi)}, nil //stream_putw(s, afi); + + } + return []byte{}, nil +} + +func (b *routerIDUpdateBody) string(version uint8, software Software) string { + return fmt.Sprintf("id: %s/%d", b.prefix.String(), b.length) +} + +// zapiNexthopFlag is defined in lib/zclient.h of FRR +const ( + zapiNexthopFlagOnlink uint8 = 0x01 // frr7.1, 7.2, 7.3, 7.4, 7.5, 8.0 + zapiNexthopFlagLabel uint8 = 0x02 // frr7.3, 7.4, 7.5, 8.0 + zapiNexthopFlagWeight uint8 = 0x04 // frr7.3, 7.4, 7.5, 8.0 + zapiNexthopFlagHasBackup uint8 = 0x08 // frr7.4, 7.5, 8.0 + zapiNexthopFlagSeg6 uint8 = 0x10 // frr8.1 + zapiNexthopFlagSeg6Local uint8 = 0x20 // frr8.1 +) + +// Flag for nexthop processing. It is gobgp's internal flag. +type nexthopProcessFlag uint8 + +const ( + nexthopHasType nexthopProcessFlag = 0x01 + nexthopHasVrfID nexthopProcessFlag = 0x02 + nexthopHasFlag nexthopProcessFlag = 0x04 + nexthopHasOnlink nexthopProcessFlag = 0x08 + nexthopProcessIPToIPIFindex nexthopProcessFlag = 0x10 + nexthopProcessIFnameToIFindex nexthopProcessFlag = 0x20 // for quagga +) + +func nexthopProcessFlagForIPRouteBody(version uint8, software Software, isDecode bool) nexthopProcessFlag { + if version < 5 { + if isDecode { + return nexthopProcessFlag(0) // frr3&quagga don't have type&vrfid + } + return nexthopHasType // frr3&quagga need type for encode(serialize) + } + processFlag := (nexthopHasVrfID | nexthopHasType) // frr4, 5, 6, 7 + if version == 6 && software.name == "frr" { + if software.version >= 7.3 { + processFlag |= (nexthopHasFlag | nexthopProcessIPToIPIFindex) + } else if software.version >= 7.1 { + processFlag |= nexthopHasOnlink + } + } + return processFlag +} + +// Ref: struct seg6local_context in lib/srv6.h of FRR8.1 +type seg6localContext struct { + nh4 net.IP //struct in_addr nh4 + nh6 net.IP //struct in_addr nh6 + table uint32 +} + +func (s6lc seg6localContext) encode() []byte { + var buf []byte + buf = append(buf, s6lc.nh4.To4()...) + buf = append(buf, s6lc.nh6.To16()...) + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, s6lc.table) + buf = append(buf, tmpbuf...) + return buf +} +func (s6lc *seg6localContext) decode(data []byte) int { + offset := 0 + s6lc.nh4 = net.IP(data[offset : offset+4]).To4() + offset += 4 + s6lc.nh6 = net.IP(data[offset : offset+16]).To16() + offset += 16 + s6lc.table = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + return offset +} + +// Ref: struct zapi_nexthop in lib/zclient.h of FRR5&FRR6&FRR7.x&FRR8, FRR8.1 (ZAPI5&6) +// Nexthop is referred in zclient +type Nexthop struct { + Type nexthopType //FRR5, FRR6, FRR7.x, FRR8, FRR8.1 + VrfID uint32 //FRR5, FRR6, FRR7.x, FRR8, FRR8.1 + Ifindex uint32 // Ifindex is referred in zclient_test + flags uint8 //FRR7.1, FRR7.2 FRR7.3, FRR7.4, FRR7.5, FRR8, FRR8.1 + Gate net.IP //union { union g_addr gate; + blackholeType uint8 // enum blackhole_type bh_type;} + LabelNum uint8 //FRR5, FRR6, FRR7.x, FRR8, FRR8.1 + MplsLabels []uint32 //FRR5, FRR6, FRR7.x, FRR8, FRR8.1 + rmac [6]byte //FRR6, FRR7.x, FRR8, FRR8.1 + weight uint32 //FRR7.3, FRR7.4, FRR7.5, FRR8, FRR8.1 + backupNum uint8 //FRR7.4, FRR7.5, FRR8, FRR8.1 + backupIndex []uint8 //FRR7.5, FRR8, FRR8.1 + srteColor uint32 //FRR7.5, FRR8, FRR8.1 + seg6localAction uint32 //FRR8.1 + seg6localCtx seg6localContext // FRR8.1 + seg6Segs net.IP //strcut in6_addr // FRR8.1 +} + +func (n Nexthop) string() string { + s := make([]string, 0) + s = append(s, fmt.Sprintf( + "type: %s, vrf_id: %d, ifindex: %d, flags: %d, gate: %s, blackholeType: %d, label_num: %d, weight: %d, backupNum: %d, srteColor: %d", + n.Type.String(), n.VrfID, n.Ifindex, n.flags, n.Gate.String(), + n.blackholeType, n.LabelNum, n.weight, n.backupNum, n.srteColor)) + for i := uint8(0); i < n.LabelNum; i++ { + s = append(s, fmt.Sprintf(" label[%d]: %d", i, n.MplsLabels[i])) + } + for i := uint8(0); i < n.backupNum; i++ { + s = append(s, fmt.Sprintf(" backupIndex[%d]: %d", i, n.backupIndex[i])) + } + return strings.Join(s, ", ") +} +func (n Nexthop) gateToType(version uint8) nexthopType { + if n.Gate.To4() != nil { + if version > 4 && n.Ifindex > 0 { + return nexthopTypeIPv4IFIndex + } + return nexthopTypeIPv4.toEach(version) + } else if n.Gate.To16() != nil { + if version > 4 && n.Ifindex > 0 { + return nexthopTypeIPv6IFIndex + } + return nexthopTypeIPv6.toEach(version) + } else if n.Ifindex > 0 { + return nexthopTypeIFIndex.toEach(version) + } else if version > 4 { + return nexthopTypeBlackhole + } + return nexthopType(0) +} + +// Ref: zapi_nexthop_encode in lib/zclient.h of FRR7.3&FRR7.4&FRR7.5&FRR8 +func (n Nexthop) encode(version uint8, software Software, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag) []byte { + var buf []byte + if processFlag&nexthopHasVrfID > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, n.VrfID) + buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->vrf_id); + } + if processFlag&nexthopHasType > 0 { + if n.Type == nexthopType(0) { + n.Type = n.gateToType(version) + } + buf = append(buf, uint8(n.Type)) //frr: stream_putc(s, api_nh->type); + } + if processFlag&nexthopHasFlag > 0 { + if n.LabelNum > 0 { + n.flags |= zapiNexthopFlagLabel + } + if n.weight > 0 { + n.flags |= zapiNexthopFlagWeight + } + if n.backupNum > 0 { + n.flags |= zapiNexthopFlagHasBackup + } + } + if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 { + // frr7.1, 7.2 has onlink, 7.3 has flag + buf = append(buf, n.flags) //frr: stream_putc(s, nh_flags); + } + + nhType := n.Type + if processFlag&nexthopProcessIPToIPIFindex > 0 { + nhType = nhType.ipToIPIFIndex() + } + if processFlag&nexthopProcessIFnameToIFindex > 0 { + nhType = nhType.ifNameToIFIndex() + } + if nhType == nexthopTypeIPv4.toEach(version) || + nhType == nexthopTypeIPv4IFIndex.toEach(version) { + //frr: stream_put_in_addr(s, &api_nh->gate.ipv4); + buf = append(buf, n.Gate.To4()...) + } else if nhType == nexthopTypeIPv6.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + //frr: stream_write(s, (uint8_t *)&api_nh->gate.ipv6, 16); + buf = append(buf, n.Gate.To16()...) + } + if nhType == nexthopTypeIFIndex || + nhType == nexthopTypeIPv4IFIndex.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, n.Ifindex) + buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->ifindex); + } + if nhType == nexthopTypeBlackhole.toEach(version) { //case NEXTHOP_TYPE_BLACKHOLE: + //frr: stream_putc(s, api_nh->bh_type); + buf = append(buf, uint8(n.blackholeType)) + } + if n.flags&zapiNexthopFlagLabel > 0 || (message&MessageLabel > 0 && + version == 5 || + (version == 6 && software.name == "frr" && + software.version >= 6 && software.version < 7.3)) { + tmpbuf := make([]byte, 1+4*n.LabelNum) + tmpbuf[0] = n.LabelNum //frr: stream_putc(s, api_nh->label_num); + for i := uint8(0); i < n.LabelNum; i++ { + // frr uses stream_put for mpls label array. + // stream_put is unaware of byteorder coversion. + // Therefore LittleEndian is used instead of BigEndian. + binary.LittleEndian.PutUint32(tmpbuf[i*4+1:], n.MplsLabels[i]) + } + //frr: stream_put(s, &api_nh->labels[0], api_nh->label_num * sizeof(mpls_label_t)); + buf = append(buf, tmpbuf...) + } + if n.flags&zapiNexthopFlagWeight > 0 && n.weight > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, uint32(n.weight)) + buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->weight); + } + if apiFlag&flagEvpnRoute.ToEach(version, software) > 0 { + //frr: stream_put(s, &(api_nh->rmac), sizeof(struct ethaddr)); + buf = append(buf, n.rmac[:]...) + } + // added in frr7.5 (Color for Segment Routing TE.) + if message&messageSRTE > 0 && (version == 6 && software.name == "frr" && software.version >= 7.5) { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, uint32(n.srteColor)) + buf = append(buf, tmpbuf...) //frr: stream_putl(s, api_nh->srte_color); + } + // added in frr7.4 (Index of backup nexthop) + if n.flags&zapiNexthopFlagHasBackup > 0 { + tmpbuf := make([]byte, 1+1*n.backupNum) + tmpbuf[0] = n.backupNum //frr: stream_putc(s, api_nh->backup_num); + for i := uint8(0); i < n.backupNum; i++ { + tmpbuf[i+1] = n.backupIndex[i] + } + buf = append(buf, tmpbuf...) + } + // added in frr8.1 + if n.flags&zapiNexthopFlagSeg6 > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, uint32(n.seg6localAction)) + buf = append(buf, tmpbuf...) // stream_putl(s, api_nh->seg6local_action); + //frr: stream_write(s, &api_nh->seg6local_ctx, sizeof(struct seg6local_context)); + buf = append(buf, n.seg6localCtx.encode()...) + } + // added in frr8.1 + if n.flags&zapiNexthopFlagSeg6Local > 0 { + //frr: stream_write(s, &api_nh->seg6_segs, sizeof(struct in6_addr)); + buf = append(buf, n.seg6Segs.To16()...) + } + return buf +} + +// Ref: zapi_nexthop_decode in lib/zclient.h of FRR7.3&FRR7.4&FRR7.5&FRR8 +func (n *Nexthop) decode(data []byte, version uint8, software Software, family uint8, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag, nhType nexthopType) (int, error) { + offset := 0 + if processFlag&nexthopHasVrfID > 0 { + //frr: STREAM_GETL(s, api_nh->vrf_id); + n.VrfID = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + + n.Type = nhType // data does not have nexthop type + if processFlag&nexthopHasType > 0 { + n.Type = nexthopType(data[offset]) //frr: STREAM_GETC(s, api_nh->type); + offset++ + } + + n.flags = uint8(0) + if processFlag&nexthopHasFlag > 0 || processFlag&nexthopHasOnlink > 0 { + n.flags = uint8(data[offset]) //frr: STREAM_GETC(s, api_nh->flags); + offset++ + } + + nhType = n.Type + if processFlag&nexthopProcessIPToIPIFindex > 0 { + nhType = nhType.ipToIPIFIndex() + } + if processFlag&nexthopProcessIFnameToIFindex > 0 { + nhType = nhType.ifNameToIFIndex() + } + if family == syscall.AF_INET { + n.Gate = net.ParseIP("0.0.0.0") + } else if family == syscall.AF_INET6 { + n.Gate = net.ParseIP("::") + } + if nhType == nexthopTypeIPv4.toEach(version) || + nhType == nexthopTypeIPv4IFIndex.toEach(version) { + //frr: STREAM_GET(&api_nh->gate.ipv4.s_addr, s, IPV4_MAX_BYTELEN); + n.Gate = net.IP(data[offset : offset+4]).To4() + offset += 4 + } else if nhType == nexthopTypeIPv6.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + //frr: STREAM_GET(&api_nh->gate.ipv6, s, 16); + n.Gate = net.IP(data[offset : offset+16]).To16() + offset += 16 + } + if nhType == nexthopTypeIFIndex || + nhType == nexthopTypeIPv4IFIndex.toEach(version) || + nhType == nexthopTypeIPv6IFIndex.toEach(version) { + //frr: STREAM_GETL(s, api_nh->ifindex); + n.Ifindex = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + if nhType == nexthopTypeBlackhole.toEach(version) { //case NEXTHOP_TYPE_BLACKHOLE: + n.blackholeType = data[offset] //frr: STREAM_GETC(s, api_nh->bh_type); + offset++ + } + if n.flags&zapiNexthopFlagLabel > 0 || (message&MessageLabel > 0 && + (version == 5 || version == 6 && software.name == "frr" && + software.version >= 6 && software.version < 7.3)) { + n.LabelNum = uint8(data[offset]) //frr: STREAM_GETC(s, api_nh->label_num); + offset++ + if n.LabelNum > maxMplsLabel { + n.LabelNum = maxMplsLabel + } + if n.LabelNum > 0 { + n.MplsLabels = make([]uint32, n.LabelNum) + for i := uint8(0); i < n.LabelNum; i++ { + // frr uses stream_put which is unaware of byteorder for mpls label array. + // Therefore LittleEndian is used instead of BigEndian. + //frr: STREAM_GET(&api_nh->labels[0], s, api_nh->label_num * sizeof(mpls_label_t)); + n.MplsLabels[i] = binary.LittleEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + } + } + if n.flags&zapiNexthopFlagWeight > 0 { + //frr: STREAM_GETL(s, api_nh->weight); + n.weight = binary.BigEndian.Uint32(data[offset:]) + offset += 4 + } + if apiFlag&flagEvpnRoute.ToEach(version, software) > 0 { + //frr: STREAM_GET(&(api_nh->rmac), s, sizeof(struct ethaddr)); + copy(n.rmac[0:], data[offset:offset+6]) + offset += 6 + } + // added in frr7.5 (Color for Segment Routing TE.) + if message&messageSRTE > 0 && + (version == 6 && software.name == "frr" && software.version >= 7.5) { + //frr: STREAM_GETL(s, api_nh->srte_color); + n.srteColor = binary.BigEndian.Uint32(data[offset:]) + offset += 4 + } + // added in frr7.4 (Index of backup nexthop) + if n.flags&zapiNexthopFlagHasBackup > 0 { + n.backupNum = data[offset] //frr: STREAM_GETC(s, api_nh->backup_num); + offset++ + if n.backupNum > 0 { + n.backupIndex = make([]uint8, n.backupNum) + for i := uint8(0); i < n.backupNum; i++ { + //frr STREAM_GETC(s, api_nh->backup_idx[i]); + n.backupIndex[i] = data[offset] + offset++ + } + } + } + // added in frr8.1 + if n.flags&zapiNexthopFlagSeg6 > 0 { + n.seg6localAction = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + offset += n.seg6localCtx.decode(data[offset : offset+24]) + } + // added in frr8.1 + if n.flags&zapiNexthopFlagSeg6Local > 0 { + n.seg6Segs = net.IP(data[offset : offset+16]).To16() + offset += 16 + } + return offset, nil +} + +// decodeNexthops is referred from decodeFromBytes of NexthopUpdateBody and IPRouteBody +func decodeNexthops(nexthops *[]Nexthop, data []byte, version uint8, software Software, family uint8, numNexthop uint16, processFlag nexthopProcessFlag, message MessageFlag, apiFlag Flag, nhType nexthopType) (int, error) { + offset := 0 + *nexthops = make([]Nexthop, numNexthop) + for i := uint16(0); i < numNexthop; i++ { + size, err := (&((*nexthops)[i])).decode(data[offset:], version, software, family, processFlag, message, apiFlag, nhType) + if err != nil { + return offset, err + } + offset += size + } + return offset, nil +} + +// Prefix referred in zclient is struct for network prefix and relate information +type Prefix struct { + Family uint8 + PrefixLen uint8 + Prefix net.IP +} + +func familyFromPrefix(prefix net.IP) uint8 { + if prefix.To4() != nil { + return syscall.AF_INET + } else if prefix.To16() != nil { + return syscall.AF_INET6 + } + return syscall.AF_UNSPEC +} + +const messageOpaqueLenth uint16 = 1024 + +type opaque struct { + length uint16 + data [messageOpaqueLenth]uint8 +} + +// Ref: struct zapi_route in lib/zclient.h of FRR4&FRR5&FRR6&FRR7.x&RR8 (ZAPI5&6) +// IPRouteBody is struct for IPRotue (zapi_route) +type IPRouteBody struct { + Type RouteType // FRR4&FRR5&FRR6&FRR7.x&FRR8 + instance uint16 // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Flags Flag // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Message MessageFlag // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Safi Safi // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Prefix Prefix // FRR4&FRR5&FRR6&FRR7.x&FRR8 + srcPrefix Prefix // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Nexthops []Nexthop // FRR4&FRR5&FRR6&FRR7.x&FRR8 + backupNexthops []Nexthop // added in frr7.4, FRR7.4&FRR7.5&FRR8 + nhgid uint32 // added in frr8 + Distance uint8 // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Metric uint32 // FRR4&FRR5&FRR6&FRR7.x&FRR8 + tag uint32 // FRR4&FRR5&FRR6&FRR7.x&FRR8 + Mtu uint32 // FRR4&FRR5&FRR6&FRR7.x&FRR8 + tableID uint32 // FRR5&FRR6&FRR7.x&FRR8 (nh_vrf_id in FRR4) + srteColor uint32 // added in frr7.5, FRR7.5&FRR8 + opaque opaque // added in frr8 + API APIType // API is referred in zclient_test + //vrfID uint32 // lib/zebra.h:typedef uint32_t vrf_id_t; +} + +func (b *IPRouteBody) safi(logger log.Logger, version uint8, software Software) Safi { + // frr 7.2 and later versions have safiUnspec, older versions don't have safiUnspec + if b.Safi == safiUnspec && (version < 6 || + (version == 6 && software.name == "frr" && software.version < 7.2)) { + return SafiUnicast //safiUnspec is regarded as safiUnicast in older versions + } + if b.Safi <= safiMulticast || version > 4 { // not need to convert + return b.Safi + } + safiMap := zapi4SafiMap + if version < 4 { + safiMap = zapi3SafiMap + } + safi, ok := safiMap[b.Safi] + if !ok { + safi = safiUnspec // failed to convert + } + logger.Debug("zebra converts safi", + log.Fields{ + "Topic": "Zebra", + "Body": b, + "Old": b.Safi.String(), + "New": safi.String()}) + return safi // success to convert +} + +// RouteFamily is referred in zclient +func (b *IPRouteBody) RouteFamily(logger log.Logger, version uint8, software Software) bgp.RouteFamily { + if b == nil { + return bgp.RF_OPAQUE // fail + } + safi := b.safi(logger, version, software) + if safi == safiEvpn { + return bgp.RF_EVPN // success + } + family := b.Prefix.Family + if family == syscall.AF_UNSPEC { + family = familyFromPrefix(b.Prefix.Prefix) + } + if family == syscall.AF_UNSPEC { // familyFromPrefix returs AF_UNSPEC + return bgp.RF_OPAQUE // fail + } + safiRouteFamilyMap := safiRouteFamilyIPv4Map // syscall.AF_INET + if family == syscall.AF_INET6 { + safiRouteFamilyMap = safiRouteFamilyIPv6Map + } + rf, ok := safiRouteFamilyMap[safi] + if !ok { + return bgp.RF_OPAQUE // fail + } + logger.Debug("zebra converts safi", + log.Fields{ + "Topic": "Zebra", + "Body": b, + "Safi": safi.String(), + "Rf": rf.String()}) + + return rf // success +} + +// IsWithdraw is referred in zclient +func (b *IPRouteBody) IsWithdraw(version uint8, software Software) bool { + api := b.API.toCommon(version, software) + switch api { + case RouteDelete, redistributeRouteDel, BackwardIPv6RouteDelete: + return true + } + if version == 4 && b.API == zapi4RedistributeIPv6Del { + return true + } + return false +} + +// Ref: zapi_ipv4_route in lib/zclient.c of Quagga1.2.x&FRR3.x(ZAPI3&4) +// Ref: zapi_route_encode in lib/zclient.c of FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (b *IPRouteBody) serialize(version uint8, software Software) ([]byte, error) { + var buf []byte + numNexthop := len(b.Nexthops) + + bufInitSize := 12 //type(1)+instance(2)+flags(4)+message(4)+safi(1), frr7.4&newer + switch version { + case 2, 3: + bufInitSize = 5 + case 4: + bufInitSize = 10 + case 5: + bufInitSize = 9 //type(1)+instance(2)+flags(4)+message(1)+safi(1) + case 6: + if software.name == "frr" && software.version < 7.4 { // frr6, 7, 7.2, 7.3 + bufInitSize = 9 //type(1)+instance(2)+flags(4)+message(1)+safi(1) + } + } + buf = make([]byte, bufInitSize) + + buf[0] = uint8(b.Type.toEach(version)) //frr: stream_putc(s, api->type); + if version < 4 { + buf[1] = uint8(b.Flags) + buf[2] = uint8(b.Message) + binary.BigEndian.PutUint16(buf[3:5], uint16(b.Safi)) + } else { // version >= 4 + //frr: stream_putw(s, api->instance); + binary.BigEndian.PutUint16(buf[1:3], uint16(b.instance)) + //frr: stream_putl(s, api->flags); + binary.BigEndian.PutUint32(buf[3:7], uint32(b.Flags)) + if version == 6 && software.name == "frr" && software.version >= 7.5 { + //frr7.5 and newer: stream_putl(s, api->message); + binary.BigEndian.PutUint32(buf[7:11], uint32(b.Message)) + buf[11] = uint8(b.Safi) //stream_putc(s, api->safi); + } else { + //frr 7.4 and older: stream_putc(s, api->message); + buf[7] = uint8(b.Message) + if version > 4 { + buf[8] = uint8(b.Safi) //frr: stream_putc(s, api->safi); + } else { // version 2,3 and 4 (quagga, frr3) + binary.BigEndian.PutUint16(buf[8:10], uint16(b.Safi)) + } + } + } + // only zapi version 5 (frr4.0.x) have evpn routes + if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, software) > 0 { + // size of struct ethaddr is 6 octets defined by ETH_ALEN + buf = append(buf, b.Nexthops[numNexthop-1].rmac[:6]...) + } + if version > 4 { // version 5, 6 (after frr4) + if b.Prefix.Family == syscall.AF_UNSPEC { + b.Prefix.Family = familyFromPrefix(b.Prefix.Prefix) + } + //frr: stream_putc(s, api->prefix.family); + buf = append(buf, b.Prefix.Family) + } + byteLen := (int(b.Prefix.PrefixLen) + 7) / 8 + buf = append(buf, b.Prefix.PrefixLen) //frr: stream_putc(s, api->prefix.prefixlen); + //frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize); + buf = append(buf, b.Prefix.Prefix[:byteLen]...) + + if version > 3 && b.Message&messageSRCPFX.ToEach(version, software) > 0 { + byteLen = (int(b.srcPrefix.PrefixLen) + 7) / 8 + //frr: stream_putc(s, api->src_prefix.prefixlen); + buf = append(buf, b.srcPrefix.PrefixLen) + //frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize); + buf = append(buf, b.srcPrefix.Prefix[:byteLen]...) + } + + // NHG(Nexthop Group) is added in frr8 + //frr: if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG)) + if version == 6 && software.name == "frr" && software.version >= 8 && + b.Message&messageNhg.ToEach(version, software) > 0 { + //frr: stream_putl(s, api->nhgid); + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.nhgid) + buf = append(buf, tmpbuf...) + } + + processFlag := nexthopProcessFlagForIPRouteBody(version, software, false) + if b.Message&MessageNexthop > 0 { + if version < 5 { + if b.Flags&flagBlackhole > 0 { + buf = append(buf, []byte{1, uint8(nexthopTypeBlackhole.toEach(version))}...) + } else { + buf = append(buf, uint8(numNexthop)) + } + } else { // version >= 5 + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, uint16(numNexthop)) + buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->nexthop_num); + } + for _, nexthop := range b.Nexthops { + buf = append(buf, nexthop.encode(version, software, processFlag, b.Message, b.Flags)...) + } + } + // MESSAGE_BACKUP_NEXTHOPS is added in frr7.4 + if version == 6 && software.name == "frr" && software.version >= 7.4 && + b.Message&messageBackupNexthops > 0 { + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, uint16(len(b.backupNexthops))) + buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->backup_nexthop_num); + for _, nexthop := range b.backupNexthops { + buf = append(buf, nexthop.encode(version, software, processFlag, b.Message, b.Flags)...) + } + } + if b.Message&MessageDistance.ToEach(version, software) > 0 { + buf = append(buf, b.Distance) + } + if b.Message&MessageMetric.ToEach(version, software) > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.Metric) + buf = append(buf, tmpbuf...) + } + if b.Message&messageTag.ToEach(version, software) > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.tag) + buf = append(buf, tmpbuf...) + } + if b.Message&MessageMTU.ToEach(version, software) > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.Mtu) + buf = append(buf, tmpbuf...) + } + if b.Message&messageTableID.ToEach(version, software) > 0 { + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.tableID) + buf = append(buf, tmpbuf...) + } + if b.Message&messageOpaque.ToEach(version, software) > 0 { + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, b.opaque.length) + buf = append(buf, tmpbuf...) //frr: stream_putw(s, api->opaque.length); + buf = append(buf, b.opaque.data[:]...) //frr: stream_write(s, api->opaque.data, api->opaque.length); + } + return buf, nil +} + +// decodeMessageNexthopFromBytes is referred in IPRouteBody's decodeFromBytes +func (b *IPRouteBody) decodeMessageNexthopFromBytes(data []byte, version uint8, software Software, isBackup bool) (int, error) { + pos := 0 + rest := len(data) + message := MessageNexthop + nexthops := &b.Nexthops + messageString := "MessageNexthop" + if isBackup { + message = messageBackupNexthops + nexthops = &b.backupNexthops + messageString = "messageBackupNexthops" + } + if b.Message&message > 0 { + numNexthop := uint16(0) + numNexthopDataSize := 2 + processFlag := nexthopProcessFlagForIPRouteBody(version, software, true) + nhType := nexthopType(0) + if message == MessageNexthop && version < 5 { // frr3 and quagga + numNexthopDataSize = 1 + nhType = nexthopTypeIPv4.toEach(version) + if b.Prefix.Family == syscall.AF_INET6 { + nhType = nexthopTypeIPv6.toEach(version) + } + } + if pos+numNexthopDataSize > rest { + return pos, fmt.Errorf("%s message length invalid pos:%d rest:%d", messageString, pos, rest) + } + if numNexthopDataSize == 2 { + //frr: STREAM_GETW(s, api->nexthop_num); + numNexthop = binary.BigEndian.Uint16(data[pos : pos+2]) + } else if message == MessageNexthop && numNexthopDataSize == 1 { + numNexthop = uint16(data[pos]) + } + pos += numNexthopDataSize + + nexthopsByteLen, err := decodeNexthops(nexthops, data[pos:], version, software, b.Prefix.Family, numNexthop, processFlag, b.Message, b.Flags, nhType) + if err != nil { + return pos, err + } + pos += nexthopsByteLen + } + return pos, nil +} + +// Ref: zebra_read_ipv4 in bgpd/bgp_zebra.c of Quagga1.2.x&FRR3.x(ZAPI3&4) +// Ref: zapi_route_decode in lib/zclient.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, software Software) error { + if b == nil { + return fmt.Errorf("IPRouteBody is nil") + } + //frr: STREAM_GETC(s, api->type); + b.Type = RouteType(data[0]) + if b.Type > getRouteAll(version, software) { //ver5 and later work, fix for older + return fmt.Errorf("unknown route type: %d in version: %d (%s)", b.Type, version, software.string()) + } + + if version <= 3 { + b.Flags = Flag(data[1]) + data = data[2:] + } else { // version >= 4 + //frr: STREAM_GETW(s, api->instance); + b.instance = binary.BigEndian.Uint16(data[1:3]) + //frr: STREAM_GETL(s, api->flags); + b.Flags = Flag(binary.BigEndian.Uint32(data[3:7])) + data = data[7:] + } + if version == 6 && software.name == "frr" && software.version >= 7.5 { + //frr7.5: STREAM_GETL(s, api->message); + b.Message = MessageFlag(binary.BigEndian.Uint32(data[0:4])) + data = data[4:] + } else { + b.Message = MessageFlag(data[0]) //frr: STREAM_GETC(s, api->message); + data = data[1:] + } + b.Safi = Safi(SafiUnicast) + b.Prefix.Family = b.API.addressFamily(version) // return AF_UNSPEC if version > 4 + var evpnNexthop Nexthop + if version > 4 { + b.Safi = Safi(data[0]) //frr: STREAM_GETC(s, api->safi); + if b.Safi > safiMax { //frr5 and later work, ToDo: fix for older version + return fmt.Errorf("unknown safi type: %d in version: %d (%s)", b.Type, version, software.string()) + } + data = data[1:] + + // zapi version 5 only + if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, software) > 0 { + // size of struct ethaddr is 6 octets defined by ETH_ALEN + copy(evpnNexthop.rmac[0:6], data[0:6]) + data = data[6:] + } + + b.Prefix.Family = data[0] //frr: STREAM_GETC(s, api->prefix.family); + data = data[1:] + } + + addrByteLen, err := addressByteLength(b.Prefix.Family) + if err != nil { + return err + } + + addrBitLen := uint8(addrByteLen * 8) + + b.Prefix.PrefixLen = data[0] //frr: STREAM_GETC(s, api->prefix.prefixlen); + if b.Prefix.PrefixLen > addrBitLen { + return fmt.Errorf("prefix length %d is greater than %d", b.Prefix.PrefixLen, addrBitLen) + } + data = data[1:] + pos := 0 + rest := len(data) + + buf := make([]byte, addrByteLen) + byteLen := int((b.Prefix.PrefixLen + 7) / 8) + if pos+byteLen > rest { + return fmt.Errorf("message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GET(&api->prefix.u.prefix, s, PSIZE(api->prefix.prefixlen)); + copy(buf, data[pos:pos+byteLen]) + b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, buf) + pos += byteLen + + if version > 3 && b.Message&messageSRCPFX.ToEach(version, software) > 0 { + if pos+1 > rest { + return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GETC(s, api->src_prefix.prefixlen); + b.srcPrefix.PrefixLen = data[pos] + if b.srcPrefix.PrefixLen > addrBitLen { + return fmt.Errorf("prefix length is greater than %d", addrByteLen*8) + } + pos++ + buf = make([]byte, addrByteLen) + byteLen = int((b.srcPrefix.PrefixLen + 7) / 8) + if pos+byteLen > rest { + return fmt.Errorf("MessageSRCPFX message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GET(&api->src_prefix.prefix, s, PSIZE(api->src_prefix.prefixlen)); + copy(buf, data[pos:pos+byteLen]) + b.srcPrefix.Prefix = ipFromFamily(b.Prefix.Family, buf) + pos += byteLen + } + + // NHG(Nexthop Group) is added in frr8 + //frr: if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NHG)) + if version == 6 && software.name == "frr" && software.version >= 8 { // added in frr8 + if b.Message&messageNhg.ToEach(version, software) > 0 { + //frr: STREAM_GETL(s, api->nhgid); + b.nhgid = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + } + + b.Nexthops = []Nexthop{} + if b.Message&MessageNexthop.ToEach(version, software) > 0 { + offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, software, false) + if err != nil { + return err + } + pos += offset + } + + b.backupNexthops = []Nexthop{} // backupNexthops is added in frr7.4 + if b.Message&messageBackupNexthops.ToEach(version, software) > 0 { + offset, err := b.decodeMessageNexthopFromBytes(data[pos:], version, software, true) + if err != nil { + return err + } + pos += offset + } + + // version 5 only, In version 6, EvpnRoute is processed in MessageNexthop + if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, software) > 0 { + b.Nexthops = append(b.Nexthops, evpnNexthop) + } + + if version < 5 && b.Message&messageIFIndex > 0 { // version 4, 3, 2 + if pos+1 > rest { + return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest) + } + numIfIndex := uint8(data[pos]) + pos++ + for i := 0; i < int(numIfIndex); i++ { + if pos+4 > rest { + return fmt.Errorf("MessageIFIndex message length invalid pos:%d rest:%d", pos, rest) + } + var nexthop Nexthop + nexthop.Ifindex = binary.BigEndian.Uint32(data[pos : pos+4]) + nexthop.Type = nexthopTypeIFIndex + b.Nexthops = append(b.Nexthops, nexthop) + pos += 4 + } + } + + if b.Message&MessageDistance.ToEach(version, software) > 0 { + if pos+1 > rest { + return fmt.Errorf("MessageDistance message length invalid pos:%d rest:%d", pos, rest) + } + b.Distance = data[pos] //frr: STREAM_GETC(s, api->distance); + pos++ + } + if b.Message&MessageMetric.ToEach(version, software) > 0 { + if pos+4 > rest { + return fmt.Errorf("MessageMetric message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GETL(s, api->metric); + b.Metric = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + if b.Message&messageTag.ToEach(version, software) > 0 { + if pos+4 > rest { + return fmt.Errorf("MessageTag message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GETL(s, api->tag); + b.tag = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + //frr3 and quagga does not have MESSAGE_MTU + if b.Message&MessageMTU.ToEach(version, software) > 0 { + if pos+4 > rest { + return fmt.Errorf("MessageMTU message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GETL(s, api->mtu); + b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + //frr5 and later version have MESSAGE_TABLEID + if b.Message&messageTableID.ToEach(version, software) > 0 { + if pos+4 > rest { + return fmt.Errorf("MessageTableID message length invalid pos:%d rest:%d", pos, rest) + } + //frr: STREAM_GETL(s, api->mtu); + b.Mtu = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + } + + if version == 6 && software.name == "frr" && software.version >= 8 { // added in frr8 + if b.Message&messageOpaque.ToEach(version, software) > 0 { + b.opaque.length = binary.BigEndian.Uint16(data[pos : pos+2]) + copy(b.opaque.data[0:b.opaque.length], data[pos+2:pos+2+int(b.opaque.length)]) + pos += 2 + int(b.opaque.length) + } + } + + if pos != rest { + return fmt.Errorf("message length invalid (last) pos:%d rest:%d, message:%#x", pos, rest, b.Message) + } + return nil +} + +func (b *IPRouteBody) string(version uint8, software Software) string { + s := fmt.Sprintf( + "type: %s, instance: %d, flags: %s, message: %d(%s), safi: %s, prefix: %s/%d, src_prefix: %s/%d", + b.Type.String(), b.instance, b.Flags.String(version, software), b.Message, + b.Message.string(version, software), b.Safi.String(), b.Prefix.Prefix.String(), b.Prefix.PrefixLen, + b.srcPrefix.Prefix.String(), b.srcPrefix.PrefixLen) + for i, nh := range b.Nexthops { + s += fmt.Sprintf(", nexthops[%d]: %s", i, nh.string()) + } + return s + fmt.Sprintf( + ", nhgid:%d, distance: %d, metric: %d, mtu: %d, tag: %d", + b.nhgid, b.Distance, b.Metric, b.Mtu, b.tag) +} + +// lookupBody is combination of nexthopLookupBody and imporetLookupBody +type lookupBody struct { + api APIType + prefixLength uint8 // importLookup serialize only + addr net.IP //it is same as prefix (it is deleted from importLookup) + distance uint8 // nexthopIPv4LookupMRIB only + metric uint32 + nexthops []Nexthop +} + +// Quagga only. Ref: zread_ipv4_(nexthop|import_lookup) in zebra/zserv.c +func (b *lookupBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 0) + if b.api == zapi3IPv4ImportLookup { + buf = append(buf, b.prefixLength) + } + switch b.api { + case ipv4NexthopLookupMRIB, zapi3IPv4NexthopLookup, zapi3IPv4ImportLookup: + buf = append(buf, b.addr.To4()...) + case zapi3IPv6NexthopLookup: + buf = append(buf, b.addr.To16()...) + } + return buf, nil +} + +// Quagga only(except ipv4NexthopLookupMRIB). +// Ref: zsend_ipv[4|6]_(nexthop|import)_lookup in zebra/zserv.c +func (b *lookupBody) decodeFromBytes(data []byte, version uint8, software Software) error { + family := uint8(syscall.AF_INET) + if b.api == zapi3IPv6NexthopLookup { + family = syscall.AF_INET6 + } + addrByteLen, _ := addressByteLength(family) + requiredLen := 5 //metric(4), numNexthop(1) + hasDistance := false + if b.api == ipv4NexthopLookupMRIB.ToEach(version, software) { + requiredLen++ //distance + hasDistance = true + } + if len(data) < addrByteLen+requiredLen { + return fmt.Errorf("message length invalid") + } + buf := make([]byte, addrByteLen) + copy(buf, data[0:addrByteLen]) + pos := addrByteLen + b.addr = ipFromFamily(family, buf) + if hasDistance { + b.distance = data[pos] + pos++ + } + b.metric = binary.BigEndian.Uint32(data[pos : pos+4]) + pos += 4 + numNexthop := uint16(data[pos]) + pos++ + b.nexthops = []Nexthop{} + processFlag := nexthopHasType | nexthopProcessIFnameToIFindex + nexthopsByteLen, err := decodeNexthops(&b.nexthops, data[pos:], version, software, family, numNexthop, processFlag, MessageFlag(0), Flag(0), nexthopType(0)) + if err != nil { + return err + } + pos += nexthopsByteLen + return nil +} +func (b *lookupBody) string(version uint8, software Software) string { + s := fmt.Sprintf( + "addr/prefixLength: %s/%d, distance:%d, metric: %d", + b.addr.String(), b.prefixLength, b.distance, b.metric) + if len(b.nexthops) > 0 { + for _, nh := range b.nexthops { + s = s + fmt.Sprintf(", nexthop:{%s}", nh.string()) + } + } + return s +} + +// RegisteredNexthop is referred in zclient +type RegisteredNexthop struct { + connected uint8 + resolveViaDef uint8 // added in frr8.2 + safi uint16 // added in frr8.2 + Family uint16 + // Note: Ignores PrefixLength (uint8), because this field should be always: + // - 32 if Address Family is AF_INET + // - 128 if Address Family is AF_INET6 + Prefix net.IP +} + +func (n *RegisteredNexthop) len() int { + // Connected (1 byte) + Address Family (2 bytes) + Prefix Length (1 byte) + Prefix (variable) + if n.Family == uint16(syscall.AF_INET) { + return 4 + net.IPv4len + } + return 4 + net.IPv6len +} + +// Ref: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) +// Ref: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) +// Ref: zclient_send_rnh in lib/zclient.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (n *RegisteredNexthop) serialize(version uint8, software Software) ([]byte, error) { + bufInitSize := 4 + if version == 6 && software.name == "frr" && software.version >= 8.2 { + bufInitSize = 7 + } + buf := make([]byte, bufInitSize) + // Connected (1 byte) + buf[0] = byte(n.connected) // stream_putc(s, (connected) ? 1 : 0); + pos := 1 + if version == 6 && software.name == "frr" && software.version >= 8.2 { + buf[1] = byte(n.resolveViaDef) + binary.BigEndian.PutUint16(buf[1:3], uint16(SafiUnicast)) // stream_putw(s, PREFIX_FAMILY(p)); + pos += 3 + } + // Address Family (2 bytes) + binary.BigEndian.PutUint16(buf[pos:pos+2], n.Family) // stream_putw(s, PREFIX_FAMILY(p)); + pos += 2 + // Prefix Length (1 byte) + addrByteLen, err := addressByteLength(uint8(n.Family)) + if err != nil { + return nil, err + } + + buf[3] = byte(addrByteLen * 8) // stream_putc(s, p->prefixlen); + pos += 1 + // Prefix (variable) + switch n.Family { + case uint16(syscall.AF_INET): + buf = append(buf, n.Prefix.To4()...) // stream_put_in_addr(s, &p->u.prefix4); + case uint16(syscall.AF_INET6): + buf = append(buf, n.Prefix.To16()...) // stream_put(s, &(p->u.prefix6), 16); + default: + return nil, fmt.Errorf("invalid address family: %d", n.Family) + } + + return buf, nil +} + +// Ref: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) +// Ref: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) +// Ref: zread_rnh_register in zebra/zapi_msg.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (n *RegisteredNexthop) decodeFromBytes(data []byte, version uint8, software Software) error { + // Connected (1 byte) + n.connected = uint8(data[0]) + data = data[1:] + if version == 6 && software.name == "frr" && software.version >= 8.2 { + n.resolveViaDef = uint8(data[0]) //STREAM_GETC(s, resolve_via_default); + n.safi = binary.BigEndian.Uint16(data[1:3]) //STREAM_GETW(s, safi); + data = data[3:] + } + // Address Family (2 bytes) + n.Family = binary.BigEndian.Uint16(data[0:2]) + // Note: Ignores Prefix Length (1 byte) + addrByteLen := (int(data[2]) + 7) / 8 + // Prefix (variable) + n.Prefix = ipFromFamily(uint8(n.Family), data[3:3+addrByteLen]) + + return nil +} + +func (n *RegisteredNexthop) string(version uint8, software Software) string { + return fmt.Sprintf( + "connected: %d, resolveViaDef:%d, safi: %d, family: %d, prefix: %s", + n.connected, n.resolveViaDef, n.safi, n.Family, n.Prefix.String()) +} + +// NexthopRegisterBody us referred in zclient +type NexthopRegisterBody struct { + api APIType + Nexthops []*RegisteredNexthop +} + +// Ref: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) +// Ref: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) +// Ref: zclient_send_rnh in lib/zclient.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (b *NexthopRegisterBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 0) + + // List of Registered Nexthops + for _, nh := range b.Nexthops { + nhBuf, err := nh.serialize(version, software) + if err != nil { + return nil, err + } + buf = append(buf, nhBuf...) + } + + return buf, nil +} + +// Ref: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) +// Ref: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) +// Ref: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) +func (b *NexthopRegisterBody) decodeFromBytes(data []byte, version uint8, software Software) error { + offset := 0 + // List of Registered Nexthops + b.Nexthops = []*RegisteredNexthop{} + for len(data[offset:]) > 0 { + nh := new(RegisteredNexthop) + err := nh.decodeFromBytes(data[offset:], version, software) + if err != nil { + return err + } + b.Nexthops = append(b.Nexthops, nh) + + offset += nh.len() + if len(data) < offset { + break + } + } + return nil +} + +func (b *NexthopRegisterBody) string(version uint8, software Software) string { + s := make([]string, 0) + for _, nh := range b.Nexthops { + s = append(s, fmt.Sprintf("nexthop:{%s}", nh.string(version, software))) + } + return strings.Join(s, ", ") +} + +// NexthopUpdateBody uses same data structure as IPRoute (zapi_route) after frr4 (Zapi5) +type NexthopUpdateBody IPRouteBody + +// Ref: send_client in zebra/zebra_rnh.c of Quagga1.2&FRR3&FRR5(ZAPI3&4$5) and until FRR7.4 +// Ref: zebra_send_rnh_update zebra/zebra_rnh.c of FRR7.5&FRR8 +func (b *NexthopUpdateBody) serialize(version uint8, software Software) ([]byte, error) { + var buf []byte + offset := 0 + // Message (4 bytes) // if (srte_color) stream_putl(s, message); + if version == 6 && software.name == "frr" && software.version >= 7.5 { // since frr7.5 + buf = make([]byte, 7) + binary.BigEndian.PutUint32(buf, uint32(b.Message)) + offset += 4 + } else { // until frr7.4 + buf = make([]byte, 3) + } + + // Address Family (2 bytes) + binary.BigEndian.PutUint16(buf[offset:], uint16(b.Prefix.Family)) + addrByteLen, err := addressByteLength(b.Prefix.Family) + if err != nil { + return nil, err + } + + buf[offset+2] = byte(addrByteLen * 8) //stream_putc(s, rn->p.prefixlen); + // Prefix Length (1 byte) + Prefix (variable) + switch b.Prefix.Family { + case syscall.AF_INET: + buf = append(buf, b.Prefix.Prefix.To4()...) + case syscall.AF_INET6: + buf = append(buf, b.Prefix.Prefix.To16()...) + default: + return nil, fmt.Errorf("invalid address family: %d", b.Prefix.Family) + } + // SRTE color // if (srte_color) stream_putl(s, srte_color); + if b.Message&messageSRTE > 0 { // since frr 7.5 + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.srteColor) + buf = append(buf, tmpbuf...) + } + if version >= 5 { + // Type (1 byte) (if version>=5) + // instance (2 bytes) (if version>=5) + buf = append(buf, byte(b.Type)) + tmpbuf := make([]byte, 2) + binary.BigEndian.PutUint16(tmpbuf, b.instance) + buf = append(buf, tmpbuf...) + } + if version >= 4 { + // Distance (1 byte) (if version>=4) + buf = append(buf, b.Distance) + } + // Metric (4 bytes) + tmpbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tmpbuf, b.Metric) + buf = append(buf, tmpbuf...) + // Number of Nexthops (1 byte) + buf = append(buf, uint8(0)) // Temporary code + // ToDo Processing Route Entry + return buf, nil +} + +// Ref: bgp_parse_nexthop_update in bgpd/bgp_nht.c of Quagga1.2&FRR3 (ZAPI3&4) +// Ref: zapi_nexthop_update_decode in lib/zclient.c of FRR5.x&FRR6&FRR7.x&FRR8 (ZAPI5&6) +func (b *NexthopUpdateBody) decodeFromBytes(data []byte, version uint8, software Software) error { + if version == 6 && software.name == "frr" && software.version >= 7.5 { // since frr7.5 + //Message //frr7.5: STREAM_GETL(s, nhr->message); + b.Message = MessageFlag(binary.BigEndian.Uint32(data[0:4])) + data = data[4:] + if software.version >= 8.2 { //added in frr8.2 + b.Safi = Safi(binary.BigEndian.Uint16(data[0:2])) + var match Prefix + match.Family = uint8(binary.BigEndian.Uint16(data[2:4])) // STREAM_GETC(s, match->prefixlen); + match.PrefixLen = data[4] // STREAM_GETC(s, match->prefixlen); + addrByteLen, err := addressByteLength(match.Family) + if err != nil { + return err + } + match.Prefix = ipFromFamily(b.Prefix.Family, data[5:5+addrByteLen]) + data = data[5+addrByteLen:] + } + } + // Address Family (2 bytes) and Prefix Length (1 byte) + prefixFamily := binary.BigEndian.Uint16(data[0:2]) + b.Prefix.Family = uint8(prefixFamily) + b.Prefix.PrefixLen = data[2] + offset := 3 + + addrByteLen, err := addressByteLength(b.Prefix.Family) + if err != nil { + return err + } + + b.Prefix.Prefix = ipFromFamily(b.Prefix.Family, data[offset:offset+addrByteLen]) + offset += addrByteLen + + if b.Message&messageSRTE > 0 { // since frr 7.5 + b.srteColor = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + } + + if version > 4 { + // Route Type (1 byte) and insrance (2 bytes) + b.Type = RouteType(data[offset]) + b.instance = binary.BigEndian.Uint16(data[offset+1 : offset+3]) + offset += 3 + } + // Distance (1 byte) (if version>=4) + if version > 3 { + b.Distance = data[offset] + offset++ + } + // Metric (4 bytes) & Number of Nexthops (1 byte) + if len(data[offset:]) < 5 { + return fmt.Errorf("invalid message length: missing metric(4 bytes) or nexthops(1 byte): %d<5", len(data[offset:])) + } + b.Metric = binary.BigEndian.Uint32(data[offset : offset+4]) + offset += 4 + + numNexthop := uint16(data[offset]) + offset++ + // List of Nexthops + b.Nexthops = []Nexthop{} + + processFlag := nexthopProcessFlag(nexthopHasType) + if version == 6 && software.name == "frr" { + if software.version >= 7.3 { + processFlag |= (nexthopHasVrfID | nexthopHasFlag | nexthopProcessIPToIPIFindex) + } else if software.version >= 7 { + processFlag |= (nexthopHasVrfID | nexthopProcessIPToIPIFindex) + } else if software.version >= 6 { + processFlag |= nexthopProcessIPToIPIFindex + } + } else if version == 5 && software.name == "frr" && software.version == 5 { + processFlag |= nexthopProcessIPToIPIFindex + } else if version < 4 { // quagga + processFlag |= nexthopProcessIFnameToIFindex + } + + // since frr7.3, MessageLabel is deleted + if (version == 6 && software.name == "frr" && software.version < 7.3) || + (version == 5 && software.name == "frr" && software.version == 5) { + b.Message |= MessageLabel + } + + nexthopsByteLen, err := decodeNexthops(&b.Nexthops, data[offset:], version, software, b.Prefix.Family, numNexthop, processFlag, b.Message, Flag(0), nexthopType(0)) + if err != nil { + return err + } + offset += nexthopsByteLen + return nil +} + +func (b *NexthopUpdateBody) string(version uint8, software Software) string { + s := fmt.Sprintf( + "family: %d, prefix: %s, distance: %d, metric: %d", + b.Prefix.Family, b.Prefix.Prefix.String(), b.Distance, b.Metric) + for _, nh := range b.Nexthops { + s = s + fmt.Sprintf(", nexthop:{%s}", nh.string()) + } + return s +} + +type labelManagerConnectBody struct { + redistDefault RouteType + instance uint16 + // The followings are used in response from Zebra + result uint8 // 0 means success +} + +// Ref: lm_label_manager_connect in lib/zclient.c of FRR +func (b *labelManagerConnectBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 3) + buf[0] = uint8(b.redistDefault) + binary.BigEndian.PutUint16(buf[1:3], b.instance) + return buf, nil +} + +func (b *labelManagerConnectBody) decodeFromBytes(data []byte, version uint8, software Software) error { + size := 1 + if version > 4 && !(software.name == "frr" && software.version == 4) { // FRR4 returns result only. + size = 4 + } + if len(data) < size { + return fmt.Errorf("invalid message length for LabelManagerConnect response: %d<%d", + len(data), size) + } + if version > 4 && !(software.name == "frr" && software.version == 4) { + b.redistDefault = RouteType(data[0]) + b.instance = binary.BigEndian.Uint16(data[1:3]) + data = data[3:] + } + b.result = data[0] + return nil +} + +func (b *labelManagerConnectBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "route_type: %s, instance: %d, result: %d", + b.redistDefault.String(), b.instance, b.result) +} + +// GetLabelChunkBody is referred in zclient (Ref: zsend_assign_label_chunk_response) +type GetLabelChunkBody struct { + proto uint8 // it is appeared in FRR5.x and 6.x + instance uint16 // it is appeared in FRR5.x and 6.x + keep uint8 + ChunkSize uint32 + Start uint32 // The followings are used in response from Zebra + End uint32 + base uint32 // it is added in FRR7.2 +} + +// Ref: zread_get_label_chunk in zebra/zserv.c of FRR3.x +// Ref: zread_get_label_chunk in zebra/zapi_msg.c of FRR5.x, 6.x, 7,x, and 8 +func (b *GetLabelChunkBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 12) + pos := 0 + b.base = 0 + if version > 4 && !(software.name == "frr" && software.version == 4) { + buf[pos] = b.proto + binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.instance) + pos += 3 + } + buf[pos] = b.keep + binary.BigEndian.PutUint32(buf[pos+1:pos+5], b.ChunkSize) + pos += 5 + if version == 6 && software.name == "frr" && software.version >= 7.2 { + binary.BigEndian.PutUint32(buf[pos:pos+4], b.base) + pos += 4 + } + return buf[0:pos], nil +} + +// Ref: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x +// Ref: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x, 6.x, 7,x, and 8 +func (b *GetLabelChunkBody) decodeFromBytes(data []byte, version uint8, software Software) error { + size := 9 + if version > 4 && !(software.name == "frr" && software.version == 4) { + size = 12 + } + if len(data) < size { + return fmt.Errorf("invalid message length for GetLabelChunk response: %d<%d", + len(data), size) + } + if version > 4 && !(software.name == "frr" && software.version == 4) { + b.proto = data[0] + b.instance = binary.BigEndian.Uint16(data[1:3]) + data = data[3:] + } + b.keep = data[0] + b.Start = binary.BigEndian.Uint32(data[1:5]) + b.End = binary.BigEndian.Uint32(data[5:9]) + return nil +} + +func (b *GetLabelChunkBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "keep: %d, chunk_size: %d, start: %d, end: %d", + b.keep, b.ChunkSize, b.Start, b.End) +} + +type releaseLabelChunkBody struct { + proto uint8 // it is added in FRR5.x + instance uint16 // it is added in FRR5.x + start uint32 + end uint32 +} + +// Ref: zread_release_label_chunk in zebra/zapi_msg.c of FRR +func (b *releaseLabelChunkBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 11) + pos := 0 + if version > 4 && !(software.name == "frr" && software.version == 4) { + buf[pos] = b.proto + binary.BigEndian.PutUint16(buf[pos+1:pos+3], b.instance) + pos += 3 + } + binary.BigEndian.PutUint32(buf[pos:pos+4], b.start) + binary.BigEndian.PutUint32(buf[pos+4:pos+8], b.end) + pos += 8 + return buf[0:pos], nil +} + +func (b *releaseLabelChunkBody) decodeFromBytes(data []byte, version uint8, software Software) error { + return nil // No response from Zebra +} + +func (b *releaseLabelChunkBody) string(version uint8, software Software) string { + return fmt.Sprintf("start: %d, end: %d", b.start, b.end) +} + +//go:generate stringer -type=lspTYPE +type lspTYPE uint8 + +const ( + lspNone lspTYPE = iota //defined in FRR3 and over + lspStatic //defined in FRR3 and over + lspLDP //defined in FRR3 and over + lspBGP //defined in FRR4 and over + lspSR //defined in FRR4 and over + lspSHARP //defined in FRR5 and over +) + +type vrfLabelBody struct { + label uint32 + afi afi + labelType lspTYPE +} + +// Ref: zclient_send_vrf_label in lib/zclient.c of FRR 5.x, 6.x, 7.x, and 8 +func (b *vrfLabelBody) serialize(version uint8, software Software) ([]byte, error) { + buf := make([]byte, 6) + binary.BigEndian.PutUint32(buf[0:4], b.label) + buf[4] = uint8(b.afi) + buf[5] = uint8(b.labelType) + return buf, nil +} + +// Ref: zread_vrf_label in zebra/zapi_msg.c of FRR 5.x, 6.x, 7.x, and 8 +func (b *vrfLabelBody) decodeFromBytes(data []byte, version uint8, software Software) error { + if len(data) < 6 { + return fmt.Errorf("invalid message length for VRFLabel message: %d<6", len(data)) + } + b.label = binary.BigEndian.Uint32(data[0:4]) + b.afi = afi(data[4]) + b.labelType = lspTYPE(data[5]) + return nil +} + +func (b *vrfLabelBody) string(version uint8, software Software) string { + return fmt.Sprintf( + "label: %d, afi: %s LSP type: %s", + b.label, b.afi, b.labelType) +} + +// Message is referred in zclient +type Message struct { + Header Header + Body Body +} + +func (m *Message) serialize(software Software) ([]byte, error) { + var body []byte + if m.Body != nil { + var err error + body, err = m.Body.serialize(m.Header.Version, software) + if err != nil { + return nil, err + } + } + m.Header.Len = uint16(len(body)) + HeaderSize(m.Header.Version) + hdr, err := m.Header.serialize() + if err != nil { + return nil, err + } + return append(hdr, body...), nil +} + +func parseMessage(hdr *Header, data []byte, software Software) (m *Message, err error) { + m = &Message{Header: *hdr} + /* TODO: + InterfaceNBRAddressAdd, InterfaceNBRAddressDelete, + InterfaceBFDDestUpdate, ImportCheckUpdate, BFDDestReplay, + InterfaceVRFUpdate, InterfaceLinkParams, PWStatusUpdate + */ + command := m.Header.Command.toCommon(m.Header.Version, software) + switch command { + case interfaceAdd, interfaceDelete, interfaceUp, interfaceDown: + m.Body = &interfaceUpdateBody{} + case interfaceAddressAdd, interfaceAddressDelete: + m.Body = &interfaceAddressUpdateBody{} + case routerIDUpdate: + m.Body = &routerIDUpdateBody{} + case nexthopUpdate: + m.Body = &NexthopUpdateBody{} + case redistributeRouteAdd, redistributeRouteDel: // for frr + m.Body = &IPRouteBody{API: m.Header.Command} + case labelManagerConnect: // Note: Synchronous message + m.Body = &labelManagerConnectBody{} + case getLabelChunk: // Note: Synchronous message + m.Body = &GetLabelChunkBody{} + case releaseLabelChunk: // Note: Synchronous message + m.Body = &releaseLabelChunkBody{} + case vrfLabel: + m.Body = &vrfLabelBody{} + case RouteAdd, RouteDelete, BackwardIPv6RouteAdd, BackwardIPv6RouteDelete: // for quagga + m.Body = &IPRouteBody{API: m.Header.Command} + case ipv4NexthopLookupMRIB: + m.Body = &lookupBody{api: m.Header.Command} + default: + m.Body = &unknownBody{} + if m.Header.Version == 4 { + switch m.Header.Command { + case zapi4RedistributeIPv6Add, zapi4RedistributeIPv6Del: // for frr3 + m.Body = &IPRouteBody{API: m.Header.Command} + } + } else if m.Header.Version < 4 { + switch m.Header.Command { + case zapi3IPv4NexthopLookup, zapi3IPv6NexthopLookup, zapi3IPv4ImportLookup: + m.Body = &lookupBody{api: m.Header.Command} + } + } + } + return m, m.Body.decodeFromBytes(data, m.Header.Version, software) +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_bsd.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_bsd.go new file mode 100644 index 000000000..e12d043b8 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_bsd.go @@ -0,0 +1,59 @@ +// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. +// +// 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. + +//go:build freebsd || netbsd || openbsd +// +build freebsd netbsd openbsd + +package zebra + +import ( + "strings" + "syscall" +) + +func intfflag2string(flag uint64) string { + ss := make([]string, 0, 10) + if flag&syscall.IFF_UP > 0 { + ss = append(ss, "UP") + } + if flag&syscall.IFF_BROADCAST > 0 { + ss = append(ss, "BROADCAST") + } + if flag&syscall.IFF_DEBUG > 0 { + ss = append(ss, "DEBUG") + } + if flag&syscall.IFF_LOOPBACK > 0 { + ss = append(ss, "LOOPBACK") + } + if flag&syscall.IFF_POINTOPOINT > 0 { + ss = append(ss, "POINTOPOINT") + } + if flag&syscall.IFF_RUNNING > 0 { + ss = append(ss, "RUNNING") + } + if flag&syscall.IFF_NOARP > 0 { + ss = append(ss, "NOARP") + } + if flag&syscall.IFF_PROMISC > 0 { + ss = append(ss, "PROMISC") + } + if flag&syscall.IFF_ALLMULTI > 0 { + ss = append(ss, "ALLMULTI") + } + if flag&syscall.IFF_MULTICAST > 0 { + ss = append(ss, "MULTICAST") + } + return strings.Join(ss, " | ") +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_darwin.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_darwin.go new file mode 100644 index 000000000..a25369130 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_darwin.go @@ -0,0 +1,59 @@ +// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 zebra + +import ( + "strings" + "syscall" +) + +func intfflag2string(flag uint64) string { + ss := make([]string, 0, 10) + if flag&syscall.IFF_UP > 0 { + ss = append(ss, "UP") + } + if flag&syscall.IFF_BROADCAST > 0 { + ss = append(ss, "BROADCAST") + } + if flag&syscall.IFF_DEBUG > 0 { + ss = append(ss, "DEBUG") + } + if flag&syscall.IFF_LOOPBACK > 0 { + ss = append(ss, "LOOPBACK") + } + if flag&syscall.IFF_POINTOPOINT > 0 { + ss = append(ss, "POINTOPOINT") + } + if flag&syscall.IFF_NOTRAILERS > 0 { + ss = append(ss, "NOTRAILERS") + } + if flag&syscall.IFF_RUNNING > 0 { + ss = append(ss, "RUNNING") + } + if flag&syscall.IFF_NOARP > 0 { + ss = append(ss, "NOARP") + } + if flag&syscall.IFF_PROMISC > 0 { + ss = append(ss, "PROMISC") + } + if flag&syscall.IFF_ALLMULTI > 0 { + ss = append(ss, "ALLMULTI") + } + if flag&syscall.IFF_MULTICAST > 0 { + ss = append(ss, "MULTICAST") + } + return strings.Join(ss, " | ") +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_linux.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_linux.go new file mode 100644 index 000000000..66fccb741 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_linux.go @@ -0,0 +1,83 @@ +// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 zebra + +import ( + "strings" + "syscall" +) + +func intfflag2string(flag uint64) string { + ss := make([]string, 0, 10) + if flag&syscall.IFF_UP > 0 { + ss = append(ss, "UP") + } + if flag&syscall.IFF_BROADCAST > 0 { + ss = append(ss, "BROADCAST") + } + if flag&syscall.IFF_DEBUG > 0 { + ss = append(ss, "DEBUG") + } + if flag&syscall.IFF_LOOPBACK > 0 { + ss = append(ss, "LOOPBACK") + } + if flag&syscall.IFF_POINTOPOINT > 0 { + ss = append(ss, "POINTOPOINT") + } + if flag&syscall.IFF_NOTRAILERS > 0 { + ss = append(ss, "NOTRAILERS") + } + if flag&syscall.IFF_RUNNING > 0 { + ss = append(ss, "RUNNING") + } + if flag&syscall.IFF_NOARP > 0 { + ss = append(ss, "NOARP") + } + if flag&syscall.IFF_PROMISC > 0 { + ss = append(ss, "PROMISC") + } + if flag&syscall.IFF_ALLMULTI > 0 { + ss = append(ss, "ALLMULTI") + } + if flag&syscall.IFF_MASTER > 0 { + ss = append(ss, "MASTER") + } + if flag&syscall.IFF_SLAVE > 0 { + ss = append(ss, "SLAVE") + } + if flag&syscall.IFF_MULTICAST > 0 { + ss = append(ss, "MULTICAST") + } + if flag&syscall.IFF_PORTSEL > 0 { + ss = append(ss, "PORTSEL") + } + if flag&syscall.IFF_AUTOMEDIA > 0 { + ss = append(ss, "AUTOMEDIA") + } + if flag&syscall.IFF_DYNAMIC > 0 { + ss = append(ss, "DYNAMIC") + } + // if flag&syscall.IFF_LOWER_UP > 0 { + // ss = append(ss, "LOWER_UP") + // } + // if flag&syscall.IFF_DORMANT > 0 { + // ss = append(ss, "DORMANT") + // } + // if flag&syscall.IFF_ECHO > 0 { + // ss = append(ss, "ECHO") + // } + return strings.Join(ss, " | ") +} diff --git a/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_windows.go b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_windows.go new file mode 100644 index 000000000..d55525db1 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_windows.go @@ -0,0 +1,38 @@ +// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation. +// +// 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 zebra + +import ( + "strings" + "syscall" +) + +func intfflag2string(flag uint64) string { + ss := make([]string, 0, 10) + if flag&syscall.IFF_UP > 0 { + ss = append(ss, "UP") + } + if flag&syscall.IFF_BROADCAST > 0 { + ss = append(ss, "BROADCAST") + } + if flag&syscall.IFF_LOOPBACK > 0 { + ss = append(ss, "LOOPBACK") + } + if flag&syscall.IFF_MULTICAST > 0 { + ss = append(ss, "MULTICAST") + } + return strings.Join(ss, " | ") +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/attribute.go b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/attribute.go new file mode 100644 index 000000000..e1534c44f --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/attribute.go @@ -0,0 +1,2406 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// 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 apiutil + +import ( + "errors" + "fmt" + "net" + "net/netip" + + "google.golang.org/protobuf/proto" + apb "google.golang.org/protobuf/types/known/anypb" + + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" +) + +func UnmarshalAttribute(an *apb.Any) (bgp.PathAttributeInterface, error) { + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err) + } + switch a := value.(type) { + case *api.OriginAttribute: + return bgp.NewPathAttributeOrigin(uint8(a.Origin)), nil + case *api.AsPathAttribute: + params := make([]bgp.AsPathParamInterface, 0, len(a.Segments)) + for _, segment := range a.Segments { + params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers)) + } + return bgp.NewPathAttributeAsPath(params), nil + case *api.NextHopAttribute: + nexthop := net.ParseIP(a.NextHop).To4() + if nexthop == nil { + if nexthop = net.ParseIP(a.NextHop).To16(); nexthop == nil { + return nil, fmt.Errorf("invalid nexthop address: %s", a.NextHop) + } + } + return bgp.NewPathAttributeNextHop(a.NextHop), nil + case *api.MultiExitDiscAttribute: + return bgp.NewPathAttributeMultiExitDisc(a.Med), nil + case *api.LocalPrefAttribute: + return bgp.NewPathAttributeLocalPref(a.LocalPref), nil + case *api.AtomicAggregateAttribute: + return bgp.NewPathAttributeAtomicAggregate(), nil + case *api.AggregatorAttribute: + if net.ParseIP(a.Address).To4() == nil { + return nil, fmt.Errorf("invalid aggregator address: %s", a.Address) + } + return bgp.NewPathAttributeAggregator(a.Asn, a.Address), nil + case *api.CommunitiesAttribute: + return bgp.NewPathAttributeCommunities(a.Communities), nil + case *api.OriginatorIdAttribute: + if net.ParseIP(a.Id).To4() == nil { + return nil, fmt.Errorf("invalid originator id: %s", a.Id) + } + return bgp.NewPathAttributeOriginatorId(a.Id), nil + case *api.ClusterListAttribute: + for _, id := range a.Ids { + if net.ParseIP(id).To4() == nil { + return nil, fmt.Errorf("invalid cluster list: %s", a.Ids) + } + } + return bgp.NewPathAttributeClusterList(a.Ids), nil + case *api.MpReachNLRIAttribute: + if a.Family == nil { + return nil, fmt.Errorf("empty family") + } + rf := ToRouteFamily(a.Family) + nlris, err := UnmarshalNLRIs(rf, a.Nlris) + if err != nil { + return nil, err + } + afi, safi := bgp.RouteFamilyToAfiSafi(rf) + nexthop := "0.0.0.0" + var linkLocalNexthop net.IP + if afi == bgp.AFI_IP6 { + nexthop = "::" + if len(a.NextHops) > 1 { + linkLocalNexthop = net.ParseIP(a.NextHops[1]).To16() + if linkLocalNexthop == nil { + return nil, fmt.Errorf("invalid nexthop: %s", a.NextHops[1]) + } + } + } + if safi == bgp.SAFI_FLOW_SPEC_UNICAST || safi == bgp.SAFI_FLOW_SPEC_VPN { + nexthop = "" + } else if len(a.NextHops) > 0 { + nexthop = a.NextHops[0] + if net.ParseIP(nexthop) == nil { + return nil, fmt.Errorf("invalid nexthop: %s", nexthop) + } + } + attr := bgp.NewPathAttributeMpReachNLRI(nexthop, nlris) + attr.LinkLocalNexthop = linkLocalNexthop + return attr, nil + case *api.MpUnreachNLRIAttribute: + rf := ToRouteFamily(a.Family) + nlris, err := UnmarshalNLRIs(rf, a.Nlris) + if err != nil { + return nil, err + } + return bgp.NewPathAttributeMpUnreachNLRI(nlris), nil + case *api.ExtendedCommunitiesAttribute: + return unmarshalExComm(a) + case *api.As4PathAttribute: + params := make([]*bgp.As4PathParam, 0, len(a.Segments)) + for _, segment := range a.Segments { + params = append(params, bgp.NewAs4PathParam(uint8(segment.Type), segment.Numbers)) + } + return bgp.NewPathAttributeAs4Path(params), nil + case *api.As4AggregatorAttribute: + if net.ParseIP(a.Address).To4() == nil { + return nil, fmt.Errorf("invalid as4 aggregator address: %s", a.Address) + } + return bgp.NewPathAttributeAs4Aggregator(a.Asn, a.Address), nil + case *api.PmsiTunnelAttribute: + typ := bgp.PmsiTunnelType(a.Type) + var isLeafInfoRequired bool + if a.Flags&0x01 > 0 { + isLeafInfoRequired = true + } + var id bgp.PmsiTunnelIDInterface + switch typ { + case bgp.PMSI_TUNNEL_TYPE_INGRESS_REPL: + ip := net.IP(a.Id) + if ip.To4() == nil && ip.To16() == nil { + return nil, fmt.Errorf("invalid pmsi tunnel identifier: %s", a.Id) + } + id = bgp.NewIngressReplTunnelID(ip.String()) + default: + id = bgp.NewDefaultPmsiTunnelID(a.Id) + } + return bgp.NewPathAttributePmsiTunnel(typ, isLeafInfoRequired, a.Label, id), nil + case *api.TunnelEncapAttribute: + tlvs := make([]*bgp.TunnelEncapTLV, 0, len(a.Tlvs)) + for _, tlv := range a.Tlvs { + subTlvs := make([]bgp.TunnelEncapSubTLVInterface, 0, len(tlv.Tlvs)) + for _, an := range tlv.Tlvs { + var subTlv bgp.TunnelEncapSubTLVInterface + subValue, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + switch sv := subValue.(type) { + case *api.TunnelEncapSubTLVEncapsulation: + subTlv = bgp.NewTunnelEncapSubTLVEncapsulation(sv.Key, sv.Cookie) + case *api.TunnelEncapSubTLVProtocol: + subTlv = bgp.NewTunnelEncapSubTLVProtocol(uint16(sv.Protocol)) + case *api.TunnelEncapSubTLVColor: + subTlv = bgp.NewTunnelEncapSubTLVColor(sv.Color) + case *api.TunnelEncapSubTLVEgressEndpoint: + subTlv = bgp.NewTunnelEncapSubTLVEgressEndpoint(sv.Address) + case *api.TunnelEncapSubTLVUDPDestPort: + subTlv = bgp.NewTunnelEncapSubTLVUDPDestPort(uint16(sv.Port)) + case *api.TunnelEncapSubTLVSRPreference: + subTlv = bgp.NewTunnelEncapSubTLVSRPreference(sv.Flags, sv.Preference) + case *api.TunnelEncapSubTLVSRPriority: + subTlv = bgp.NewTunnelEncapSubTLVSRPriority(uint8(sv.Priority)) + case *api.TunnelEncapSubTLVSRCandidatePathName: + subTlv = bgp.NewTunnelEncapSubTLVSRCandidatePathName(sv.CandidatePathName) + case *api.TunnelEncapSubTLVSRENLP: + subTlv = bgp.NewTunnelEncapSubTLVSRENLP(sv.Flags, bgp.SRENLPValue(sv.Enlp)) + case *api.TunnelEncapSubTLVSRBindingSID: + var err error + subTlv, err = UnmarshalSRBSID(sv.Bsid) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + case *api.TunnelEncapSubTLVSRSegmentList: + var err error + weight := uint32(0) + flags := uint8(0) + if sv.Weight != nil { + weight = sv.Weight.Weight + flags = uint8(sv.Weight.Flags) + } + s := &bgp.TunnelEncapSubTLVSRSegmentList{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST, + Length: uint16(6), // Weight (6 bytes) + length of segment (added later, after all segments are discovered) + }, + Weight: &bgp.SegmentListWeight{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.SegmentListSubTLVWeight, + Length: uint16(6), + }, + Flags: flags, + Weight: weight, + }, + Segments: make([]bgp.TunnelEncapSubTLVInterface, 0), + } + if len(sv.Segments) != 0 { + s.Segments, err = UnmarshalSRSegments(sv.Segments) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + } + // Get total length of Segment List Sub TLV + for _, seg := range s.Segments { + s.TunnelEncapSubTLV.Length += uint16(seg.Len() + 2) // Adding 1 byte of type and 1 byte of length for each Segment object + } + subTlv = s + case *api.TunnelEncapSubTLVUnknown: + subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value) + default: + return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v type: %T", subValue, sv) + } + subTlvs = append(subTlvs, subTlv) + } + tlvs = append(tlvs, bgp.NewTunnelEncapTLV(bgp.TunnelType(tlv.Type), subTlvs)) + } + return bgp.NewPathAttributeTunnelEncap(tlvs), nil + case *api.IP6ExtendedCommunitiesAttribute: + communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities)) + for _, an := range a.Communities { + var community bgp.ExtendedCommunityInterface + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal ipv6 extended community: %s", err) + } + switch v := value.(type) { + case *api.IPv6AddressSpecificExtended: + community = bgp.NewIPv6AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + case *api.RedirectIPv6AddressSpecificExtended: + community = bgp.NewRedirectIPv6AddressSpecificExtended(v.Address, uint16(v.LocalAdmin)) + } + if community == nil { + return nil, fmt.Errorf("invalid ipv6 extended community: %v", value) + } + communities = append(communities, community) + } + return bgp.NewPathAttributeIP6ExtendedCommunities(communities), nil + + case *api.AigpAttribute: + tlvs := make([]bgp.AigpTLVInterface, 0, len(a.Tlvs)) + for _, an := range a.Tlvs { + var tlv bgp.AigpTLVInterface + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal aigp attribute tlv: %s", err) + } + switch v := value.(type) { + case *api.AigpTLVIGPMetric: + tlv = bgp.NewAigpTLVIgpMetric(v.Metric) + case *api.AigpTLVUnknown: + tlv = bgp.NewAigpTLVDefault(bgp.AigpTLVType(v.Type), v.Value) + } + if tlv == nil { + return nil, fmt.Errorf("invalid aigp attribute tlv: %v", value) + } + tlvs = append(tlvs, tlv) + } + return bgp.NewPathAttributeAigp(tlvs), nil + + case *api.LargeCommunitiesAttribute: + communities := make([]*bgp.LargeCommunity, 0, len(a.Communities)) + for _, c := range a.Communities { + communities = append(communities, bgp.NewLargeCommunity(c.GlobalAdmin, c.LocalData1, c.LocalData2)) + } + return bgp.NewPathAttributeLargeCommunities(communities), nil + case *api.PrefixSID: + return UnmarshalPrefixSID(a) + case *api.UnknownAttribute: + return bgp.NewPathAttributeUnknown(bgp.BGPAttrFlag(a.Flags), bgp.BGPAttrType(a.Type), a.Value), nil + } + return nil, errors.New("unknown path attribute") +} + +func NewOriginAttributeFromNative(a *bgp.PathAttributeOrigin) (*api.OriginAttribute, error) { + return &api.OriginAttribute{ + Origin: uint32(a.Value), + }, nil +} + +func NewAsPathAttributeFromNative(a *bgp.PathAttributeAsPath) (*api.AsPathAttribute, error) { + segments := make([]*api.AsSegment, 0, len(a.Value)) + for _, param := range a.Value { + segments = append(segments, &api.AsSegment{ + Type: api.AsSegment_Type(param.GetType()), + Numbers: param.GetAS(), + }) + } + return &api.AsPathAttribute{ + Segments: segments, + }, nil +} + +func NewNextHopAttributeFromNative(a *bgp.PathAttributeNextHop) (*api.NextHopAttribute, error) { + return &api.NextHopAttribute{ + NextHop: a.Value.String(), + }, nil +} + +func NewMultiExitDiscAttributeFromNative(a *bgp.PathAttributeMultiExitDisc) (*api.MultiExitDiscAttribute, error) { + return &api.MultiExitDiscAttribute{ + Med: a.Value, + }, nil +} + +func NewLocalPrefAttributeFromNative(a *bgp.PathAttributeLocalPref) (*api.LocalPrefAttribute, error) { + return &api.LocalPrefAttribute{ + LocalPref: a.Value, + }, nil +} + +func NewAtomicAggregateAttributeFromNative(a *bgp.PathAttributeAtomicAggregate) (*api.AtomicAggregateAttribute, error) { + return &api.AtomicAggregateAttribute{}, nil +} + +func NewAggregatorAttributeFromNative(a *bgp.PathAttributeAggregator) (*api.AggregatorAttribute, error) { + return &api.AggregatorAttribute{ + Asn: a.Value.AS, + Address: a.Value.Address.String(), + }, nil +} + +func NewCommunitiesAttributeFromNative(a *bgp.PathAttributeCommunities) (*api.CommunitiesAttribute, error) { + return &api.CommunitiesAttribute{ + Communities: a.Value, + }, nil +} + +func NewOriginatorIdAttributeFromNative(a *bgp.PathAttributeOriginatorId) (*api.OriginatorIdAttribute, error) { + return &api.OriginatorIdAttribute{ + Id: a.Value.String(), + }, nil +} + +func NewClusterListAttributeFromNative(a *bgp.PathAttributeClusterList) (*api.ClusterListAttribute, error) { + ids := make([]string, 0, len(a.Value)) + for _, id := range a.Value { + ids = append(ids, id.String()) + } + return &api.ClusterListAttribute{ + Ids: ids, + }, nil +} + +func NewPrefixSIDAttributeFromNative(a *bgp.PathAttributePrefixSID) (*api.PrefixSID, error) { + var err error + psid := &api.PrefixSID{} + psid.Tlvs, err = MarshalSRv6TLVs(a.TLVs) + if err != nil { + return nil, err + } + return psid, nil +} + +func MarshalSRv6TLVs(tlvs []bgp.PrefixSIDTLVInterface) ([]*apb.Any, error) { + var err error + mtlvs := make([]*apb.Any, len(tlvs)) + for i, tlv := range tlvs { + var r proto.Message + switch t := tlv.(type) { + case *bgp.SRv6L3ServiceAttribute: + o := &api.SRv6L3ServiceTLV{} + o.SubTlvs, err = MarshalSRv6SubTLVs(t.SubTLVs) + if err != nil { + return nil, err + } + r = o + case *bgp.SRv6ServiceTLV: + switch t.TLV.Type { + case bgp.TLVTypeSRv6L3Service: + o := &api.SRv6L3ServiceTLV{} + o.SubTlvs, err = MarshalSRv6SubTLVs(t.SubTLVs) + if err != nil { + return nil, err + } + r = o + case bgp.TLVTypeSRv6L2Service: + o := &api.SRv6L2ServiceTLV{} + o.SubTlvs, err = MarshalSRv6SubTLVs(t.SubTLVs) + if err != nil { + return nil, err + } + r = o + } + default: + return nil, fmt.Errorf("invalid prefix sid tlv type to marshal %v", t) + } + a, _ := apb.New(r) + mtlvs[i] = a + } + + return mtlvs, nil +} + +func MarshalSRv6SubTLVs(tlvs []bgp.PrefixSIDTLVInterface) (map[uint32]*api.SRv6TLV, error) { + mtlvs := make(map[uint32]*api.SRv6TLV) + var key uint32 + for _, tlv := range tlvs { + var r proto.Message + switch t := tlv.(type) { + case *bgp.SRv6InformationSubTLV: + o := &api.SRv6InformationSubTLV{ + EndpointBehavior: uint32(t.EndpointBehavior), + // TODO Once flags are used in RFC, add processing. + Flags: &api.SRv6SIDFlags{}, + } + o.Sid = make([]byte, len(t.SID)) + copy(o.Sid, t.SID) + var err error + o.SubSubTlvs, err = MarshalSRv6SubSubTLVs(t.SubSubTLVs) + if err != nil { + return nil, err + } + // SRv6 Information Sub TLV is type 1 Sub TLV + key = 1 + r = o + default: + return nil, fmt.Errorf("invalid prefix sid sub tlv type to marshal: %v", t) + } + a, _ := apb.New(r) + tlvs, ok := mtlvs[key] + if !ok { + tlvs = &api.SRv6TLV{ + Tlv: make([]*apb.Any, 0), + } + mtlvs[key] = tlvs + } + tlvs.Tlv = append(tlvs.Tlv, a) + } + + return mtlvs, nil +} + +func MarshalSRv6SubSubTLVs(tlvs []bgp.PrefixSIDTLVInterface) (map[uint32]*api.SRv6TLV, error) { + mtlvs := make(map[uint32]*api.SRv6TLV) + var key uint32 + for _, tlv := range tlvs { + var r proto.Message + switch t := tlv.(type) { + case *bgp.SRv6SIDStructureSubSubTLV: + o := &api.SRv6StructureSubSubTLV{ + LocatorBlockLength: uint32(t.LocatorBlockLength), + LocatorNodeLength: uint32(t.LocatorNodeLength), + FunctionLength: uint32(t.FunctionLength), + ArgumentLength: uint32(t.ArgumentLength), + TranspositionLength: uint32(t.TranspositionLength), + TranspositionOffset: uint32(t.TranspositionOffset), + } + // SRv6 SID Structure Sub Sub TLV is type 1 Sub Sub TLV + key = 1 + r = o + default: + return nil, fmt.Errorf("invalid prefix sid sub sub tlv type to marshal: %v", t) + } + a, _ := apb.New(r) + tlvs, ok := mtlvs[key] + if !ok { + tlvs = &api.SRv6TLV{ + Tlv: make([]*apb.Any, 0), + } + mtlvs[key] = tlvs + } + tlvs.Tlv = append(tlvs.Tlv, a) + } + return mtlvs, nil +} + +func MarshalRD(rd bgp.RouteDistinguisherInterface) (*apb.Any, error) { + var r proto.Message + switch v := rd.(type) { + case *bgp.RouteDistinguisherTwoOctetAS: + r = &api.RouteDistinguisherTwoOctetASN{ + Admin: uint32(v.Admin), + Assigned: v.Assigned, + } + case *bgp.RouteDistinguisherIPAddressAS: + r = &api.RouteDistinguisherIPAddress{ + Admin: v.Admin.String(), + Assigned: uint32(v.Assigned), + } + case *bgp.RouteDistinguisherFourOctetAS: + r = &api.RouteDistinguisherFourOctetASN{ + Admin: v.Admin, + Assigned: uint32(v.Assigned), + } + default: + return nil, fmt.Errorf("invalid rd type to marshal: %v", rd) + } + a, _ := apb.New(r) + return a, nil +} + +func UnmarshalRD(a *apb.Any) (bgp.RouteDistinguisherInterface, error) { + value, err := a.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal route distinguisher: %s", err) + } + switch v := value.(type) { + case *api.RouteDistinguisherTwoOctetASN: + return bgp.NewRouteDistinguisherTwoOctetAS(uint16(v.Admin), v.Assigned), nil + case *api.RouteDistinguisherIPAddress: + rd := bgp.NewRouteDistinguisherIPAddressAS(v.Admin, uint16(v.Assigned)) + if rd == nil { + return nil, fmt.Errorf("invalid address for route distinguisher: %s", v.Admin) + } + return rd, nil + case *api.RouteDistinguisherFourOctetASN: + return bgp.NewRouteDistinguisherFourOctetAS(v.Admin, uint16(v.Assigned)), nil + } + return nil, fmt.Errorf("invalid route distinguisher type: %s", a.TypeUrl) +} + +func NewEthernetSegmentIdentifierFromNative(a *bgp.EthernetSegmentIdentifier) (*api.EthernetSegmentIdentifier, error) { + return &api.EthernetSegmentIdentifier{ + Type: uint32(a.Type), + Value: a.Value, + }, nil +} + +func unmarshalESI(a *api.EthernetSegmentIdentifier) (*bgp.EthernetSegmentIdentifier, error) { + return &bgp.EthernetSegmentIdentifier{ + Type: bgp.ESIType(a.Type), + Value: a.Value, + }, nil +} + +func MarshalFlowSpecRules(values []bgp.FlowSpecComponentInterface) ([]*apb.Any, error) { + rules := make([]*apb.Any, 0, len(values)) + for _, value := range values { + var rule proto.Message + switch v := value.(type) { + case *bgp.FlowSpecDestinationPrefix: + rule = &api.FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(), + } + case *bgp.FlowSpecSourcePrefix: + rule = &api.FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPAddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPAddrPrefix).Prefix.String(), + } + case *bgp.FlowSpecDestinationPrefix6: + rule = &api.FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(), + Offset: uint32(v.Offset), + } + case *bgp.FlowSpecSourcePrefix6: + rule = &api.FlowSpecIPPrefix{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_PREFIX), + PrefixLen: uint32(v.Prefix.(*bgp.IPv6AddrPrefix).Length), + Prefix: v.Prefix.(*bgp.IPv6AddrPrefix).Prefix.String(), + Offset: uint32(v.Offset), + } + case *bgp.FlowSpecSourceMac: + rule = &api.FlowSpecMAC{ + Type: uint32(bgp.FLOW_SPEC_TYPE_SRC_MAC), + Address: v.Mac.String(), + } + case *bgp.FlowSpecDestinationMac: + rule = &api.FlowSpecMAC{ + Type: uint32(bgp.FLOW_SPEC_TYPE_DST_MAC), + Address: v.Mac.String(), + } + case *bgp.FlowSpecComponent: + items := make([]*api.FlowSpecComponentItem, 0, len(v.Items)) + for _, i := range v.Items { + items = append(items, &api.FlowSpecComponentItem{ + Op: uint32(i.Op), + Value: i.Value, + }) + } + rule = &api.FlowSpecComponent{ + Type: uint32(v.Type()), + Items: items, + } + } + a, _ := apb.New(rule) + rules = append(rules, a) + } + return rules, nil +} + +func UnmarshalFlowSpecRules(values []*apb.Any) ([]bgp.FlowSpecComponentInterface, error) { + rules := make([]bgp.FlowSpecComponentInterface, 0, len(values)) + for _, an := range values { + var rule bgp.FlowSpecComponentInterface + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal flow spec component: %s", err) + } + switch v := value.(type) { + case *api.FlowSpecIPPrefix: + typ := bgp.BGPFlowSpecType(v.Type) + isIPv4 := net.ParseIP(v.Prefix).To4() != nil + switch { + case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && isIPv4: + rule = bgp.NewFlowSpecDestinationPrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix)) + case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && isIPv4: + rule = bgp.NewFlowSpecSourcePrefix(bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix)) + case typ == bgp.FLOW_SPEC_TYPE_DST_PREFIX && !isIPv4: + rule = bgp.NewFlowSpecDestinationPrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset)) + case typ == bgp.FLOW_SPEC_TYPE_SRC_PREFIX && !isIPv4: + rule = bgp.NewFlowSpecSourcePrefix6(bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix), uint8(v.Offset)) + } + case *api.FlowSpecMAC: + typ := bgp.BGPFlowSpecType(v.Type) + mac, err := net.ParseMAC(v.Address) + if err != nil { + return nil, fmt.Errorf("invalid mac address for %s flow spec component: %s", typ.String(), v.Address) + } + switch typ { + case bgp.FLOW_SPEC_TYPE_SRC_MAC: + rule = bgp.NewFlowSpecSourceMac(mac) + case bgp.FLOW_SPEC_TYPE_DST_MAC: + rule = bgp.NewFlowSpecDestinationMac(mac) + } + case *api.FlowSpecComponent: + items := make([]*bgp.FlowSpecComponentItem, 0, len(v.Items)) + for _, item := range v.Items { + items = append(items, bgp.NewFlowSpecComponentItem(uint8(item.Op), item.Value)) + } + rule = bgp.NewFlowSpecComponent(bgp.BGPFlowSpecType(v.Type), items) + } + if rule == nil { + return nil, fmt.Errorf("invalid flow spec component: %v", value) + } + rules = append(rules, rule) + } + return rules, nil +} + +func MarshalLsNodeDescriptor(d *bgp.LsNodeDescriptor) (*api.LsNodeDescriptor, error) { + return &api.LsNodeDescriptor{ + Asn: d.Asn, + BgpLsId: d.BGPLsID, + OspfAreaId: d.OspfAreaID, + Pseudonode: d.PseudoNode, + IgpRouterId: d.IGPRouterID, + }, nil +} + +func MarshalLsLinkDescriptor(n *bgp.LsLinkDescriptor) (*api.LsLinkDescriptor, error) { + return &api.LsLinkDescriptor{ + LinkLocalId: uint32OrDefault(n.LinkLocalID), + LinkRemoteId: uint32OrDefault(n.LinkRemoteID), + InterfaceAddrIpv4: ipOrDefault(n.InterfaceAddrIPv4), + NeighborAddrIpv4: ipOrDefault(n.NeighborAddrIPv4), + InterfaceAddrIpv6: ipOrDefault(n.InterfaceAddrIPv6), + NeighborAddrIpv6: ipOrDefault(n.NeighborAddrIPv6), + }, nil +} + +func MarshalLsPrefixDescriptor(d *bgp.LsPrefixDescriptor) (*api.LsPrefixDescriptor, error) { + p := &api.LsPrefixDescriptor{ + OspfRouteType: api.LsOspfRouteType(d.OSPFRouteType), + } + + for _, ip := range d.IPReachability { + p.IpReachability = append(p.IpReachability, ip.String()) + } + return p, nil +} + +func MarshalLsNodeNLRI(n *bgp.LsNodeNLRI) (*apb.Any, error) { + ln, err := MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()) + if err != nil { + return nil, err + } + node := &api.LsNodeNLRI{ + LocalNode: ln, + } + a, _ := apb.New(node) + + return a, nil +} + +func MarshalLsLinkNLRI(n *bgp.LsLinkNLRI) (*apb.Any, error) { + desc := &bgp.LsLinkDescriptor{} + desc.ParseTLVs(n.LinkDesc) + + var err error + ln, err := MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()) + if err != nil { + return nil, err + } + rn, err := MarshalLsNodeDescriptor(n.RemoteNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()) + if err != nil { + return nil, err + } + + ld, err := MarshalLsLinkDescriptor(desc) + if err != nil { + return nil, err + } + + link := &api.LsLinkNLRI{ + LocalNode: ln, + RemoteNode: rn, + LinkDescriptor: ld, + } + a, _ := apb.New(link) + + return a, nil +} + +func MarshalLsPrefixV4NLRI(n *bgp.LsPrefixV4NLRI) (*apb.Any, error) { + desc := &bgp.LsPrefixDescriptor{} + desc.ParseTLVs(n.PrefixDesc, false) + + ln, err := MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()) + if err != nil { + return nil, err + } + + pd, err := MarshalLsPrefixDescriptor(desc) + if err != nil { + return nil, err + } + + prefix := &api.LsPrefixV4NLRI{ + LocalNode: ln, + PrefixDescriptor: pd, + } + a, _ := apb.New(prefix) + + return a, nil +} + +func MarshalLsPrefixV6NLRI(n *bgp.LsPrefixV6NLRI) (*apb.Any, error) { + desc := &bgp.LsPrefixDescriptor{} + desc.ParseTLVs(n.PrefixDesc, true) + + ln, err := MarshalLsNodeDescriptor(n.LocalNodeDesc.(*bgp.LsTLVNodeDescriptor).Extract()) + if err != nil { + return nil, err + } + + pd, err := MarshalLsPrefixDescriptor(desc) + if err != nil { + return nil, err + } + + prefix := &api.LsPrefixV6NLRI{ + LocalNode: ln, + PrefixDescriptor: pd, + } + a, _ := apb.New(prefix) + + return a, nil +} + +func MarshalNLRI(value bgp.AddrPrefixInterface) (*apb.Any, error) { + var nlri proto.Message + + switch v := value.(type) { + case *bgp.IPAddrPrefix: + nlri = &api.IPAddressPrefix{ + PrefixLen: uint32(v.Length), + Prefix: v.Prefix.String(), + } + case *bgp.IPv6AddrPrefix: + nlri = &api.IPAddressPrefix{ + PrefixLen: uint32(v.Length), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledIPAddrPrefix: + nlri = &api.LabeledIPAddressPrefix{ + Labels: v.Labels.Labels, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledIPv6AddrPrefix: + nlri = &api.LabeledIPAddressPrefix{ + Labels: v.Labels.Labels, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.EncapNLRI: + nlri = &api.EncapsulationNLRI{ + Address: v.String(), + } + case *bgp.Encapv6NLRI: + nlri = &api.EncapsulationNLRI{ + Address: v.String(), + } + case *bgp.EVPNNLRI: + switch r := v.RouteTypeData.(type) { + case *bgp.EVPNEthernetAutoDiscoveryRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + esi, err := NewEthernetSegmentIdentifierFromNative(&r.ESI) + if err != nil { + return nil, err + } + + nlri = &api.EVPNEthernetAutoDiscoveryRoute{ + Rd: rd, + Esi: esi, + EthernetTag: r.ETag, + Label: r.Label, + } + case *bgp.EVPNMacIPAdvertisementRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + esi, err := NewEthernetSegmentIdentifierFromNative(&r.ESI) + if err != nil { + return nil, err + } + + nlri = &api.EVPNMACIPAdvertisementRoute{ + Rd: rd, + Esi: esi, + EthernetTag: r.ETag, + MacAddress: r.MacAddress.String(), + IpAddress: r.IPAddress.String(), + Labels: r.Labels, + } + case *bgp.EVPNMulticastEthernetTagRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + nlri = &api.EVPNInclusiveMulticastEthernetTagRoute{ + Rd: rd, + EthernetTag: r.ETag, + IpAddress: r.IPAddress.String(), + } + case *bgp.EVPNEthernetSegmentRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + esi, err := NewEthernetSegmentIdentifierFromNative(&r.ESI) + if err != nil { + return nil, err + } + nlri = &api.EVPNEthernetSegmentRoute{ + Rd: rd, + Esi: esi, + IpAddress: r.IPAddress.String(), + } + case *bgp.EVPNIPPrefixRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + esi, err := NewEthernetSegmentIdentifierFromNative(&r.ESI) + if err != nil { + return nil, err + } + nlri = &api.EVPNIPPrefixRoute{ + Rd: rd, + Esi: esi, + EthernetTag: r.ETag, + IpPrefix: r.IPPrefix.String(), + IpPrefixLen: uint32(r.IPPrefixLength), + Label: r.Label, + GwAddress: r.GWIPAddress.String(), + } + } + case *bgp.LabeledVPNIPAddrPrefix: + rd, err := MarshalRD(v.RD) + if err != nil { + return nil, err + } + nlri = &api.LabeledVPNIPAddressPrefix{ + Labels: v.Labels.Labels, + Rd: rd, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.LabeledVPNIPv6AddrPrefix: + rd, err := MarshalRD(v.RD) + if err != nil { + return nil, err + } + nlri = &api.LabeledVPNIPAddressPrefix{ + Labels: v.Labels.Labels, + Rd: rd, + PrefixLen: uint32(v.IPPrefixLen()), + Prefix: v.Prefix.String(), + } + case *bgp.RouteTargetMembershipNLRI: + rt, err := MarshalRT(v.RouteTarget) + if err != nil { + return nil, err + } + nlri = &api.RouteTargetMembershipNLRI{ + Asn: v.AS, + Rt: rt, + } + case *bgp.FlowSpecIPv4Unicast: + rules, err := MarshalFlowSpecRules(v.Value) + if err != nil { + return nil, err + } + nlri = &api.FlowSpecNLRI{ + Rules: rules, + } + case *bgp.FlowSpecIPv6Unicast: + rules, err := MarshalFlowSpecRules(v.Value) + if err != nil { + return nil, err + } + nlri = &api.FlowSpecNLRI{ + Rules: rules, + } + case *bgp.FlowSpecIPv4VPN: + rd, err := MarshalRD(v.RD()) + if err != nil { + return nil, err + } + rules, err := MarshalFlowSpecRules(v.Value) + if err != nil { + return nil, err + } + nlri = &api.VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + } + case *bgp.FlowSpecIPv6VPN: + rd, err := MarshalRD(v.RD()) + if err != nil { + return nil, err + } + rules, err := MarshalFlowSpecRules(v.Value) + if err != nil { + return nil, err + } + nlri = &api.VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + } + case *bgp.FlowSpecL2VPN: + rd, err := MarshalRD(v.RD()) + if err != nil { + return nil, err + } + rules, err := MarshalFlowSpecRules(v.Value) + if err != nil { + return nil, err + } + nlri = &api.VPNFlowSpecNLRI{ + Rd: rd, + Rules: rules, + } + case *bgp.LsAddrPrefix: + switch n := v.NLRI.(type) { + case *bgp.LsNodeNLRI: + node, err := MarshalLsNodeNLRI(n) + if err != nil { + return nil, err + } + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_NODE, + Nlri: node, + Length: uint32(n.Length), + ProtocolId: api.LsProtocolID(n.ProtocolID), + Identifier: n.Identifier, + } + + case *bgp.LsLinkNLRI: + node, err := MarshalLsLinkNLRI(n) + if err != nil { + return nil, err + } + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_LINK, + Nlri: node, + Length: uint32(n.Length), + ProtocolId: api.LsProtocolID(n.ProtocolID), + Identifier: n.Identifier, + } + + case *bgp.LsPrefixV4NLRI: + node, err := MarshalLsPrefixV4NLRI(n) + if err != nil { + return nil, err + } + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_PREFIX_V4, + Nlri: node, + Length: uint32(n.Length), + ProtocolId: api.LsProtocolID(n.ProtocolID), + Identifier: n.Identifier, + } + + case *bgp.LsPrefixV6NLRI: + node, err := MarshalLsPrefixV6NLRI(n) + if err != nil { + return nil, err + } + nlri = &api.LsAddrPrefix{ + Type: api.LsNLRIType_LS_NLRI_PREFIX_V6, + Nlri: node, + Length: uint32(n.Length), + ProtocolId: api.LsProtocolID(n.ProtocolID), + Identifier: n.Identifier, + } + } + case *bgp.SRPolicyIPv4: + nlri = &api.SRPolicyNLRI{ + Length: uint32(v.Length), + Distinguisher: v.Distinguisher, + Color: v.Color, + Endpoint: v.Endpoint, + } + case *bgp.SRPolicyIPv6: + nlri = &api.SRPolicyNLRI{ + Length: uint32(v.Length), + Distinguisher: v.Distinguisher, + Color: v.Color, + Endpoint: v.Endpoint, + } + case *bgp.MUPNLRI: + switch r := v.RouteTypeData.(type) { + case *bgp.MUPInterworkSegmentDiscoveryRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + nlri = &api.MUPInterworkSegmentDiscoveryRoute{ + Rd: rd, + Prefix: r.Prefix.String(), + } + case *bgp.MUPDirectSegmentDiscoveryRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + nlri = &api.MUPDirectSegmentDiscoveryRoute{ + Rd: rd, + Address: r.Address.String(), + } + case *bgp.MUPType1SessionTransformedRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + nlri = &api.MUPType1SessionTransformedRoute{ + Rd: rd, + Prefix: r.Prefix.String(), + Teid: r.TEID, + Qfi: uint32(r.QFI), + EndpointAddressLength: uint32(r.EndpointAddressLength), + EndpointAddress: r.EndpointAddress.String(), + } + case *bgp.MUPType2SessionTransformedRoute: + rd, err := MarshalRD(r.RD) + if err != nil { + return nil, err + } + nlri = &api.MUPType2SessionTransformedRoute{ + Rd: rd, + EndpointAddressLength: uint32(r.EndpointAddressLength), + EndpointAddress: r.EndpointAddress.String(), + Teid: r.TEID, + } + } + } + + an, _ := apb.New(nlri) + return an, nil +} + +func MarshalNLRIs(values []bgp.AddrPrefixInterface) ([]*apb.Any, error) { + nlris := make([]*apb.Any, 0, len(values)) + for _, value := range values { + nlri, err := MarshalNLRI(value) + if err != nil { + return nil, err + } + nlris = append(nlris, nlri) + } + return nlris, nil +} + +func UnmarshalNLRI(rf bgp.RouteFamily, an *apb.Any) (bgp.AddrPrefixInterface, error) { + var nlri bgp.AddrPrefixInterface + + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal nlri: %s", err) + } + + switch v := value.(type) { + case *api.IPAddressPrefix: + switch rf { + case bgp.RF_IPv4_UC: + nlri = bgp.NewIPAddrPrefix(uint8(v.PrefixLen), v.Prefix) + case bgp.RF_IPv6_UC: + nlri = bgp.NewIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix) + } + case *api.LabeledIPAddressPrefix: + switch rf { + case bgp.RF_IPv4_MPLS: + nlri = bgp.NewLabeledIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...)) + case bgp.RF_IPv6_MPLS: + nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...)) + } + case *api.EncapsulationNLRI: + switch rf { + case bgp.RF_IPv4_ENCAP: + nlri = bgp.NewEncapNLRI(v.Address) + case bgp.RF_IPv6_ENCAP: + nlri = bgp.NewEncapv6NLRI(v.Address) + } + case *api.EVPNEthernetAutoDiscoveryRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := unmarshalESI(v.Esi) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNEthernetAutoDiscoveryRoute(rd, *esi, v.EthernetTag, v.Label) + } + case *api.EVPNMACIPAdvertisementRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := unmarshalESI(v.Esi) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNMacIPAdvertisementRoute(rd, *esi, v.EthernetTag, v.MacAddress, v.IpAddress, v.Labels) + } + case *api.EVPNInclusiveMulticastEthernetTagRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNMulticastEthernetTagRoute(rd, v.EthernetTag, v.IpAddress) + } + case *api.EVPNEthernetSegmentRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := unmarshalESI(v.Esi) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNEthernetSegmentRoute(rd, *esi, v.IpAddress) + } + case *api.EVPNIPPrefixRoute: + if rf == bgp.RF_EVPN { + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + esi, err := unmarshalESI(v.Esi) + if err != nil { + return nil, err + } + nlri = bgp.NewEVPNIPPrefixRoute(rd, *esi, v.EthernetTag, uint8(v.IpPrefixLen), v.IpPrefix, v.GwAddress, v.Label) + } + case *api.SRPolicyNLRI: + switch rf { + case bgp.RF_SR_POLICY_IPv4: + nlri = bgp.NewSRPolicyIPv4(v.Length, v.Distinguisher, v.Color, v.Endpoint) + case bgp.RF_SR_POLICY_IPv6: + nlri = bgp.NewSRPolicyIPv6(v.Length, v.Distinguisher, v.Color, v.Endpoint) + } + case *api.LabeledVPNIPAddressPrefix: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_IPv4_VPN: + nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd) + case bgp.RF_IPv6_VPN: + nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(v.PrefixLen), v.Prefix, *bgp.NewMPLSLabelStack(v.Labels...), rd) + } + case *api.RouteTargetMembershipNLRI: + rt, err := UnmarshalRT(v.Rt) + if err != nil { + return nil, err + } + nlri = bgp.NewRouteTargetMembershipNLRI(v.Asn, rt) + case *api.FlowSpecNLRI: + rules, err := UnmarshalFlowSpecRules(v.Rules) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_FS_IPv4_UC: + nlri = bgp.NewFlowSpecIPv4Unicast(rules) + case bgp.RF_FS_IPv6_UC: + nlri = bgp.NewFlowSpecIPv6Unicast(rules) + } + case *api.VPNFlowSpecNLRI: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + rules, err := UnmarshalFlowSpecRules(v.Rules) + if err != nil { + return nil, err + } + switch rf { + case bgp.RF_FS_IPv4_VPN: + nlri = bgp.NewFlowSpecIPv4VPN(rd, rules) + case bgp.RF_FS_IPv6_VPN: + nlri = bgp.NewFlowSpecIPv6VPN(rd, rules) + case bgp.RF_FS_L2_VPN: + nlri = bgp.NewFlowSpecL2VPN(rd, rules) + } + case *api.MUPInterworkSegmentDiscoveryRoute: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + prefix, err := netip.ParsePrefix(v.Prefix) + if err != nil { + return nil, err + } + nlri = bgp.NewMUPInterworkSegmentDiscoveryRoute(rd, prefix) + case *api.MUPDirectSegmentDiscoveryRoute: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + address, err := netip.ParseAddr(v.Address) + if err != nil { + return nil, err + } + nlri = bgp.NewMUPDirectSegmentDiscoveryRoute(rd, address) + case *api.MUPType1SessionTransformedRoute: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + prefix, err := netip.ParsePrefix(v.Prefix) + if err != nil { + return nil, err + } + ea, err := netip.ParseAddr(v.EndpointAddress) + if err != nil { + return nil, err + } + nlri = bgp.NewMUPType1SessionTransformedRoute(rd, prefix, v.Teid, uint8(v.Qfi), ea) + case *api.MUPType2SessionTransformedRoute: + rd, err := UnmarshalRD(v.Rd) + if err != nil { + return nil, err + } + ea, err := netip.ParseAddr(v.EndpointAddress) + if err != nil { + return nil, err + } + nlri = bgp.NewMUPType2SessionTransformedRoute(rd, ea, v.Teid) + } + + if nlri == nil { + return nil, fmt.Errorf("invalid nlri for %s family: %s", rf.String(), value) + } + + return nlri, nil +} + +func UnmarshalNLRIs(rf bgp.RouteFamily, values []*apb.Any) ([]bgp.AddrPrefixInterface, error) { + nlris := make([]bgp.AddrPrefixInterface, 0, len(values)) + for _, an := range values { + nlri, err := UnmarshalNLRI(rf, an) + if err != nil { + return nil, err + } + nlris = append(nlris, nlri) + } + return nlris, nil +} + +func NewMpReachNLRIAttributeFromNative(a *bgp.PathAttributeMpReachNLRI) (*api.MpReachNLRIAttribute, error) { + var nexthops []string + if a.SAFI == bgp.SAFI_FLOW_SPEC_UNICAST || a.SAFI == bgp.SAFI_FLOW_SPEC_VPN { + nexthops = nil + } else { + nexthops = []string{a.Nexthop.String()} + if a.LinkLocalNexthop != nil && a.LinkLocalNexthop.IsLinkLocalUnicast() { + nexthops = append(nexthops, a.LinkLocalNexthop.String()) + } + } + n, err := MarshalNLRIs(a.Value) + if err != nil { + return nil, err + } + return &api.MpReachNLRIAttribute{ + Family: ToApiFamily(a.AFI, a.SAFI), + NextHops: nexthops, + Nlris: n, + }, nil +} + +func NewMpUnreachNLRIAttributeFromNative(a *bgp.PathAttributeMpUnreachNLRI) (*api.MpUnreachNLRIAttribute, error) { + n, err := MarshalNLRIs(a.Value) + if err != nil { + return nil, err + } + return &api.MpUnreachNLRIAttribute{ + Family: ToApiFamily(a.AFI, a.SAFI), + Nlris: n, + }, nil +} + +func MarshalRT(rt bgp.ExtendedCommunityInterface) (*apb.Any, error) { + var r proto.Message + switch v := rt.(type) { + case *bgp.TwoOctetAsSpecificExtended: + r = &api.TwoOctetAsSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + Asn: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.IPv4AddressSpecificExtended: + r = &api.IPv4AddressSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.FourOctetAsSpecificExtended: + r = &api.FourOctetAsSpecificExtended{ + IsTransitive: true, + SubType: uint32(bgp.EC_SUBTYPE_ROUTE_TARGET), + Asn: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + default: + return nil, fmt.Errorf("invalid rt type to marshal: %v", rt) + } + a, _ := apb.New(r) + return a, nil +} + +func MarshalRTs(values []bgp.ExtendedCommunityInterface) ([]*apb.Any, error) { + rts := make([]*apb.Any, 0, len(values)) + for _, rt := range values { + r, err := MarshalRT(rt) + if err != nil { + return nil, err + } + rts = append(rts, r) + } + return rts, nil +} + +func UnmarshalRT(a *apb.Any) (bgp.ExtendedCommunityInterface, error) { + value, err := a.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal route target: %s", err) + } + switch v := value.(type) { + case *api.TwoOctetAsSpecificExtended: + return bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.Asn), v.LocalAdmin, v.IsTransitive), nil + case *api.IPv4AddressSpecificExtended: + rt := bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + if rt == nil { + return nil, fmt.Errorf("invalid address for ipv4 address specific route target: %s", v.Address) + } + return rt, nil + case *api.FourOctetAsSpecificExtended: + return bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Asn, uint16(v.LocalAdmin), v.IsTransitive), nil + } + return nil, fmt.Errorf("invalid route target type: %s", a.TypeUrl) +} + +func UnmarshalRTs(values []*apb.Any) ([]bgp.ExtendedCommunityInterface, error) { + rts := make([]bgp.ExtendedCommunityInterface, 0, len(values)) + for _, an := range values { + rt, err := UnmarshalRT(an) + if err != nil { + return nil, err + } + rts = append(rts, rt) + } + return rts, nil +} + +func NewExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeExtendedCommunities) (*api.ExtendedCommunitiesAttribute, error) { + communities := make([]*apb.Any, 0, len(a.Value)) + for _, value := range a.Value { + var community proto.Message + switch v := value.(type) { + case *bgp.TwoOctetAsSpecificExtended: + community = &api.TwoOctetAsSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Asn: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.IPv4AddressSpecificExtended: + community = &api.IPv4AddressSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.FourOctetAsSpecificExtended: + community = &api.FourOctetAsSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Asn: uint32(v.AS), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.ValidationExtended: + community = &api.ValidationExtended{ + State: uint32(v.State), + } + case *bgp.LinkBandwidthExtended: + community = &api.LinkBandwidthExtended{ + Asn: uint32(v.AS), + Bandwidth: v.Bandwidth, + } + case *bgp.ColorExtended: + community = &api.ColorExtended{ + Color: v.Color, + } + case *bgp.EncapExtended: + community = &api.EncapExtended{ + TunnelType: uint32(v.TunnelType), + } + case *bgp.DefaultGatewayExtended: + community = &api.DefaultGatewayExtended{} + case *bgp.OpaqueExtended: + community = &api.OpaqueExtended{ + IsTransitive: v.IsTransitive, + Value: v.Value, + } + case *bgp.ESILabelExtended: + community = &api.ESILabelExtended{ + IsSingleActive: v.IsSingleActive, + Label: v.Label, + } + case *bgp.ESImportRouteTarget: + community = &api.ESImportRouteTarget{ + EsImport: v.ESImport.String(), + } + case *bgp.MacMobilityExtended: + community = &api.MacMobilityExtended{ + IsSticky: v.IsSticky, + SequenceNum: v.Sequence, + } + case *bgp.RouterMacExtended: + community = &api.RouterMacExtended{ + Mac: v.Mac.String(), + } + case *bgp.TrafficRateExtended: + community = &api.TrafficRateExtended{ + Asn: uint32(v.AS), + Rate: v.Rate, + } + case *bgp.TrafficActionExtended: + community = &api.TrafficActionExtended{ + Terminal: v.Terminal, + Sample: v.Sample, + } + case *bgp.RedirectTwoOctetAsSpecificExtended: + community = &api.RedirectTwoOctetAsSpecificExtended{ + Asn: uint32(v.AS), + LocalAdmin: v.LocalAdmin, + } + case *bgp.RedirectIPv4AddressSpecificExtended: + community = &api.RedirectIPv4AddressSpecificExtended{ + Address: v.IPv4.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.RedirectFourOctetAsSpecificExtended: + community = &api.RedirectFourOctetAsSpecificExtended{ + Asn: v.AS, + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.TrafficRemarkExtended: + community = &api.TrafficRemarkExtended{ + Dscp: uint32(v.DSCP), + } + case *bgp.MUPExtended: + community = &api.MUPExtended{ + SubType: uint32(v.SubType), + SegmentId2: uint32(v.SegmentID2), + SegmentId4: v.SegmentID4, + } + case *bgp.UnknownExtended: + community = &api.UnknownExtended{ + Type: uint32(v.Type), + Value: v.Value, + } + default: + return nil, fmt.Errorf("unsupported extended community: %v", value) + } + an, _ := apb.New(community) + communities = append(communities, an) + } + return &api.ExtendedCommunitiesAttribute{ + Communities: communities, + }, nil +} + +func unmarshalExComm(a *api.ExtendedCommunitiesAttribute) (*bgp.PathAttributeExtendedCommunities, error) { + communities := make([]bgp.ExtendedCommunityInterface, 0, len(a.Communities)) + for _, an := range a.Communities { + var community bgp.ExtendedCommunityInterface + value, err := an.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal extended community: %s", err) + } + switch v := value.(type) { + case *api.TwoOctetAsSpecificExtended: + community = bgp.NewTwoOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), uint16(v.Asn), v.LocalAdmin, v.IsTransitive) + case *api.IPv4AddressSpecificExtended: + community = bgp.NewIPv4AddressSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Address, uint16(v.LocalAdmin), v.IsTransitive) + case *api.FourOctetAsSpecificExtended: + community = bgp.NewFourOctetAsSpecificExtended(bgp.ExtendedCommunityAttrSubType(v.SubType), v.Asn, uint16(v.LocalAdmin), v.IsTransitive) + case *api.ValidationExtended: + community = bgp.NewValidationExtended(bgp.ValidationState(v.State)) + case *api.LinkBandwidthExtended: + community = bgp.NewLinkBandwidthExtended(uint16(v.Asn), v.Bandwidth) + case *api.ColorExtended: + community = bgp.NewColorExtended(v.Color) + case *api.EncapExtended: + community = bgp.NewEncapExtended(bgp.TunnelType(v.TunnelType)) + case *api.DefaultGatewayExtended: + community = bgp.NewDefaultGatewayExtended() + case *api.OpaqueExtended: + community = bgp.NewOpaqueExtended(v.IsTransitive, v.Value) + case *api.ESILabelExtended: + community = bgp.NewESILabelExtended(v.Label, v.IsSingleActive) + case *api.ESImportRouteTarget: + community = bgp.NewESImportRouteTarget(v.EsImport) + case *api.MacMobilityExtended: + community = bgp.NewMacMobilityExtended(v.SequenceNum, v.IsSticky) + case *api.RouterMacExtended: + community = bgp.NewRoutersMacExtended(v.Mac) + case *api.TrafficRateExtended: + community = bgp.NewTrafficRateExtended(uint16(v.Asn), v.Rate) + case *api.TrafficActionExtended: + community = bgp.NewTrafficActionExtended(v.Terminal, v.Sample) + case *api.RedirectTwoOctetAsSpecificExtended: + community = bgp.NewRedirectTwoOctetAsSpecificExtended(uint16(v.Asn), v.LocalAdmin) + case *api.RedirectIPv4AddressSpecificExtended: + community = bgp.NewRedirectIPv4AddressSpecificExtended(v.Address, uint16(v.LocalAdmin)) + case *api.RedirectFourOctetAsSpecificExtended: + community = bgp.NewRedirectFourOctetAsSpecificExtended(v.Asn, uint16(v.LocalAdmin)) + case *api.TrafficRemarkExtended: + community = bgp.NewTrafficRemarkExtended(uint8(v.Dscp)) + case *api.MUPExtended: + community = bgp.NewMUPExtended(uint16(v.SegmentId2), v.SegmentId4) + case *api.UnknownExtended: + community = bgp.NewUnknownExtended(bgp.ExtendedCommunityAttrType(v.Type), v.Value) + } + if community == nil { + return nil, fmt.Errorf("invalid extended community: %v", value) + } + communities = append(communities, community) + } + return bgp.NewPathAttributeExtendedCommunities(communities), nil +} + +func NewAs4PathAttributeFromNative(a *bgp.PathAttributeAs4Path) (*api.As4PathAttribute, error) { + segments := make([]*api.AsSegment, 0, len(a.Value)) + for _, param := range a.Value { + segments = append(segments, &api.AsSegment{ + Type: api.AsSegment_Type(param.Type), + Numbers: param.AS, + }) + } + return &api.As4PathAttribute{ + Segments: segments, + }, nil +} + +func NewAs4AggregatorAttributeFromNative(a *bgp.PathAttributeAs4Aggregator) (*api.As4AggregatorAttribute, error) { + return &api.As4AggregatorAttribute{ + Asn: a.Value.AS, + Address: a.Value.Address.String(), + }, nil +} + +func NewPmsiTunnelAttributeFromNative(a *bgp.PathAttributePmsiTunnel) (*api.PmsiTunnelAttribute, error) { + var flags uint32 + if a.IsLeafInfoRequired { + flags |= 0x01 + } + id, _ := a.TunnelID.Serialize() + return &api.PmsiTunnelAttribute{ + Flags: flags, + Type: uint32(a.TunnelType), + Label: a.Label, + Id: id, + }, nil +} + +func NewTunnelEncapAttributeFromNative(a *bgp.PathAttributeTunnelEncap) (*api.TunnelEncapAttribute, error) { + tlvs := make([]*api.TunnelEncapTLV, 0, len(a.Value)) + for _, v := range a.Value { + subTlvs := make([]*apb.Any, 0, len(v.Value)) + for _, s := range v.Value { + var subTlv proto.Message + switch sv := s.(type) { + case *bgp.TunnelEncapSubTLVEncapsulation: + subTlv = &api.TunnelEncapSubTLVEncapsulation{ + Key: sv.Key, + Cookie: sv.Cookie, + } + case *bgp.TunnelEncapSubTLVProtocol: + subTlv = &api.TunnelEncapSubTLVProtocol{ + Protocol: uint32(sv.Protocol), + } + case *bgp.TunnelEncapSubTLVColor: + subTlv = &api.TunnelEncapSubTLVColor{ + Color: sv.Color, + } + case *bgp.TunnelEncapSubTLVEgressEndpoint: + subTlv = &api.TunnelEncapSubTLVEgressEndpoint{ + Address: sv.Address.String(), + } + case *bgp.TunnelEncapSubTLVUDPDestPort: + subTlv = &api.TunnelEncapSubTLVUDPDestPort{ + Port: uint32(sv.UDPDestPort), + } + case *bgp.TunnelEncapSubTLVUnknown: + subTlv = &api.TunnelEncapSubTLVUnknown{ + Type: uint32(sv.Type), + Value: sv.Value, + } + case *bgp.TunnelEncapSubTLVSRBSID: + t, err := MarshalSRBSID(sv) + if err != nil { + return nil, err + } + subTlv = t + // TODO (sbezverk) Add processing of SRv6 Binding SID when it gets assigned ID + case *bgp.TunnelEncapSubTLVSRCandidatePathName: + subTlv = &api.TunnelEncapSubTLVSRCandidatePathName{ + CandidatePathName: sv.CandidatePathName, + } + // TODO (sbezverk) Add processing of SR Policy name when it gets assigned ID + case *bgp.TunnelEncapSubTLVSRENLP: + subTlv = &api.TunnelEncapSubTLVSRENLP{ + Flags: uint32(sv.Flags), + Enlp: api.ENLPType(sv.ENLP), + } + case *bgp.TunnelEncapSubTLVSRPreference: + subTlv = &api.TunnelEncapSubTLVSRPreference{ + Flags: uint32(sv.Flags), + Preference: sv.Preference, + } + case *bgp.TunnelEncapSubTLVSRPriority: + subTlv = &api.TunnelEncapSubTLVSRPriority{ + Priority: uint32(sv.Priority), + } + case *bgp.TunnelEncapSubTLVSRSegmentList: + s, err := MarshalSRSegments(sv.Segments) + if err != nil { + return nil, err + } + subTlv = &api.TunnelEncapSubTLVSRSegmentList{ + Weight: &api.SRWeight{ + Flags: uint32(sv.Weight.Flags), + Weight: uint32(sv.Weight.Weight), + }, + Segments: s, + } + } + an, _ := apb.New(subTlv) + subTlvs = append(subTlvs, an) + } + tlvs = append(tlvs, &api.TunnelEncapTLV{ + Type: uint32(v.Type), + Tlvs: subTlvs, + }) + } + return &api.TunnelEncapAttribute{ + Tlvs: tlvs, + }, nil +} + +func NewIP6ExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeIP6ExtendedCommunities) (*api.IP6ExtendedCommunitiesAttribute, error) { + communities := make([]*apb.Any, 0, len(a.Value)) + for _, value := range a.Value { + var community proto.Message + switch v := value.(type) { + case *bgp.IPv6AddressSpecificExtended: + community = &api.IPv6AddressSpecificExtended{ + IsTransitive: v.IsTransitive, + SubType: uint32(v.SubType), + Address: v.IPv6.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + case *bgp.RedirectIPv6AddressSpecificExtended: + community = &api.RedirectIPv6AddressSpecificExtended{ + Address: v.IPv6.String(), + LocalAdmin: uint32(v.LocalAdmin), + } + default: + return nil, fmt.Errorf("invalid ipv6 extended community: %v", value) + } + an, _ := apb.New(community) + communities = append(communities, an) + } + return &api.IP6ExtendedCommunitiesAttribute{ + Communities: communities, + }, nil +} + +func NewAigpAttributeFromNative(a *bgp.PathAttributeAigp) (*api.AigpAttribute, error) { + tlvs := make([]*apb.Any, 0, len(a.Values)) + for _, value := range a.Values { + var tlv proto.Message + switch v := value.(type) { + case *bgp.AigpTLVIgpMetric: + tlv = &api.AigpTLVIGPMetric{ + Metric: v.Metric, + } + case *bgp.AigpTLVDefault: + tlv = &api.AigpTLVUnknown{ + Type: uint32(v.Type()), + Value: v.Value, + } + } + an, _ := apb.New(tlv) + tlvs = append(tlvs, an) + } + return &api.AigpAttribute{ + Tlvs: tlvs, + }, nil +} + +func NewLargeCommunitiesAttributeFromNative(a *bgp.PathAttributeLargeCommunities) (*api.LargeCommunitiesAttribute, error) { + communities := make([]*api.LargeCommunity, 0, len(a.Values)) + for _, v := range a.Values { + communities = append(communities, &api.LargeCommunity{ + GlobalAdmin: v.ASN, + LocalData1: v.LocalData1, + LocalData2: v.LocalData2, + }) + } + return &api.LargeCommunitiesAttribute{ + Communities: communities, + }, nil +} + +func stringOrDefault(s *string) string { + if s == nil { + return "" + } + return *s +} + +func bytesOrDefault(b *[]byte) []byte { + if b == nil { + return []byte{} + } + return *b +} + +func ipOrDefault(ip *net.IP) string { + if ip == nil { + return "" + } + return ip.String() +} + +func uint32OrDefault(i *uint32) uint32 { + if i == nil { + return 0 + } + return *i +} + +func float32OrDefault(f *float32) float32 { + if f == nil { + return 0.0 + } + return *f +} + +func NewLsAttributeFromNative(a *bgp.PathAttributeLs) (*api.LsAttribute, error) { + attr := a.Extract() + + apiAttr := &api.LsAttribute{ + Node: &api.LsAttributeNode{ + Name: stringOrDefault(attr.Node.Name), + Opaque: bytesOrDefault(attr.Node.Opaque), + IsisArea: bytesOrDefault(attr.Node.IsisArea), + LocalRouterId: ipOrDefault(attr.Node.LocalRouterID), + LocalRouterIdV6: ipOrDefault(attr.Node.LocalRouterIDv6), + + SrAlgorithms: bytesOrDefault(attr.Node.SrAlgorithms), + }, + Link: &api.LsAttributeLink{ + Name: stringOrDefault(attr.Link.Name), + Opaque: bytesOrDefault(attr.Link.Opaque), + LocalRouterId: ipOrDefault(attr.Link.LocalRouterID), + LocalRouterIdV6: ipOrDefault(attr.Link.LocalRouterIDv6), + RemoteRouterId: ipOrDefault(attr.Link.RemoteRouterID), + RemoteRouterIdV6: ipOrDefault(attr.Link.RemoteRouterIDv6), + AdminGroup: uint32OrDefault(attr.Link.AdminGroup), + DefaultTeMetric: uint32OrDefault(attr.Link.DefaultTEMetric), + IgpMetric: uint32OrDefault(attr.Link.IGPMetric), + + Bandwidth: float32OrDefault(attr.Link.Bandwidth), + ReservableBandwidth: float32OrDefault(attr.Link.ReservableBandwidth), + SrAdjacencySid: uint32OrDefault(attr.Link.SrAdjacencySID), + }, + Prefix: &api.LsAttributePrefix{ + Opaque: bytesOrDefault(attr.Prefix.Opaque), + + SrPrefixSid: uint32OrDefault(attr.Prefix.SrPrefixSID), + }, + } + + if attr.Node.Flags != nil { + apiAttr.Node.Flags = &api.LsNodeFlags{ + Overload: attr.Node.Flags.Overload, + Attached: attr.Node.Flags.Attached, + External: attr.Node.Flags.External, + Abr: attr.Node.Flags.ABR, + Router: attr.Node.Flags.Router, + V6: attr.Node.Flags.V6, + } + } + + if attr.Node.SrCapabilties != nil { + apiAttr.Node.SrCapabilities = &api.LsSrCapabilities{ + Ipv4Supported: attr.Node.SrCapabilties.IPv4Supported, + Ipv6Supported: attr.Node.SrCapabilties.IPv6Supported, + } + + for _, r := range attr.Node.SrCapabilties.Ranges { + apiAttr.Node.SrCapabilities.Ranges = append(apiAttr.Node.SrCapabilities.Ranges, &api.LsSrRange{ + Begin: r.Begin, + End: r.End, + }) + } + } + + if attr.Node.SrLocalBlock != nil { + apiAttr.Node.SrLocalBlock = &api.LsSrLocalBlock{} + for _, r := range attr.Node.SrLocalBlock.Ranges { + apiAttr.Node.SrLocalBlock.Ranges = append(apiAttr.Node.SrLocalBlock.Ranges, &api.LsSrRange{ + Begin: r.Begin, + End: r.End, + }) + } + } + + if attr.Link.UnreservedBandwidth != nil { + for _, f := range attr.Link.UnreservedBandwidth { + apiAttr.Link.UnreservedBandwidth = append(apiAttr.Link.UnreservedBandwidth, f) + } + } + + if attr.Link.Srlgs != nil { + apiAttr.Link.Srlgs = append(apiAttr.Link.Srlgs, *attr.Link.Srlgs...) + } + + if attr.Prefix.IGPFlags != nil { + apiAttr.Prefix.IgpFlags = &api.LsIGPFlags{ + Down: attr.Prefix.IGPFlags.Down, + NoUnicast: attr.Prefix.IGPFlags.NoUnicast, + LocalAddress: attr.Prefix.IGPFlags.LocalAddress, + PropagateNssa: attr.Prefix.IGPFlags.PropagateNSSA, + } + } + + return apiAttr, nil +} + +func NewUnknownAttributeFromNative(a *bgp.PathAttributeUnknown) (*api.UnknownAttribute, error) { + return &api.UnknownAttribute{ + Flags: uint32(a.Flags), + Type: uint32(a.Type), + Value: a.Value, + }, nil +} + +func MarshalPathAttributes(attrList []bgp.PathAttributeInterface) ([]*apb.Any, error) { + anyList := make([]*apb.Any, 0, len(attrList)) + for _, attr := range attrList { + switch a := attr.(type) { + case *bgp.PathAttributeOrigin: + v, err := NewOriginAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAsPath: + v, err := NewAsPathAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeNextHop: + v, err := NewNextHopAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeMultiExitDisc: + v, err := NewMultiExitDiscAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeLocalPref: + v, err := NewLocalPrefAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAtomicAggregate: + v, err := NewAtomicAggregateAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAggregator: + v, err := NewAggregatorAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeCommunities: + v, err := NewCommunitiesAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeOriginatorId: + v, err := NewOriginatorIdAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeClusterList: + v, err := NewClusterListAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeMpReachNLRI: + v, err := NewMpReachNLRIAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeMpUnreachNLRI: + v, err := NewMpUnreachNLRIAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeExtendedCommunities: + v, err := NewExtendedCommunitiesAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAs4Path: + v, err := NewAs4PathAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAs4Aggregator: + v, err := NewAs4AggregatorAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributePmsiTunnel: + v, err := NewPmsiTunnelAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeTunnelEncap: + v, err := NewTunnelEncapAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeIP6ExtendedCommunities: + v, err := NewIP6ExtendedCommunitiesAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeAigp: + v, err := NewAigpAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeLargeCommunities: + v, err := NewLargeCommunitiesAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeLs: + v, err := NewLsAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributePrefixSID: + v, err := NewPrefixSIDAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + case *bgp.PathAttributeUnknown: + v, err := NewUnknownAttributeFromNative(a) + if err != nil { + return nil, err + } + n, _ := apb.New(v) + anyList = append(anyList, n) + } + } + return anyList, nil +} + +func UnmarshalPathAttributes(values []*apb.Any) ([]bgp.PathAttributeInterface, error) { + attrList := make([]bgp.PathAttributeInterface, 0, len(values)) + typeMap := make(map[bgp.BGPAttrType]struct{}) + for _, an := range values { + attr, err := UnmarshalAttribute(an) + if err != nil { + return nil, err + } + if _, ok := typeMap[attr.GetType()]; ok { + return nil, fmt.Errorf("duplicated path attribute type: %d", attr.GetType()) + } + typeMap[attr.GetType()] = struct{}{} + attrList = append(attrList, attr) + } + return attrList, nil +} + +// MarshalSRBSID marshals SR Policy Binding SID Sub TLV structure +func MarshalSRBSID(bsid *bgp.TunnelEncapSubTLVSRBSID) (*apb.Any, error) { + var r proto.Message + s := &api.SRBindingSID{ + Sid: make([]byte, len(bsid.BSID.Value)), + } + copy(s.Sid, bsid.BSID.Value) + s.SFlag = bsid.Flags&0x80 == 0x80 + s.IFlag = bsid.Flags&0x40 == 0x40 + r = s + a, _ := apb.New(r) + return a, nil +} + +// UnmarshalSRBSID unmarshals SR Policy Binding SID Sub TLV and returns native TunnelEncapSubTLVInterface interface +func UnmarshalSRBSID(bsid *apb.Any) (bgp.TunnelEncapSubTLVInterface, error) { + value, err := bsid.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encap sub tlv: %s", err) + } + switch v := value.(type) { + case *api.SRBindingSID: + b, err := bgp.NewBSID(v.Sid) + if err != nil { + return nil, err + } + flags := uint8(0x0) + if v.SFlag { + flags += 0x80 + } + if v.IFlag { + flags += 0x40 + } + return &bgp.TunnelEncapSubTLVSRBSID{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.ENCAP_SUBTLV_TYPE_SRBINDING_SID, + Length: uint16(2 + b.Len()), + }, + BSID: b, + Flags: flags, + }, nil + case *api.SRv6BindingSID: + b, err := bgp.NewBSID(v.Sid) + if err != nil { + return nil, err + } + result := &bgp.TunnelEncapSubTLVSRv6BSID{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.ENCAP_SUBTLV_TYPE_SRBINDING_SID, + Length: uint16(2 + b.Len()), + }, + Flags: 0, + BSID: b, + } + + if v.EndpointBehaviorStructure != nil { + result.EPBAS = &bgp.SRv6EndpointBehaviorStructure{ + Behavior: bgp.SRBehavior(v.EndpointBehaviorStructure.Behavior), + BlockLen: uint8(v.EndpointBehaviorStructure.BlockLen), + NodeLen: uint8(v.EndpointBehaviorStructure.NodeLen), + FuncLen: uint8(v.EndpointBehaviorStructure.FuncLen), + ArgLen: uint8(v.EndpointBehaviorStructure.ArgLen), + } + } + + return result, nil + default: + return nil, fmt.Errorf("unknown binding sid type %+v", v) + } +} + +// MarshalSRSegments marshals a slice of SR Policy Segment List +func MarshalSRSegments(segs []bgp.TunnelEncapSubTLVInterface) ([]*apb.Any, error) { + anyList := make([]*apb.Any, 0, len(segs)) + for _, seg := range segs { + var r proto.Message + switch s := seg.(type) { + case *bgp.SegmentTypeA: + r = &api.SegmentTypeA{ + Label: s.Label, + Flags: &api.SegmentFlags{ + VFlag: s.Flags&0x80 == 0x80, + AFlag: s.Flags&0x40 == 0x40, + SFlag: s.Flags&0x20 == 0x20, + BFlag: s.Flags&0x10 == 0x10, + }, + } + case *bgp.SegmentTypeB: + flags := &api.SegmentFlags{ + VFlag: s.Flags&0x80 == 0x80, + AFlag: s.Flags&0x40 == 0x40, + SFlag: s.Flags&0x20 == 0x20, + BFlag: s.Flags&0x10 == 0x10, + } + segment := &api.SegmentTypeB{ + Flags: flags, + Sid: s.SID, + } + if s.SRv6EBS != nil { + segment.EndpointBehaviorStructure = &api.SRv6EndPointBehavior{ + Behavior: api.SRv6Behavior(s.SRv6EBS.Behavior), + BlockLen: uint32(s.SRv6EBS.BlockLen), + NodeLen: uint32(s.SRv6EBS.NodeLen), + FuncLen: uint32(s.SRv6EBS.FuncLen), + ArgLen: uint32(s.SRv6EBS.ArgLen), + } + } + r = segment + default: + // Unrecognize Segment type, skip it + continue + } + a, _ := apb.New(r) + anyList = append(anyList, a) + } + return anyList, nil +} + +// UnmarshalSRSegments unmarshals SR Policy Segments slice of structs +func UnmarshalSRSegments(s []*apb.Any) ([]bgp.TunnelEncapSubTLVInterface, error) { + if len(s) == 0 { + return nil, nil + } + segments := make([]bgp.TunnelEncapSubTLVInterface, len(s)) + for i := 0; i < len(s); i++ { + value, err := s[i].UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal SR Policy Segment: %s", err) + } + switch v := value.(type) { + case *api.SegmentTypeA: + seg := &bgp.SegmentTypeA{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.EncapSubTLVType(bgp.TypeA), + Length: 6, + }, + Label: v.Label, + } + if v.Flags.VFlag { + seg.Flags += 0x80 + } + if v.Flags.AFlag { + seg.Flags += 0x40 + } + if v.Flags.SFlag { + seg.Flags += 0x20 + } + if v.Flags.BFlag { + seg.Flags += 0x10 + } + segments[i] = seg + case *api.SegmentTypeB: + seg := &bgp.SegmentTypeB{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.EncapSubTLVType(bgp.TypeB), + Length: 18, + }, + SID: v.GetSid(), + } + if v.Flags.VFlag { + seg.Flags += 0x80 + } + if v.Flags.AFlag { + seg.Flags += 0x40 + } + if v.Flags.SFlag { + seg.Flags += 0x20 + } + if v.Flags.BFlag { + seg.Flags += 0x10 + } + if v.EndpointBehaviorStructure != nil { + ebs := v.GetEndpointBehaviorStructure() + seg.SRv6EBS = &bgp.SRv6EndpointBehaviorStructure{ + Behavior: bgp.SRBehavior(ebs.Behavior), + BlockLen: uint8(ebs.BlockLen), + NodeLen: uint8(ebs.NodeLen), + FuncLen: uint8(ebs.FuncLen), + ArgLen: uint8(ebs.ArgLen), + } + } + segments[i] = seg + } + } + return segments, nil +} + +func UnmarshalPrefixSID(psid *api.PrefixSID) (*bgp.PathAttributePrefixSID, error) { + t := bgp.BGP_ATTR_TYPE_PREFIX_SID + s := &bgp.PathAttributePrefixSID{ + PathAttribute: bgp.PathAttribute{ + Flags: bgp.PathAttrFlags[t], + Type: t, + }, + TLVs: make([]bgp.PrefixSIDTLVInterface, 0), + } + for _, raw := range psid.Tlvs { + tlv, err := raw.UnmarshalNew() + if err != nil { + return nil, err + } + switch v := tlv.(type) { + case *api.SRv6L3ServiceTLV: + tlvLength, tlvs, err := UnmarshalSubTLVs(v.SubTlvs) + if err != nil { + return nil, err + } + o := &bgp.SRv6L3ServiceAttribute{ + TLV: bgp.TLV{ + Type: bgp.TLVType(5), + Length: tlvLength, + }, + } + s.PathAttribute.Length += tlvLength + // Storing Sub TLVs in a Service TLV + o.SubTLVs = append(o.SubTLVs, tlvs...) + // Adding Service TLV to Path Attribute TLV slice. + s.TLVs = append(s.TLVs, o) + default: + return nil, fmt.Errorf("unknown or not implemented Prefix SID type: %+v", v) + } + } + // Final Path Attribute Length is 3 bytes of the header and 1 byte Reserved1 + s.PathAttribute.Length += (3 + 1) + return s, nil +} + +func UnmarshalSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []bgp.PrefixSIDTLVInterface, error) { + p := make([]bgp.PrefixSIDTLVInterface, 0, len(stlvs)) + l := uint16(0) + // v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type + for t, tlv := range stlvs { + switch t { + case 1: + // Sub TLV Type 1 is SRv6 Informational Sub TLV + for _, stlvRaw := range tlv.Tlv { + // Instantiating Information Sub TLV + info := &bgp.SRv6InformationSubTLV{ + SubTLV: bgp.SubTLV{ + Type: bgp.SubTLVType(1), + }, + SubSubTLVs: make([]bgp.PrefixSIDTLVInterface, 0), + } + raw, err := stlvRaw.UnmarshalNew() + if err != nil { + return 0, nil, err + } + infoProto := raw.(*api.SRv6InformationSubTLV) + info.SID = make([]byte, len(infoProto.Sid)) + copy(info.SID, infoProto.Sid) + // TODO Once RFC is published add processing of flags + info.Flags = 0 + info.EndpointBehavior = uint16(infoProto.EndpointBehavior) + var sstlvslength uint16 + var sstlvs []bgp.PrefixSIDTLVInterface + if len(infoProto.SubSubTlvs) != 0 { + // Processing Sub Sub TLVs + var err error + sstlvslength, sstlvs, err = UnmarshalSubSubTLVs(infoProto.SubSubTlvs) + if err != nil { + return 0, nil, err + } + info.SubSubTLVs = append(info.SubSubTLVs, sstlvs...) + } + // SRv6 Information Sub TLV length consists 1 byte Resrved2, 16 bytes SID, 1 byte flags, 2 bytes Endpoint Behavior + // 1 byte Reserved3 and length of Sub Sub TLVs + info.SubTLV.Length = 1 + 16 + 1 + 2 + 1 + sstlvslength + // For total Srv6 Information Sub TLV length, adding 3 bytes of the Sub TLV header + l += info.SubTLV.Length + 4 + p = append(p, info) + } + default: + return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t) + } + } + + return l, p, nil +} + +func UnmarshalSubSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []bgp.PrefixSIDTLVInterface, error) { + p := make([]bgp.PrefixSIDTLVInterface, 0) + l := uint16(0) + // v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type + for t, tlv := range stlvs { + switch t { + case 1: + // Sub Sub TLV Type 1 is SRv6 Structure Sub Sub TLV + for _, stlvRaw := range tlv.Tlv { + // Instantiating Information Sub TLV + structure := &bgp.SRv6SIDStructureSubSubTLV{ + SubSubTLV: bgp.SubSubTLV{ + Type: bgp.SubSubTLVType(1), + Length: 6, + }, + } + raw, err := stlvRaw.UnmarshalNew() + if err != nil { + return 0, nil, err + } + structureProto := raw.(*api.SRv6StructureSubSubTLV) + structure.LocatorBlockLength = uint8(structureProto.LocatorBlockLength) + structure.LocatorNodeLength = uint8(structureProto.LocatorNodeLength) + structure.FunctionLength = uint8(structureProto.FunctionLength) + structure.ArgumentLength = uint8(structureProto.ArgumentLength) + structure.TranspositionLength = uint8(structureProto.TranspositionLength) + structure.TranspositionOffset = uint8(structureProto.TranspositionOffset) + + // SRv6 Structure Sub Sub TLV length consists of header 3 bytes, 6 bytes of value + l += 3 + 6 + p = append(p, structure) + } + default: + return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t) + } + } + + return l, p, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/capability.go b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/capability.go new file mode 100644 index 000000000..1334f5c93 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/capability.go @@ -0,0 +1,256 @@ +// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation. +// +// 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 apiutil + +import ( + "fmt" + + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" + proto "google.golang.org/protobuf/proto" + apb "google.golang.org/protobuf/types/known/anypb" +) + +func NewMultiProtocolCapability(a *bgp.CapMultiProtocol) *api.MultiProtocolCapability { + afi, safi := bgp.RouteFamilyToAfiSafi(a.CapValue) + return &api.MultiProtocolCapability{ + Family: ToApiFamily(afi, safi), + } +} + +func NewRouteRefreshCapability(a *bgp.CapRouteRefresh) *api.RouteRefreshCapability { + return &api.RouteRefreshCapability{} +} + +func NewCarryingLabelInfoCapability(a *bgp.CapCarryingLabelInfo) *api.CarryingLabelInfoCapability { + return &api.CarryingLabelInfoCapability{} +} + +func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *api.ExtendedNexthopCapability { + tuples := make([]*api.ExtendedNexthopCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &api.ExtendedNexthopCapabilityTuple{ + NlriFamily: ToApiFamily(t.NLRIAFI, uint8(t.NLRISAFI)), + NexthopFamily: ToApiFamily(t.NexthopAFI, bgp.SAFI_UNICAST), + }) + } + return &api.ExtendedNexthopCapability{ + Tuples: tuples, + } +} + +func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *api.GracefulRestartCapability { + tuples := make([]*api.GracefulRestartCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &api.GracefulRestartCapabilityTuple{ + Family: ToApiFamily(t.AFI, t.SAFI), + Flags: uint32(t.Flags), + }) + } + return &api.GracefulRestartCapability{ + Flags: uint32(a.Flags), + Time: uint32(a.Time), + Tuples: tuples, + } +} + +func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *api.FourOctetASNCapability { + return &api.FourOctetASNCapability{ + Asn: a.CapValue, + } +} + +func NewAddPathCapability(a *bgp.CapAddPath) *api.AddPathCapability { + tuples := make([]*api.AddPathCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + afi, safi := bgp.RouteFamilyToAfiSafi(t.RouteFamily) + tuples = append(tuples, &api.AddPathCapabilityTuple{ + Family: ToApiFamily(afi, safi), + Mode: api.AddPathCapabilityTuple_Mode(t.Mode), + }) + } + return &api.AddPathCapability{ + Tuples: tuples, + } +} + +func NewEnhancedRouteRefreshCapability(a *bgp.CapEnhancedRouteRefresh) *api.EnhancedRouteRefreshCapability { + return &api.EnhancedRouteRefreshCapability{} +} + +func NewLongLivedGracefulRestartCapability(a *bgp.CapLongLivedGracefulRestart) *api.LongLivedGracefulRestartCapability { + tuples := make([]*api.LongLivedGracefulRestartCapabilityTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, &api.LongLivedGracefulRestartCapabilityTuple{ + Family: ToApiFamily(t.AFI, uint8(t.SAFI)), + Flags: uint32(t.Flags), + Time: t.RestartTime, + }) + } + return &api.LongLivedGracefulRestartCapability{ + Tuples: tuples, + } +} + +func NewRouteRefreshCiscoCapability(a *bgp.CapRouteRefreshCisco) *api.RouteRefreshCiscoCapability { + return &api.RouteRefreshCiscoCapability{} +} + +func NewFQDNCapability(a *bgp.CapFQDN) *api.FqdnCapability { + return &api.FqdnCapability{ + HostName: a.HostName, + DomainName: a.DomainName, + } +} + +func NewUnknownCapability(a *bgp.CapUnknown) *api.UnknownCapability { + return &api.UnknownCapability{ + Code: uint32(a.CapCode), + Value: a.CapValue, + } +} + +func MarshalCapability(value bgp.ParameterCapabilityInterface) (*apb.Any, error) { + var m proto.Message + switch n := value.(type) { + case *bgp.CapMultiProtocol: + m = NewMultiProtocolCapability(n) + case *bgp.CapRouteRefresh: + m = NewRouteRefreshCapability(n) + case *bgp.CapCarryingLabelInfo: + m = NewCarryingLabelInfoCapability(n) + case *bgp.CapExtendedNexthop: + m = NewExtendedNexthopCapability(n) + case *bgp.CapGracefulRestart: + m = NewGracefulRestartCapability(n) + case *bgp.CapFourOctetASNumber: + m = NewFourOctetASNumberCapability(n) + case *bgp.CapAddPath: + m = NewAddPathCapability(n) + case *bgp.CapEnhancedRouteRefresh: + m = NewEnhancedRouteRefreshCapability(n) + case *bgp.CapLongLivedGracefulRestart: + m = NewLongLivedGracefulRestartCapability(n) + case *bgp.CapRouteRefreshCisco: + m = NewRouteRefreshCiscoCapability(n) + case *bgp.CapFQDN: + m = NewFQDNCapability(n) + case *bgp.CapUnknown: + m = NewUnknownCapability(n) + default: + return nil, fmt.Errorf("invalid capability type to marshal: %+v", value) + } + return apb.New(m) +} + +func MarshalCapabilities(values []bgp.ParameterCapabilityInterface) ([]*apb.Any, error) { + caps := make([]*apb.Any, 0, len(values)) + for _, value := range values { + a, err := MarshalCapability(value) + if err != nil { + return nil, err + } + caps = append(caps, a) + } + return caps, nil +} + +func unmarshalCapability(a *apb.Any) (bgp.ParameterCapabilityInterface, error) { + value, err := a.UnmarshalNew() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal capability: %s", err) + } + switch a := value.(type) { + case *api.MultiProtocolCapability: + return bgp.NewCapMultiProtocol(ToRouteFamily(a.Family)), nil + case *api.RouteRefreshCapability: + return bgp.NewCapRouteRefresh(), nil + case *api.CarryingLabelInfoCapability: + return bgp.NewCapCarryingLabelInfo(), nil + case *api.ExtendedNexthopCapability: + tuples := make([]*bgp.CapExtendedNexthopTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var nhAfi uint16 + switch t.NexthopFamily.Afi { + case api.Family_AFI_IP: + nhAfi = bgp.AFI_IP + case api.Family_AFI_IP6: + nhAfi = bgp.AFI_IP6 + default: + return nil, fmt.Errorf("invalid address family for nexthop afi in extended nexthop capability: %s", t.NexthopFamily) + } + tuples = append(tuples, bgp.NewCapExtendedNexthopTuple(ToRouteFamily(t.NlriFamily), nhAfi)) + } + return bgp.NewCapExtendedNexthop(tuples), nil + case *api.GracefulRestartCapability: + tuples := make([]*bgp.CapGracefulRestartTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var forward bool + if t.Flags&0x80 > 0 { + forward = true + } + tuples = append(tuples, bgp.NewCapGracefulRestartTuple(ToRouteFamily(t.Family), forward)) + } + var restarting bool + if a.Flags&0x08 > 0 { + restarting = true + } + var notification bool + if a.Flags&0x04 > 0 { + notification = true + } + return bgp.NewCapGracefulRestart(restarting, notification, uint16(a.Time), tuples), nil + case *api.FourOctetASNCapability: + return bgp.NewCapFourOctetASNumber(a.Asn), nil + case *api.AddPathCapability: + tuples := make([]*bgp.CapAddPathTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + tuples = append(tuples, bgp.NewCapAddPathTuple(ToRouteFamily(t.Family), bgp.BGPAddPathMode(t.Mode))) + } + return bgp.NewCapAddPath(tuples), nil + case *api.EnhancedRouteRefreshCapability: + return bgp.NewCapEnhancedRouteRefresh(), nil + case *api.LongLivedGracefulRestartCapability: + tuples := make([]*bgp.CapLongLivedGracefulRestartTuple, 0, len(a.Tuples)) + for _, t := range a.Tuples { + var forward bool + if t.Flags&0x80 > 0 { + forward = true + } + tuples = append(tuples, bgp.NewCapLongLivedGracefulRestartTuple(ToRouteFamily(t.Family), forward, t.Time)) + } + return bgp.NewCapLongLivedGracefulRestart(tuples), nil + case *api.RouteRefreshCiscoCapability: + return bgp.NewCapRouteRefreshCisco(), nil + case *api.FqdnCapability: + return bgp.NewCapFQDN(a.HostName, a.DomainName), nil + case *api.UnknownCapability: + return bgp.NewCapUnknown(bgp.BGPCapabilityCode(a.Code), a.Value), nil + } + return nil, fmt.Errorf("invalid capability type to unmarshal: %s", a.TypeUrl) +} + +func UnmarshalCapabilities(values []*apb.Any) ([]bgp.ParameterCapabilityInterface, error) { + caps := make([]bgp.ParameterCapabilityInterface, 0, len(values)) + for _, value := range values { + c, err := unmarshalCapability(value) + if err != nil { + return nil, err + } + caps = append(caps, c) + } + return caps, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/util.go b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/util.go new file mode 100644 index 000000000..d2cfdd6c5 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/apiutil/util.go @@ -0,0 +1,138 @@ +// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. +// +// 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 apiutil + +import ( + "encoding/json" + "fmt" + "net" + "time" + + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" + tspb "google.golang.org/protobuf/types/known/timestamppb" +) + +// workaround. This for the json format compatibility. Once we update senario tests, we can remove this. +type Path struct { + Nlri bgp.AddrPrefixInterface `json:"nlri"` + Age int64 `json:"age"` + Best bool `json:"best"` + Attrs []bgp.PathAttributeInterface `json:"attrs"` + Stale bool `json:"stale"` + Withdrawal bool `json:"withdrawal,omitempty"` + SourceID net.IP `json:"source-id,omitempty"` + NeighborIP net.IP `json:"neighbor-ip,omitempty"` +} + +type Destination struct { + Paths []*Path +} + +func (d *Destination) MarshalJSON() ([]byte, error) { + return json.Marshal(d.Paths) +} + +func NewDestination(dst *api.Destination) *Destination { + l := make([]*Path, 0, len(dst.Paths)) + for _, p := range dst.Paths { + nlri, _ := GetNativeNlri(p) + attrs, _ := GetNativePathAttributes(p) + l = append(l, &Path{ + Nlri: nlri, + Age: p.Age.AsTime().Unix(), + Best: p.Best, + Attrs: attrs, + Stale: p.Stale, + Withdrawal: p.IsWithdraw, + SourceID: net.ParseIP(p.SourceId), + NeighborIP: net.ParseIP(p.NeighborIp), + }) + } + return &Destination{Paths: l} +} + +func NewPath(nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, age time.Time) (*api.Path, error) { + n, err := MarshalNLRI(nlri) + if err != nil { + return nil, err + } + a, err := MarshalPathAttributes(attrs) + if err != nil { + return nil, err + } + return &api.Path{ + Nlri: n, + Pattrs: a, + Age: tspb.New(age), + IsWithdraw: isWithdraw, + Family: ToApiFamily(nlri.AFI(), nlri.SAFI()), + Identifier: nlri.PathIdentifier(), + }, nil +} + +func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error) { + afi, safi := bgp.RouteFamilyToAfiSafi(family) + nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi) + if err != nil { + return nil, err + } + if err := nlri.DecodeFromBytes(buf); err != nil { + return nil, err + } + return nlri, nil +} + +func GetNativeNlri(p *api.Path) (bgp.AddrPrefixInterface, error) { + if p.Family == nil { + return nil, fmt.Errorf("family cannot be nil") + } + if len(p.NlriBinary) > 0 { + return getNLRI(ToRouteFamily(p.Family), p.NlriBinary) + } + return UnmarshalNLRI(ToRouteFamily(p.Family), p.Nlri) +} + +func GetNativePathAttributes(p *api.Path) ([]bgp.PathAttributeInterface, error) { + pattrsLen := len(p.PattrsBinary) + if pattrsLen > 0 { + pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen) + for _, attr := range p.PattrsBinary { + a, err := bgp.GetPathAttribute(attr) + if err != nil { + return nil, err + } + err = a.DecodeFromBytes(attr) + if err != nil { + return nil, err + } + pattrs = append(pattrs, a) + } + return pattrs, nil + } + return UnmarshalPathAttributes(p.Pattrs) +} + +func ToRouteFamily(f *api.Family) bgp.RouteFamily { + return bgp.AfiSafiToRouteFamily(uint16(f.Afi), uint8(f.Safi)) +} + +func ToApiFamily(afi uint16, safi uint8) *api.Family { + return &api.Family{ + Afi: api.Family_Afi(afi), + Safi: api.Family_Safi(safi), + } +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/config/config.go b/vendor/github.com/osrg/gobgp/v3/pkg/config/config.go new file mode 100644 index 000000000..3da630799 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/config/config.go @@ -0,0 +1,415 @@ +package config + +import ( + "golang.org/x/net/context" + apb "google.golang.org/protobuf/types/known/anypb" + + api "github.com/osrg/gobgp/v3/api" + "github.com/osrg/gobgp/v3/internal/pkg/config" + "github.com/osrg/gobgp/v3/internal/pkg/table" + "github.com/osrg/gobgp/v3/pkg/apiutil" + "github.com/osrg/gobgp/v3/pkg/log" + "github.com/osrg/gobgp/v3/pkg/packet/bgp" + "github.com/osrg/gobgp/v3/pkg/server" +) + +// ReadConfigFile parses a config file into a BgpConfigSet which can be applied +// using InitialConfig and UpdateConfig. +func ReadConfigFile(configFile, configType string) (*config.BgpConfigSet, error) { + return config.ReadConfigfile(configFile, configType) +} + +func marshalRouteTargets(l []string) ([]*apb.Any, error) { + rtList := make([]*apb.Any, 0, len(l)) + for _, rtString := range l { + rt, err := bgp.ParseRouteTarget(rtString) + if err != nil { + return nil, err + } + a, err := apiutil.MarshalRT(rt) + if err != nil { + return nil, err + } + rtList = append(rtList, a) + } + return rtList, nil +} + +func assignGlobalpolicy(ctx context.Context, bgpServer *server.BgpServer, a *config.ApplyPolicyConfig) { + toDefaultTable := func(r config.DefaultPolicyType) table.RouteType { + var def table.RouteType + switch r { + case config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE: + def = table.ROUTE_TYPE_ACCEPT + case config.DEFAULT_POLICY_TYPE_REJECT_ROUTE: + def = table.ROUTE_TYPE_REJECT + } + return def + } + toPolicies := func(r []string) []*table.Policy { + p := make([]*table.Policy, 0, len(r)) + for _, n := range r { + p = append(p, &table.Policy{ + Name: n, + }) + } + return p + } + + def := toDefaultTable(a.DefaultImportPolicy) + ps := toPolicies(a.ImportPolicyList) + bgpServer.SetPolicyAssignment(ctx, &api.SetPolicyAssignmentRequest{ + Assignment: table.NewAPIPolicyAssignmentFromTableStruct(&table.PolicyAssignment{ + Name: table.GLOBAL_RIB_NAME, + Type: table.POLICY_DIRECTION_IMPORT, + Policies: ps, + Default: def, + }), + }) + + def = toDefaultTable(a.DefaultExportPolicy) + ps = toPolicies(a.ExportPolicyList) + bgpServer.SetPolicyAssignment(ctx, &api.SetPolicyAssignmentRequest{ + Assignment: table.NewAPIPolicyAssignmentFromTableStruct(&table.PolicyAssignment{ + Name: table.GLOBAL_RIB_NAME, + Type: table.POLICY_DIRECTION_EXPORT, + Policies: ps, + Default: def, + }), + }) + +} + +func addPeerGroups(ctx context.Context, bgpServer *server.BgpServer, addedPg []config.PeerGroup) { + for _, pg := range addedPg { + bgpServer.Log().Info("Add PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName, + }) + + if err := bgpServer.AddPeerGroup(ctx, &api.AddPeerGroupRequest{ + PeerGroup: config.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + bgpServer.Log().Warn("Failed to add PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName, + "Error": err}) + } + } +} + +func deletePeerGroups(ctx context.Context, bgpServer *server.BgpServer, deletedPg []config.PeerGroup) { + for _, pg := range deletedPg { + bgpServer.Log().Info("delete PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName}) + if err := bgpServer.DeletePeerGroup(ctx, &api.DeletePeerGroupRequest{ + Name: pg.Config.PeerGroupName, + }); err != nil { + bgpServer.Log().Warn("Failed to delete PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName, + "Error": err}) + } + } +} + +func updatePeerGroups(ctx context.Context, bgpServer *server.BgpServer, updatedPg []config.PeerGroup) bool { + for _, pg := range updatedPg { + bgpServer.Log().Info("update PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName}) + if u, err := bgpServer.UpdatePeerGroup(ctx, &api.UpdatePeerGroupRequest{ + PeerGroup: config.NewPeerGroupFromConfigStruct(&pg), + }); err != nil { + bgpServer.Log().Warn("Failed to update PeerGroup", + log.Fields{ + "Topic": "config", + "Key": pg.Config.PeerGroupName, + "Error": err}) + } else { + return u.NeedsSoftResetIn + } + } + return false +} + +func addDynamicNeighbors(ctx context.Context, bgpServer *server.BgpServer, dynamicNeighbors []config.DynamicNeighbor) { + for _, dn := range dynamicNeighbors { + bgpServer.Log().Info("Add Dynamic Neighbor to PeerGroup", + log.Fields{ + "Topic": "config", + "Key": dn.Config.PeerGroup, + "Prefix": dn.Config.Prefix}) + if err := bgpServer.AddDynamicNeighbor(ctx, &api.AddDynamicNeighborRequest{ + DynamicNeighbor: &api.DynamicNeighbor{ + Prefix: dn.Config.Prefix, + PeerGroup: dn.Config.PeerGroup, + }, + }); err != nil { + bgpServer.Log().Warn("Failed to add Dynamic Neighbor to PeerGroup", + log.Fields{ + "Topic": "config", + "Key": dn.Config.PeerGroup, + "Prefix": dn.Config.Prefix, + "Error": err}) + } + } +} + +func addNeighbors(ctx context.Context, bgpServer *server.BgpServer, added []config.Neighbor) { + for _, p := range added { + bgpServer.Log().Info("Add Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress}) + if err := bgpServer.AddPeer(ctx, &api.AddPeerRequest{ + Peer: config.NewPeerFromConfigStruct(&p), + }); err != nil { + bgpServer.Log().Warn("Failed to add Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress, + "Error": err}) + } + } +} + +func deleteNeighbors(ctx context.Context, bgpServer *server.BgpServer, deleted []config.Neighbor) { + for _, p := range deleted { + bgpServer.Log().Info("Delete Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress}) + if err := bgpServer.DeletePeer(ctx, &api.DeletePeerRequest{ + Address: p.State.NeighborAddress, + }); err != nil { + bgpServer.Log().Warn("Failed to delete Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress, + "Error": err}) + } + } +} + +func updateNeighbors(ctx context.Context, bgpServer *server.BgpServer, updated []config.Neighbor) bool { + for _, p := range updated { + bgpServer.Log().Info("Update Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress}) + if u, err := bgpServer.UpdatePeer(ctx, &api.UpdatePeerRequest{ + Peer: config.NewPeerFromConfigStruct(&p), + }); err != nil { + bgpServer.Log().Warn("Failed to update Peer", + log.Fields{ + "Topic": "config", + "Key": p.State.NeighborAddress, + "Error": err}) + } else { + return u.NeedsSoftResetIn + } + } + return false +} + +// InitialConfig applies initial configuration to a pristine gobgp instance. It +// can only be called once for an instance. Subsequent changes to the +// configuration can be applied using UpdateConfig. The BgpConfigSet can be +// obtained by calling ReadConfigFile. If graceful restart behavior is desired, +// pass true for isGracefulRestart. Otherwise, pass false. +func InitialConfig(ctx context.Context, bgpServer *server.BgpServer, newConfig *config.BgpConfigSet, isGracefulRestart bool) (*config.BgpConfigSet, error) { + if err := bgpServer.StartBgp(ctx, &api.StartBgpRequest{ + Global: config.NewGlobalFromConfigStruct(&newConfig.Global), + }); err != nil { + bgpServer.Log().Fatal("failed to set global config", + log.Fields{"Topic": "config", "Error": err}) + } + + if newConfig.Zebra.Config.Enabled { + tps := newConfig.Zebra.Config.RedistributeRouteTypeList + l := make([]string, 0, len(tps)) + l = append(l, tps...) + if err := bgpServer.EnableZebra(ctx, &api.EnableZebraRequest{ + Url: newConfig.Zebra.Config.Url, + RouteTypes: l, + Version: uint32(newConfig.Zebra.Config.Version), + NexthopTriggerEnable: newConfig.Zebra.Config.NexthopTriggerEnable, + NexthopTriggerDelay: uint32(newConfig.Zebra.Config.NexthopTriggerDelay), + MplsLabelRangeSize: uint32(newConfig.Zebra.Config.MplsLabelRangeSize), + SoftwareName: newConfig.Zebra.Config.SoftwareName, + }); err != nil { + bgpServer.Log().Fatal("failed to set zebra config", + log.Fields{"Topic": "config", "Error": err}) + } + } + + if len(newConfig.Collector.Config.Url) > 0 { + bgpServer.Log().Fatal("collector feature is not supported", + log.Fields{"Topic": "config"}) + } + + for _, c := range newConfig.RpkiServers { + if err := bgpServer.AddRpki(ctx, &api.AddRpkiRequest{ + Address: c.Config.Address, + Port: c.Config.Port, + Lifetime: c.Config.RecordLifetime, + }); err != nil { + bgpServer.Log().Fatal("failed to set rpki config", + log.Fields{"Topic": "config", "Error": err}) + } + } + for _, c := range newConfig.BmpServers { + if err := bgpServer.AddBmp(ctx, &api.AddBmpRequest{ + Address: c.Config.Address, + Port: c.Config.Port, + SysName: c.Config.SysName, + SysDescr: c.Config.SysDescr, + Policy: api.AddBmpRequest_MonitoringPolicy(c.Config.RouteMonitoringPolicy.ToInt()), + StatisticsTimeout: int32(c.Config.StatisticsTimeout), + }); err != nil { + bgpServer.Log().Fatal("failed to set bmp config", + log.Fields{"Topic": "config", "Error": err}) + } + } + for _, vrf := range newConfig.Vrfs { + rd, err := bgp.ParseRouteDistinguisher(vrf.Config.Rd) + if err != nil { + bgpServer.Log().Fatal("failed to load vrf rd config", + log.Fields{"Topic": "config", "Error": err}) + } + + importRtList, err := marshalRouteTargets(vrf.Config.ImportRtList) + if err != nil { + bgpServer.Log().Fatal("failed to load vrf import rt config", + log.Fields{"Topic": "config", "Error": err}) + } + exportRtList, err := marshalRouteTargets(vrf.Config.ExportRtList) + if err != nil { + bgpServer.Log().Fatal("failed to load vrf export rt config", + log.Fields{"Topic": "config", "Error": err}) + } + + a, err := apiutil.MarshalRD(rd) + if err != nil { + bgpServer.Log().Fatal("failed to set vrf config", + log.Fields{"Topic": "config", "Error": err}) + } + if err := bgpServer.AddVrf(ctx, &api.AddVrfRequest{ + Vrf: &api.Vrf{ + Name: vrf.Config.Name, + Rd: a, + Id: uint32(vrf.Config.Id), + ImportRt: importRtList, + ExportRt: exportRtList, + }, + }); err != nil { + bgpServer.Log().Fatal("failed to set vrf config", + log.Fields{"Topic": "config", "Error": err}) + } + } + for _, c := range newConfig.MrtDump { + if len(c.Config.FileName) == 0 { + continue + } + if err := bgpServer.EnableMrt(ctx, &api.EnableMrtRequest{ + Type: api.EnableMrtRequest_DumpType(c.Config.DumpType.ToInt()), + Filename: c.Config.FileName, + DumpInterval: c.Config.DumpInterval, + RotationInterval: c.Config.RotationInterval, + }); err != nil { + bgpServer.Log().Fatal("failed to set mrt config", + log.Fields{"Topic": "config", "Error": err}) + } + } + p := config.ConfigSetToRoutingPolicy(newConfig) + rp, err := table.NewAPIRoutingPolicyFromConfigStruct(p) + if err != nil { + bgpServer.Log().Fatal("failed to update policy config", + log.Fields{"Topic": "config", "Error": err}) + } else { + bgpServer.SetPolicies(ctx, &api.SetPoliciesRequest{ + DefinedSets: rp.DefinedSets, + Policies: rp.Policies, + }) + } + + assignGlobalpolicy(ctx, bgpServer, &newConfig.Global.ApplyPolicy.Config) + + added := newConfig.Neighbors + addedPg := newConfig.PeerGroups + if isGracefulRestart { + for i, n := range added { + if n.GracefulRestart.Config.Enabled { + added[i].GracefulRestart.State.LocalRestarting = true + } + } + } + + addPeerGroups(ctx, bgpServer, addedPg) + addDynamicNeighbors(ctx, bgpServer, newConfig.DynamicNeighbors) + addNeighbors(ctx, bgpServer, added) + return newConfig, nil +} + +// UpdateConfig updates the configuration of a running gobgp instance. +// InitialConfig must have been called once before this can be called for +// subsequent changes to config. The differences are that this call 1) does not +// hangle graceful restart and 2) requires a BgpConfigSet for the previous +// configuration so that it can compute the delta between it and the new +// config. The new BgpConfigSet can be obtained using ReadConfigFile. +func UpdateConfig(ctx context.Context, bgpServer *server.BgpServer, c, newConfig *config.BgpConfigSet) (*config.BgpConfigSet, error) { + addedPg, deletedPg, updatedPg := config.UpdatePeerGroupConfig(bgpServer.Log(), c, newConfig) + added, deleted, updated := config.UpdateNeighborConfig(bgpServer.Log(), c, newConfig) + updatePolicy := config.CheckPolicyDifference(bgpServer.Log(), config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig)) + + if updatePolicy { + bgpServer.Log().Info("policy config is update", log.Fields{"Topic": "config"}) + p := config.ConfigSetToRoutingPolicy(newConfig) + rp, err := table.NewAPIRoutingPolicyFromConfigStruct(p) + if err != nil { + bgpServer.Log().Warn("failed to update policy config", + log.Fields{ + "Topic": "config", + "Error": err}) + } else { + bgpServer.SetPolicies(ctx, &api.SetPoliciesRequest{ + DefinedSets: rp.DefinedSets, + Policies: rp.Policies, + }) + } + } + // global policy update + if !newConfig.Global.ApplyPolicy.Config.Equal(&c.Global.ApplyPolicy.Config) { + assignGlobalpolicy(ctx, bgpServer, &newConfig.Global.ApplyPolicy.Config) + updatePolicy = true + } + + addPeerGroups(ctx, bgpServer, addedPg) + deletePeerGroups(ctx, bgpServer, deletedPg) + needsSoftResetIn := updatePeerGroups(ctx, bgpServer, updatedPg) + updatePolicy = updatePolicy || needsSoftResetIn + addDynamicNeighbors(ctx, bgpServer, newConfig.DynamicNeighbors) + addNeighbors(ctx, bgpServer, added) + deleteNeighbors(ctx, bgpServer, deleted) + needsSoftResetIn = updateNeighbors(ctx, bgpServer, updated) + updatePolicy = updatePolicy || needsSoftResetIn + + if updatePolicy { + if err := bgpServer.ResetPeer(ctx, &api.ResetPeerRequest{ + Address: "", + Direction: api.ResetPeerRequest_IN, + Soft: true, + }); err != nil { + bgpServer.Log().Fatal("failed to update policy config", + log.Fields{"Topic": "config", "Error": err}) + } + } + return newConfig, nil +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/log/logger.go b/vendor/github.com/osrg/gobgp/v3/pkg/log/logger.go new file mode 100644 index 000000000..97a783057 --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/log/logger.go @@ -0,0 +1,87 @@ +// Copyright (C) 2021 Nippon Telegraph and Telephone Corporation. +// +// 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 log + +import ( + "github.com/sirupsen/logrus" +) + +type LogLevel uint32 + +const ( + PanicLevel LogLevel = iota + FatalLevel + ErrorLevel + WarnLevel + InfoLevel + DebugLevel + TraceLevel +) + +type Fields map[string]interface{} + +type Logger interface { + Panic(msg string, fields Fields) + Fatal(msg string, fields Fields) + Error(msg string, fields Fields) + Warn(msg string, fields Fields) + Info(msg string, fields Fields) + Debug(msg string, fields Fields) + SetLevel(level LogLevel) + GetLevel() LogLevel +} + +type DefaultLogger struct { + logger *logrus.Logger +} + +func (l *DefaultLogger) Panic(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Panic(msg) +} + +func (l *DefaultLogger) Fatal(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Fatal(msg) +} + +func (l *DefaultLogger) Error(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Error(msg) +} + +func (l *DefaultLogger) Warn(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Warn(msg) +} + +func (l *DefaultLogger) Info(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Info(msg) +} + +func (l *DefaultLogger) Debug(msg string, fields Fields) { + l.logger.WithFields(logrus.Fields(fields)).Debug(msg) +} + +func (l *DefaultLogger) SetLevel(level LogLevel) { + l.logger.SetLevel(logrus.Level(level)) +} + +func (l *DefaultLogger) GetLevel() LogLevel { + return LogLevel(l.logger.GetLevel()) +} + +func NewDefaultLogger() *DefaultLogger { + return &DefaultLogger{ + logger: logrus.New(), + } +} diff --git a/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go b/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go new file mode 100644 index 000000000..7c2e807bf --- /dev/null +++ b/vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go @@ -0,0 +1,13633 @@ +// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. +// +// 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 bgp + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "math" + "net" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "sync" +) + +type MarshallingOption struct { + AddPath map[RouteFamily]BGPAddPathMode + Attributes map[BGPAttrType]bool +} + +func IsAddPathEnabled(decode bool, f RouteFamily, options []*MarshallingOption) bool { + for _, opt := range options { + if opt == nil { + continue + } + if o := opt.AddPath; o != nil { + if decode && o[f]&BGP_ADD_PATH_RECEIVE > 0 { + return true + } else if !decode && o[f]&BGP_ADD_PATH_SEND > 0 { + return true + } + } + } + return false +} +func IsAttributePresent(attr BGPAttrType, options []*MarshallingOption) bool { + for _, opt := range options { + if opt == nil { + continue + } + if o := opt.Attributes; o != nil { + _, ok := o[attr] + return ok + } + } + return false +} + +const ( + AFI_IP = 1 + AFI_IP6 = 2 + AFI_L2VPN = 25 + AFI_LS = 16388 + AFI_OPAQUE = 16397 +) + +const ( + SAFI_UNICAST = 1 + SAFI_MULTICAST = 2 + SAFI_MPLS_LABEL = 4 + SAFI_ENCAPSULATION = 7 + SAFI_VPLS = 65 + SAFI_EVPN = 70 + SAFI_LS = 71 + SAFI_SRPOLICY = 73 + SAFI_MUP = 85 + SAFI_MPLS_VPN = 128 + SAFI_MPLS_VPN_MULTICAST = 129 + SAFI_ROUTE_TARGET_CONSTRAINTS = 132 + SAFI_FLOW_SPEC_UNICAST = 133 + SAFI_FLOW_SPEC_VPN = 134 + SAFI_KEY_VALUE = 241 +) + +const ( + BGP_ORIGIN_ATTR_TYPE_IGP uint8 = 0 + BGP_ORIGIN_ATTR_TYPE_EGP uint8 = 1 + BGP_ORIGIN_ATTR_TYPE_INCOMPLETE uint8 = 2 +) + +const ( + BGP_ASPATH_ATTR_TYPE_SET = 1 + BGP_ASPATH_ATTR_TYPE_SEQ = 2 + BGP_ASPATH_ATTR_TYPE_CONFED_SEQ = 3 + BGP_ASPATH_ATTR_TYPE_CONFED_SET = 4 +) + +const ( + BGP_ATTR_NHLEN_IPV6_GLOBAL = 16 + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL = 32 +) + +// RFC7153 5.1. Registries for the "Type" Field +// RANGE REGISTRATION PROCEDURES +// 0x00-0x3F Transitive First Come First Served +// 0x40-0x7F Non-Transitive First Come First Served +// 0x80-0x8F Transitive Experimental Use +// 0x90-0xBF Transitive Standards Action +// 0xC0-0xCF Non-Transitive Experimental Use +// 0xD0-0xFF Non-Transitive Standards Action +type ExtendedCommunityAttrType uint8 + +const ( + EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC ExtendedCommunityAttrType = 0x00 + EC_TYPE_TRANSITIVE_IP6_SPECIFIC ExtendedCommunityAttrType = 0x00 // RFC5701 + EC_TYPE_TRANSITIVE_IP4_SPECIFIC ExtendedCommunityAttrType = 0x01 + EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC ExtendedCommunityAttrType = 0x02 + EC_TYPE_TRANSITIVE_OPAQUE ExtendedCommunityAttrType = 0x03 + EC_TYPE_TRANSITIVE_QOS_MARKING ExtendedCommunityAttrType = 0x04 + EC_TYPE_COS_CAPABILITY ExtendedCommunityAttrType = 0x05 + EC_TYPE_EVPN ExtendedCommunityAttrType = 0x06 + EC_TYPE_FLOWSPEC_REDIRECT_MIRROR ExtendedCommunityAttrType = 0x08 + EC_TYPE_MUP ExtendedCommunityAttrType = 0x0c + EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC ExtendedCommunityAttrType = 0x40 + EC_TYPE_NON_TRANSITIVE_LINK_BANDWIDTH ExtendedCommunityAttrType = 0x40 + EC_TYPE_NON_TRANSITIVE_IP6_SPECIFIC ExtendedCommunityAttrType = 0x40 // RFC5701 + EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC ExtendedCommunityAttrType = 0x41 + EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC ExtendedCommunityAttrType = 0x42 + EC_TYPE_NON_TRANSITIVE_OPAQUE ExtendedCommunityAttrType = 0x43 + EC_TYPE_NON_TRANSITIVE_QOS_MARKING ExtendedCommunityAttrType = 0x44 + EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL ExtendedCommunityAttrType = 0x80 + EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2 ExtendedCommunityAttrType = 0x81 // RFC7674 + EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3 ExtendedCommunityAttrType = 0x82 // RFC7674 +) + +// RFC7153 5.2. Registries for the "Sub-Type" Field +// RANGE REGISTRATION PROCEDURES +// 0x00-0xBF First Come First Served +// 0xC0-0xFF IETF Review +type ExtendedCommunityAttrSubType uint8 + +const ( + EC_SUBTYPE_ROUTE_TARGET ExtendedCommunityAttrSubType = 0x02 // EC_TYPE: 0x00, 0x01, 0x02 + EC_SUBTYPE_ROUTE_ORIGIN ExtendedCommunityAttrSubType = 0x03 // EC_TYPE: 0x00, 0x01, 0x02 + EC_SUBTYPE_LINK_BANDWIDTH ExtendedCommunityAttrSubType = 0x04 // EC_TYPE: 0x40 + EC_SUBTYPE_GENERIC ExtendedCommunityAttrSubType = 0x04 // EC_TYPE: 0x02, 0x42 + EC_SUBTYPE_OSPF_DOMAIN_ID ExtendedCommunityAttrSubType = 0x05 // EC_TYPE: 0x00, 0x01, 0x02 + EC_SUBTYPE_OSPF_ROUTE_ID ExtendedCommunityAttrSubType = 0x07 // EC_TYPE: 0x01 + EC_SUBTYPE_BGP_DATA_COLLECTION ExtendedCommunityAttrSubType = 0x08 // EC_TYPE: 0x00, 0x02 + EC_SUBTYPE_SOURCE_AS ExtendedCommunityAttrSubType = 0x09 // EC_TYPE: 0x00, 0x02 + EC_SUBTYPE_L2VPN_ID ExtendedCommunityAttrSubType = 0x0A // EC_TYPE: 0x00, 0x01 + EC_SUBTYPE_VRF_ROUTE_IMPORT ExtendedCommunityAttrSubType = 0x0B // EC_TYPE: 0x01 + EC_SUBTYPE_CISCO_VPN_DISTINGUISHER ExtendedCommunityAttrSubType = 0x10 // EC_TYPE: 0x00, 0x01, 0x02 + + EC_SUBTYPE_OSPF_ROUTE_TYPE ExtendedCommunityAttrSubType = 0x06 // EC_TYPE: 0x03 + EC_SUBTYPE_COLOR ExtendedCommunityAttrSubType = 0x0B // EC_TYPE: 0x03 + EC_SUBTYPE_ENCAPSULATION ExtendedCommunityAttrSubType = 0x0C // EC_TYPE: 0x03 + EC_SUBTYPE_DEFAULT_GATEWAY ExtendedCommunityAttrSubType = 0x0D // EC_TYPE: 0x03 + + EC_SUBTYPE_ORIGIN_VALIDATION ExtendedCommunityAttrSubType = 0x00 // EC_TYPE: 0x43 + + EC_SUBTYPE_MUP_DIRECT_SEG ExtendedCommunityAttrSubType = 0x00 // EC_TYPE: 0x0c + + EC_SUBTYPE_FLOWSPEC_TRAFFIC_RATE ExtendedCommunityAttrSubType = 0x06 // EC_TYPE: 0x80 + EC_SUBTYPE_FLOWSPEC_TRAFFIC_ACTION ExtendedCommunityAttrSubType = 0x07 // EC_TYPE: 0x80 + EC_SUBTYPE_FLOWSPEC_REDIRECT ExtendedCommunityAttrSubType = 0x08 // EC_TYPE: 0x80 + EC_SUBTYPE_FLOWSPEC_TRAFFIC_REMARK ExtendedCommunityAttrSubType = 0x09 // EC_TYPE: 0x80 + EC_SUBTYPE_L2_INFO ExtendedCommunityAttrSubType = 0x0A // EC_TYPE: 0x80 + EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6 ExtendedCommunityAttrSubType = 0x0B // EC_TYPE: 0x80 + + EC_SUBTYPE_MAC_MOBILITY ExtendedCommunityAttrSubType = 0x00 // EC_TYPE: 0x06 + EC_SUBTYPE_ESI_LABEL ExtendedCommunityAttrSubType = 0x01 // EC_TYPE: 0x06 + EC_SUBTYPE_ES_IMPORT ExtendedCommunityAttrSubType = 0x02 // EC_TYPE: 0x06 + EC_SUBTYPE_ROUTER_MAC ExtendedCommunityAttrSubType = 0x03 // EC_TYPE: 0x06 + + EC_SUBTYPE_UUID_BASED_RT ExtendedCommunityAttrSubType = 0x11 +) + +type TunnelType uint16 + +const ( + TUNNEL_TYPE_L2TP3 TunnelType = 1 + TUNNEL_TYPE_GRE TunnelType = 2 + TUNNEL_TYPE_IP_IN_IP TunnelType = 7 + TUNNEL_TYPE_VXLAN TunnelType = 8 + TUNNEL_TYPE_NVGRE TunnelType = 9 + TUNNEL_TYPE_MPLS TunnelType = 10 + TUNNEL_TYPE_MPLS_IN_GRE TunnelType = 11 + TUNNEL_TYPE_VXLAN_GRE TunnelType = 12 + TUNNEL_TYPE_MPLS_IN_UDP TunnelType = 13 + TUNNEL_TYPE_SR_POLICY TunnelType = 15 + TUNNEL_TYPE_GENEVE TunnelType = 19 +) + +func (p TunnelType) String() string { + switch p { + case TUNNEL_TYPE_L2TP3: + return "l2tp3" + case TUNNEL_TYPE_GRE: + return "gre" + case TUNNEL_TYPE_IP_IN_IP: + return "ip-in-ip" + case TUNNEL_TYPE_VXLAN: + return "vxlan" + case TUNNEL_TYPE_NVGRE: + return "nvgre" + case TUNNEL_TYPE_MPLS: + return "mpls" + case TUNNEL_TYPE_MPLS_IN_GRE: + return "mpls-in-gre" + case TUNNEL_TYPE_VXLAN_GRE: + return "vxlan-gre" + case TUNNEL_TYPE_MPLS_IN_UDP: + return "mpls-in-udp" + case TUNNEL_TYPE_SR_POLICY: + return "sr-policy" + case TUNNEL_TYPE_GENEVE: + return "geneve" + default: + return fmt.Sprintf("TunnelType(%d)", uint8(p)) + } +} + +type PmsiTunnelType uint8 + +const ( + PMSI_TUNNEL_TYPE_NO_TUNNEL PmsiTunnelType = 0 + PMSI_TUNNEL_TYPE_RSVP_TE_P2MP PmsiTunnelType = 1 + PMSI_TUNNEL_TYPE_MLDP_P2MP PmsiTunnelType = 2 + PMSI_TUNNEL_TYPE_PIM_SSM_TREE PmsiTunnelType = 3 + PMSI_TUNNEL_TYPE_PIM_SM_TREE PmsiTunnelType = 4 + PMSI_TUNNEL_TYPE_BIDIR_PIM_TREE PmsiTunnelType = 5 + PMSI_TUNNEL_TYPE_INGRESS_REPL PmsiTunnelType = 6 + PMSI_TUNNEL_TYPE_MLDP_MP2MP PmsiTunnelType = 7 +) + +func (p PmsiTunnelType) String() string { + switch p { + case PMSI_TUNNEL_TYPE_NO_TUNNEL: + return "no-tunnel" + case PMSI_TUNNEL_TYPE_RSVP_TE_P2MP: + return "rsvp-te-p2mp" + case PMSI_TUNNEL_TYPE_MLDP_P2MP: + return "mldp-p2mp" + case PMSI_TUNNEL_TYPE_PIM_SSM_TREE: + return "pim-ssm-tree" + case PMSI_TUNNEL_TYPE_PIM_SM_TREE: + return "pim-sm-tree" + case PMSI_TUNNEL_TYPE_BIDIR_PIM_TREE: + return "bidir-pim-tree" + case PMSI_TUNNEL_TYPE_INGRESS_REPL: + return "ingress-repl" + case PMSI_TUNNEL_TYPE_MLDP_MP2MP: + return "mldp-mp2mp" + default: + return fmt.Sprintf("PmsiTunnelType(%d)", uint8(p)) + } +} + +type EncapSubTLVType uint8 + +const ( + ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1 + ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2 + ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4 + ENCAP_SUBTLV_TYPE_EGRESS_ENDPOINT EncapSubTLVType = 6 + ENCAP_SUBTLV_TYPE_UDP_DEST_PORT EncapSubTLVType = 8 + ENCAP_SUBTLV_TYPE_SRPREFERENCE EncapSubTLVType = 12 + ENCAP_SUBTLV_TYPE_SRBINDING_SID EncapSubTLVType = 13 + ENCAP_SUBTLV_TYPE_SRENLP EncapSubTLVType = 14 + ENCAP_SUBTLV_TYPE_SRPRIORITY EncapSubTLVType = 15 + ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST EncapSubTLVType = 128 + ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME EncapSubTLVType = 129 +) + +const ( + _ = iota + BGP_MSG_OPEN + BGP_MSG_UPDATE + BGP_MSG_NOTIFICATION + BGP_MSG_KEEPALIVE + BGP_MSG_ROUTE_REFRESH +) + +const ( + BGP_OPT_CAPABILITY = 2 +) + +type BGPCapabilityCode uint8 + +const ( + BGP_CAP_MULTIPROTOCOL BGPCapabilityCode = 1 + BGP_CAP_ROUTE_REFRESH BGPCapabilityCode = 2 + BGP_CAP_CARRYING_LABEL_INFO BGPCapabilityCode = 4 + BGP_CAP_EXTENDED_NEXTHOP BGPCapabilityCode = 5 + BGP_CAP_GRACEFUL_RESTART BGPCapabilityCode = 64 + BGP_CAP_FOUR_OCTET_AS_NUMBER BGPCapabilityCode = 65 + BGP_CAP_ADD_PATH BGPCapabilityCode = 69 + BGP_CAP_ENHANCED_ROUTE_REFRESH BGPCapabilityCode = 70 + BGP_CAP_LONG_LIVED_GRACEFUL_RESTART BGPCapabilityCode = 71 + BGP_CAP_FQDN BGPCapabilityCode = 73 + BGP_CAP_ROUTE_REFRESH_CISCO BGPCapabilityCode = 128 +) + +var CapNameMap = map[BGPCapabilityCode]string{ + BGP_CAP_MULTIPROTOCOL: "multiprotocol", + BGP_CAP_ROUTE_REFRESH: "route-refresh", + BGP_CAP_CARRYING_LABEL_INFO: "carrying-label-info", + BGP_CAP_GRACEFUL_RESTART: "graceful-restart", + BGP_CAP_EXTENDED_NEXTHOP: "extended-nexthop", + BGP_CAP_FOUR_OCTET_AS_NUMBER: "4-octet-as", + BGP_CAP_ADD_PATH: "add-path", + BGP_CAP_ENHANCED_ROUTE_REFRESH: "enhanced-route-refresh", + BGP_CAP_ROUTE_REFRESH_CISCO: "cisco-route-refresh", + BGP_CAP_LONG_LIVED_GRACEFUL_RESTART: "long-lived-graceful-restart", + BGP_CAP_FQDN: "fqdn", +} + +func (c BGPCapabilityCode) String() string { + if n, y := CapNameMap[c]; y { + return n + } + return fmt.Sprintf("UnknownCapability(%d)", c) +} + +var ( + // Used parsing RouteDistinguisher + _regexpRouteDistinguisher = regexp.MustCompile(`^((\d+)\.(\d+)\.(\d+)\.(\d+)|((\d+)\.)?(\d+)|([\w]+:[\w:]*:[\w]+)):(\d+)$`) + + // Used for operator and value for the FlowSpec numeric type + // Example: + // re.FindStringSubmatch("&==80") + // >>> ["&==80" "&" "==" "80"] + _regexpFlowSpecNumericType = regexp.MustCompile(`(&?)(==|=|>|>=|<|<=|!|!=|=!)?(\d+|-\d|true|false)`) + + // - "=!" is used in the old style format of "tcp-flags" and "fragment". + // - The value field should be one of the followings: + // * Decimal value (e.g., 80) + // * Combination of the small letters, decimals, "-" and "+" + // (e.g., tcp, ipv4, is-fragment+first-fragment) + // * Capital letters (e.g., SA) + _regexpFlowSpecOperator = regexp.MustCompile(`&|=|>|<|!|[\w\-+]+`) + _regexpFlowSpecOperatorValue = regexp.MustCompile(`[\w\-+]+`) + + // Note: "(-*)" and "(.*)" catch the invalid flags + // Example: In this case, "Z" is unsupported flag type. + // re.FindStringSubmatch("&==-SZU") + // >>> ["&==-SZU" "&" "==" "-" "S" "ZU"] + _regexpFlowSpecTCPFlag = regexp.MustCompile("(&?)(==|=|!|!=|=!)?(-*)([FSRPAUCE]+)(.*)") + + // Note: "(.*)" catches the invalid flags + // re.FindStringSubmatch("&!=+first-fragment+last-fragment+invalid-fragment") + // >>> ["&!=+first-fragment+last-fragment+invalid-fragment" "&" "!=" "+first-fragment+last-fragment" "+last-fragment" "+" "last" "+invalid-fragment"] + _regexpFlowSpecFragment = regexp.MustCompile(`(&?)(==|=|!|!=|=!)?(((\+)?(dont|is|first|last|not-a)-fragment)+)(.*)`) + + // re.FindStringSubmatch("192.168.0.0/24") + // >>> ["192.168.0.0/24" "192.168.0.0" "/24" "24"] + // re.FindStringSubmatch("192.168.0.1") + // >>> ["192.168.0.1" "192.168.0.1" "" ""] + _regexpFindIPv4Prefix = regexp.MustCompile(`^([\d.]+)(/(\d{1,2}))?`) + + // re.FindStringSubmatch("2001:dB8::/64") + // >>> ["2001:dB8::/64" "2001:dB8::" "/64" "64" "" ""] + // re.FindStringSubmatch("2001:dB8::/64/8") + // >>> ["2001:dB8::/64/8" "2001:dB8::" "/64" "64" "/8" "8"] + // re.FindStringSubmatch("2001:dB8::1") + // >>> ["2001:dB8::1" "2001:dB8::1" "" "" "" ""] + _regexpFindIPv6Prefix = regexp.MustCompile(`^([a-fA-F\d:.]+)(/(\d{1,3}))?(/(\d{1,3}))?`) +) + +type ParameterCapabilityInterface interface { + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + Len() int + Code() BGPCapabilityCode +} + +type DefaultParameterCapability struct { + CapCode BGPCapabilityCode `json:"code"` + CapLen uint8 `json:"-"` + CapValue []byte `json:"value,omitempty"` +} + +func (c *DefaultParameterCapability) Code() BGPCapabilityCode { + return c.CapCode +} + +func (c *DefaultParameterCapability) DecodeFromBytes(data []byte) error { + c.CapCode = BGPCapabilityCode(data[0]) + c.CapLen = data[1] + if len(data) < 2+int(c.CapLen) { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all OptionParameterCapability bytes available") + } + if c.CapLen > 0 { + c.CapValue = data[2 : 2+c.CapLen] + } + return nil +} + +func (c *DefaultParameterCapability) Serialize() ([]byte, error) { + c.CapLen = uint8(len(c.CapValue)) + buf := make([]byte, 2+len(c.CapValue)) + buf[0] = uint8(c.CapCode) + buf[1] = c.CapLen + copy(buf[2:], c.CapValue) + return buf, nil +} + +func (c *DefaultParameterCapability) Len() int { + return int(c.CapLen + 2) +} + +type CapMultiProtocol struct { + DefaultParameterCapability + CapValue RouteFamily +} + +func (c *CapMultiProtocol) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 4 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityMultiProtocol bytes available") + } + c.CapValue = AfiSafiToRouteFamily(binary.BigEndian.Uint16(data[0:2]), data[3]) + return nil +} + +func (c *CapMultiProtocol) Serialize() ([]byte, error) { + buf := make([]byte, 4) + afi, safi := RouteFamilyToAfiSafi(c.CapValue) + binary.BigEndian.PutUint16(buf[0:], afi) + buf[3] = safi + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapMultiProtocol) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Value RouteFamily `json:"value"` + }{ + Code: c.Code(), + Value: c.CapValue, + }) +} + +func NewCapMultiProtocol(rf RouteFamily) *CapMultiProtocol { + return &CapMultiProtocol{ + DefaultParameterCapability{ + CapCode: BGP_CAP_MULTIPROTOCOL, + }, + rf, + } +} + +type CapRouteRefresh struct { + DefaultParameterCapability +} + +func NewCapRouteRefresh() *CapRouteRefresh { + return &CapRouteRefresh{ + DefaultParameterCapability{ + CapCode: BGP_CAP_ROUTE_REFRESH, + }, + } +} + +type CapCarryingLabelInfo struct { + DefaultParameterCapability +} + +func NewCapCarryingLabelInfo() *CapCarryingLabelInfo { + return &CapCarryingLabelInfo{ + DefaultParameterCapability{ + CapCode: BGP_CAP_CARRYING_LABEL_INFO, + }, + } +} + +type CapExtendedNexthopTuple struct { + NLRIAFI uint16 + NLRISAFI uint16 + NexthopAFI uint16 +} + +func (c *CapExtendedNexthopTuple) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + NLRIAddressFamily RouteFamily `json:"nlri_address_family"` + NexthopAddressFamily uint16 `json:"nexthop_address_family"` + }{ + NLRIAddressFamily: AfiSafiToRouteFamily(c.NLRIAFI, uint8(c.NLRISAFI)), + NexthopAddressFamily: c.NexthopAFI, + }) +} + +func NewCapExtendedNexthopTuple(af RouteFamily, nexthop uint16) *CapExtendedNexthopTuple { + afi, safi := RouteFamilyToAfiSafi(af) + return &CapExtendedNexthopTuple{ + NLRIAFI: afi, + NLRISAFI: uint16(safi), + NexthopAFI: nexthop, + } +} + +type CapExtendedNexthop struct { + DefaultParameterCapability + Tuples []*CapExtendedNexthopTuple +} + +func (c *CapExtendedNexthop) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + capLen := int(c.CapLen) + if capLen%6 != 0 || capLen < 6 || len(data) < capLen { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityExtendedNexthop bytes available") + } + + c.Tuples = []*CapExtendedNexthopTuple{} + for capLen >= 6 { + t := &CapExtendedNexthopTuple{ + binary.BigEndian.Uint16(data[0:2]), + binary.BigEndian.Uint16(data[2:4]), + binary.BigEndian.Uint16(data[4:6]), + } + c.Tuples = append(c.Tuples, t) + data = data[6:] + capLen -= 6 + } + return nil +} + +func (c *CapExtendedNexthop) Serialize() ([]byte, error) { + buf := make([]byte, len(c.Tuples)*6) + for i, t := range c.Tuples { + binary.BigEndian.PutUint16(buf[i*6:i*6+2], t.NLRIAFI) + binary.BigEndian.PutUint16(buf[i*6+2:i*6+4], t.NLRISAFI) + binary.BigEndian.PutUint16(buf[i*6+4:i*6+6], t.NexthopAFI) + } + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapExtendedNexthop) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Tuples []*CapExtendedNexthopTuple `json:"tuples"` + }{ + Code: c.Code(), + Tuples: c.Tuples, + }) +} + +func NewCapExtendedNexthop(tuples []*CapExtendedNexthopTuple) *CapExtendedNexthop { + return &CapExtendedNexthop{ + DefaultParameterCapability{ + CapCode: BGP_CAP_EXTENDED_NEXTHOP, + }, + tuples, + } +} + +type CapGracefulRestartTuple struct { + AFI uint16 + SAFI uint8 + Flags uint8 +} + +func (c *CapGracefulRestartTuple) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RouteFamily RouteFamily `json:"route_family"` + Flags uint8 `json:"flags"` + }{ + RouteFamily: AfiSafiToRouteFamily(c.AFI, c.SAFI), + Flags: c.Flags, + }) +} + +func NewCapGracefulRestartTuple(rf RouteFamily, forward bool) *CapGracefulRestartTuple { + afi, safi := RouteFamilyToAfiSafi(rf) + flags := 0 + if forward { + flags = 0x80 + } + return &CapGracefulRestartTuple{ + AFI: afi, + SAFI: safi, + Flags: uint8(flags), + } +} + +type CapGracefulRestart struct { + DefaultParameterCapability + Flags uint8 + Time uint16 + Tuples []*CapGracefulRestartTuple +} + +func (c *CapGracefulRestart) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 2 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityGracefulRestart bytes available") + } + restart := binary.BigEndian.Uint16(data[0:2]) + c.Flags = uint8(restart >> 12) + c.Time = restart & 0xfff + data = data[2:] + + valueLen := int(c.CapLen) - 2 + + if valueLen >= 4 && len(data) >= valueLen { + c.Tuples = make([]*CapGracefulRestartTuple, 0, valueLen/4) + + for i := valueLen; i >= 4; i -= 4 { + t := &CapGracefulRestartTuple{binary.BigEndian.Uint16(data[0:2]), + data[2], data[3]} + c.Tuples = append(c.Tuples, t) + data = data[4:] + } + } + return nil +} + +func (c *CapGracefulRestart) Serialize() ([]byte, error) { + buf := make([]byte, 2, 2+4*len(c.Tuples)) + binary.BigEndian.PutUint16(buf[0:], uint16(c.Flags)<<12|c.Time) + var tbuf [4]byte + for _, t := range c.Tuples { + binary.BigEndian.PutUint16(tbuf[0:2], t.AFI) + tbuf[2] = t.SAFI + tbuf[3] = t.Flags + buf = append(buf, tbuf[:]...) + } + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapGracefulRestart) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Flags uint8 `json:"flags"` + Time uint16 `json:"time"` + Tuples []*CapGracefulRestartTuple `json:"tuples"` + }{ + Code: c.Code(), + Flags: c.Flags, + Time: c.Time, + Tuples: c.Tuples, + }) +} + +func NewCapGracefulRestart(restarting, notification bool, time uint16, tuples []*CapGracefulRestartTuple) *CapGracefulRestart { + flags := 0 + if restarting { + flags = 0x08 + } + if notification { + flags |= 0x04 + } + return &CapGracefulRestart{ + DefaultParameterCapability: DefaultParameterCapability{ + CapCode: BGP_CAP_GRACEFUL_RESTART, + }, + Flags: uint8(flags), + Time: time, + Tuples: tuples, + } +} + +type CapFourOctetASNumber struct { + DefaultParameterCapability + CapValue uint32 +} + +func (c *CapFourOctetASNumber) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 4 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityFourOctetASNumber bytes available") + } + c.CapValue = binary.BigEndian.Uint32(data[0:4]) + return nil +} + +func (c *CapFourOctetASNumber) Serialize() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, c.CapValue) + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapFourOctetASNumber) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Value uint32 `json:"value"` + }{ + Code: c.Code(), + Value: c.CapValue, + }) +} + +func NewCapFourOctetASNumber(asnum uint32) *CapFourOctetASNumber { + return &CapFourOctetASNumber{ + DefaultParameterCapability{ + CapCode: BGP_CAP_FOUR_OCTET_AS_NUMBER, + }, + asnum, + } +} + +type BGPAddPathMode uint8 + +const ( + BGP_ADD_PATH_NONE BGPAddPathMode = iota + BGP_ADD_PATH_RECEIVE + BGP_ADD_PATH_SEND + BGP_ADD_PATH_BOTH +) + +func (m BGPAddPathMode) String() string { + switch m { + case BGP_ADD_PATH_NONE: + return "none" + case BGP_ADD_PATH_RECEIVE: + return "receive" + case BGP_ADD_PATH_SEND: + return "send" + case BGP_ADD_PATH_BOTH: + return "receive/send" + default: + return fmt.Sprintf("unknown(%d)", m) + } +} + +type CapAddPathTuple struct { + RouteFamily RouteFamily + Mode BGPAddPathMode +} + +func (t *CapAddPathTuple) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RouteFamily RouteFamily `json:"family"` + Mode uint8 `json:"mode"` + }{ + RouteFamily: t.RouteFamily, + Mode: uint8(t.Mode), + }) +} + +func NewCapAddPathTuple(family RouteFamily, mode BGPAddPathMode) *CapAddPathTuple { + return &CapAddPathTuple{ + RouteFamily: family, + Mode: mode, + } +} + +type CapAddPath struct { + DefaultParameterCapability + Tuples []*CapAddPathTuple +} + +func (c *CapAddPath) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + capLen := int(c.CapLen) + if capLen%4 != 0 || capLen < 4 || len(data) < capLen { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityAddPath bytes available") + } + + c.Tuples = []*CapAddPathTuple{} + for capLen >= 4 { + t := &CapAddPathTuple{ + RouteFamily: AfiSafiToRouteFamily(binary.BigEndian.Uint16(data[:2]), data[2]), + Mode: BGPAddPathMode(data[3]), + } + c.Tuples = append(c.Tuples, t) + data = data[4:] + capLen -= 4 + } + return nil +} + +func (c *CapAddPath) Serialize() ([]byte, error) { + buf := make([]byte, len(c.Tuples)*4) + for i, t := range c.Tuples { + afi, safi := RouteFamilyToAfiSafi(t.RouteFamily) + binary.BigEndian.PutUint16(buf[i*4:i*4+2], afi) + buf[i*4+2] = safi + buf[i*4+3] = byte(t.Mode) + } + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapAddPath) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Tuples []*CapAddPathTuple `json:"tuples"` + }{ + Code: c.Code(), + Tuples: c.Tuples, + }) +} + +func NewCapAddPath(tuples []*CapAddPathTuple) *CapAddPath { + return &CapAddPath{ + DefaultParameterCapability: DefaultParameterCapability{ + CapCode: BGP_CAP_ADD_PATH, + }, + Tuples: tuples, + } +} + +type CapEnhancedRouteRefresh struct { + DefaultParameterCapability +} + +func NewCapEnhancedRouteRefresh() *CapEnhancedRouteRefresh { + return &CapEnhancedRouteRefresh{ + DefaultParameterCapability{ + CapCode: BGP_CAP_ENHANCED_ROUTE_REFRESH, + }, + } +} + +type CapRouteRefreshCisco struct { + DefaultParameterCapability +} + +func NewCapRouteRefreshCisco() *CapRouteRefreshCisco { + return &CapRouteRefreshCisco{ + DefaultParameterCapability{ + CapCode: BGP_CAP_ROUTE_REFRESH_CISCO, + }, + } +} + +type CapLongLivedGracefulRestartTuple struct { + AFI uint16 + SAFI uint8 + Flags uint8 + RestartTime uint32 +} + +func (c *CapLongLivedGracefulRestartTuple) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RouteFamily RouteFamily `json:"route_family"` + Flags uint8 `json:"flags"` + RestartTime uint32 `json:"restart_time"` + }{ + RouteFamily: AfiSafiToRouteFamily(c.AFI, c.SAFI), + Flags: c.Flags, + RestartTime: c.RestartTime, + }) +} + +func NewCapLongLivedGracefulRestartTuple(rf RouteFamily, forward bool, restartTime uint32) *CapLongLivedGracefulRestartTuple { + afi, safi := RouteFamilyToAfiSafi(rf) + flags := 0 + if forward { + flags = 0x80 + } + return &CapLongLivedGracefulRestartTuple{ + AFI: afi, + SAFI: safi, + Flags: uint8(flags), + RestartTime: restartTime, + } +} + +type CapLongLivedGracefulRestart struct { + DefaultParameterCapability + Tuples []*CapLongLivedGracefulRestartTuple +} + +func (c *CapLongLivedGracefulRestart) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + + valueLen := int(c.CapLen) + if valueLen%7 != 0 || len(data) < valueLen { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "invalid length of long lived graceful restart capablity") + } + for i := valueLen; i >= 7; i -= 7 { + t := &CapLongLivedGracefulRestartTuple{ + binary.BigEndian.Uint16(data), + data[2], + data[3], + uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]), + } + c.Tuples = append(c.Tuples, t) + data = data[7:] + } + return nil +} + +func (c *CapLongLivedGracefulRestart) Serialize() ([]byte, error) { + buf := make([]byte, 7*len(c.Tuples)) + for idx, t := range c.Tuples { + binary.BigEndian.PutUint16(buf[idx*7:], t.AFI) + buf[idx*7+2] = t.SAFI + buf[idx*7+3] = t.Flags + buf[idx*7+4] = uint8((t.RestartTime >> 16) & 0xff) + buf[idx*7+5] = uint8((t.RestartTime >> 8) & 0xff) + buf[idx*7+6] = uint8(t.RestartTime & 0xff) + } + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapLongLivedGracefulRestart) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Code BGPCapabilityCode `json:"code"` + Tuples []*CapLongLivedGracefulRestartTuple `json:"tuples"` + }{ + Code: c.Code(), + Tuples: c.Tuples, + }) +} + +func NewCapLongLivedGracefulRestart(tuples []*CapLongLivedGracefulRestartTuple) *CapLongLivedGracefulRestart { + return &CapLongLivedGracefulRestart{ + DefaultParameterCapability: DefaultParameterCapability{ + CapCode: BGP_CAP_LONG_LIVED_GRACEFUL_RESTART, + }, + Tuples: tuples, + } +} + +type CapFQDN struct { + DefaultParameterCapability + HostNameLen uint8 + HostName string + DomainNameLen uint8 + DomainName string +} + +func (c *CapFQDN) DecodeFromBytes(data []byte) error { + c.DefaultParameterCapability.DecodeFromBytes(data) + data = data[2:] + if len(data) < 2 { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityFQDN bytes allowed") + } + hostNameLen := uint8(data[0]) + c.HostNameLen = hostNameLen + c.HostName = string(data[1 : c.HostNameLen+1]) + domainNameLen := uint8(data[c.HostNameLen+1]) + c.DomainNameLen = domainNameLen + c.DomainName = string(data[c.HostNameLen+2:]) + return nil +} + +func (c *CapFQDN) Serialize() ([]byte, error) { + buf := make([]byte, c.HostNameLen+c.DomainNameLen+2) + buf[0] = c.HostNameLen + copy(buf[1:c.HostNameLen+1], c.HostName) + buf[c.HostNameLen+1] = c.DomainNameLen + copy(buf[c.HostNameLen+2:], c.DomainName) + c.DefaultParameterCapability.CapValue = buf + return c.DefaultParameterCapability.Serialize() +} + +func (c *CapFQDN) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + HostNameLen uint8 `json:"hostname_len"` + HostName string `json:"hostname"` + DomainNameLen uint8 `json:"domainname_len"` + DomainName string `json:"domainname"` + }{ + HostNameLen: c.HostNameLen, + HostName: c.HostName, + DomainNameLen: c.DomainNameLen, + DomainName: c.DomainName, + }) +} + +func NewCapFQDN(hostname string, domainname string) *CapFQDN { + if len(hostname) > 64 { + hostname = hostname[:64] + } + if len(domainname) > 64 { + domainname = domainname[:64] + } + return &CapFQDN{ + DefaultParameterCapability{ + CapCode: BGP_CAP_FQDN, + }, + uint8(len(hostname)), + hostname, + uint8(len(domainname)), + domainname, + } +} + +type CapUnknown struct { + DefaultParameterCapability +} + +func NewCapUnknown(code BGPCapabilityCode, value []byte) *CapUnknown { + return &CapUnknown{ + DefaultParameterCapability{ + CapCode: code, + CapValue: value, + }, + } +} + +func DecodeCapability(data []byte) (ParameterCapabilityInterface, error) { + if len(data) < 2 { + return nil, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all ParameterCapability bytes available") + } + var c ParameterCapabilityInterface + switch BGPCapabilityCode(data[0]) { + case BGP_CAP_MULTIPROTOCOL: + c = &CapMultiProtocol{} + case BGP_CAP_ROUTE_REFRESH: + c = &CapRouteRefresh{} + case BGP_CAP_CARRYING_LABEL_INFO: + c = &CapCarryingLabelInfo{} + case BGP_CAP_EXTENDED_NEXTHOP: + c = &CapExtendedNexthop{} + case BGP_CAP_GRACEFUL_RESTART: + c = &CapGracefulRestart{} + case BGP_CAP_FOUR_OCTET_AS_NUMBER: + c = &CapFourOctetASNumber{} + case BGP_CAP_ADD_PATH: + c = &CapAddPath{} + case BGP_CAP_ENHANCED_ROUTE_REFRESH: + c = &CapEnhancedRouteRefresh{} + case BGP_CAP_ROUTE_REFRESH_CISCO: + c = &CapRouteRefreshCisco{} + case BGP_CAP_LONG_LIVED_GRACEFUL_RESTART: + c = &CapLongLivedGracefulRestart{} + case BGP_CAP_FQDN: + c = &CapFQDN{} + default: + c = &CapUnknown{} + } + err := c.DecodeFromBytes(data) + return c, err +} + +type OptionParameterInterface interface { + Serialize() ([]byte, error) +} + +type OptionParameterCapability struct { + ParamType uint8 + ParamLen uint8 + Capability []ParameterCapabilityInterface +} + +func (o *OptionParameterCapability) DecodeFromBytes(data []byte) error { + if uint8(len(data)) < o.ParamLen { + return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_OPTIONAL_PARAMETER, nil, "Not all OptionParameterCapability bytes available") + } + for len(data) >= 2 { + c, err := DecodeCapability(data) + if err != nil { + return err + } + o.Capability = append(o.Capability, c) + if c.Len() == 0 || len(data) < c.Len() { + return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Bad capability length") + } + data = data[c.Len():] + } + return nil +} + +func (o *OptionParameterCapability) Serialize() ([]byte, error) { + buf := make([]byte, 2) + buf[0] = o.ParamType + for _, p := range o.Capability { + pbuf, err := p.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, pbuf...) + } + o.ParamLen = uint8(len(buf) - 2) + buf[1] = o.ParamLen + return buf, nil +} + +func NewOptionParameterCapability(capability []ParameterCapabilityInterface) *OptionParameterCapability { + return &OptionParameterCapability{ + ParamType: BGP_OPT_CAPABILITY, + Capability: capability, + } +} + +type OptionParameterUnknown struct { + ParamType uint8 + ParamLen uint8 + Value []byte +} + +func (o *OptionParameterUnknown) Serialize() ([]byte, error) { + buf := make([]byte, 2+len(o.Value)) + buf[0] = o.ParamType + if o.ParamLen == 0 { + o.ParamLen = uint8(len(o.Value)) + } + buf[1] = o.ParamLen + copy(buf[2:], o.Value) + return buf, nil +} + +type BGPOpen struct { + Version uint8 + MyAS uint16 + HoldTime uint16 + ID net.IP + OptParamLen uint8 + OptParams []OptionParameterInterface +} + +func (msg *BGPOpen) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if len(data) < 10 { + return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Not all BGP Open message bytes available") + } + msg.Version = data[0] + msg.MyAS = binary.BigEndian.Uint16(data[1:3]) + msg.HoldTime = binary.BigEndian.Uint16(data[3:5]) + msg.ID = net.IP(data[5:9]).To4() + msg.OptParamLen = data[9] + data = data[10:] + if len(data) < int(msg.OptParamLen) { + return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Not all BGP Open message bytes available") + } + + msg.OptParams = []OptionParameterInterface{} + for rest := msg.OptParamLen; rest > 0; { + if rest < 2 { + return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Malformed BGP Open message") + } + paramtype := data[0] + paramlen := data[1] + if paramlen >= 254 || rest < paramlen+2 { + return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Malformed BGP Open message") + } + rest -= paramlen + 2 + + if paramtype == BGP_OPT_CAPABILITY { + p := &OptionParameterCapability{} + p.ParamType = paramtype + p.ParamLen = paramlen + p.DecodeFromBytes(data[2 : 2+paramlen]) + msg.OptParams = append(msg.OptParams, p) + } else { + p := &OptionParameterUnknown{} + p.ParamType = paramtype + p.ParamLen = paramlen + p.Value = data[2 : 2+paramlen] + msg.OptParams = append(msg.OptParams, p) + } + data = data[2+paramlen:] + } + return nil +} + +func (msg *BGPOpen) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 10) + buf[0] = msg.Version + binary.BigEndian.PutUint16(buf[1:3], msg.MyAS) + binary.BigEndian.PutUint16(buf[3:5], msg.HoldTime) + copy(buf[5:9], msg.ID.To4()) + pbuf := make([]byte, 0) + for _, p := range msg.OptParams { + onepbuf, err := p.Serialize() + if err != nil { + return nil, err + } + pbuf = append(pbuf, onepbuf...) + } + msg.OptParamLen = uint8(len(pbuf)) + buf[9] = msg.OptParamLen + return append(buf, pbuf...), nil +} + +func NewBGPOpenMessage(myas uint16, holdtime uint16, id string, optparams []OptionParameterInterface) *BGPMessage { + return &BGPMessage{ + Header: BGPHeader{Type: BGP_MSG_OPEN}, + Body: &BGPOpen{4, myas, holdtime, net.ParseIP(id).To4(), 0, optparams}, + } +} + +type AddrPrefixInterface interface { + DecodeFromBytes([]byte, ...*MarshallingOption) error + Serialize(...*MarshallingOption) ([]byte, error) + AFI() uint16 + SAFI() uint8 + Len(...*MarshallingOption) int + String() string + MarshalJSON() ([]byte, error) + // Create a flat map to describe attributes and their + // values. This can be used to create structured outputs. + Flat() map[string]string + PathIdentifier() uint32 + SetPathIdentifier(uint32) + PathLocalIdentifier() uint32 + SetPathLocalIdentifier(uint32) +} + +func LabelString(nlri AddrPrefixInterface) string { + label := "" + switch n := nlri.(type) { + case *LabeledIPAddrPrefix: + label = n.Labels.String() + case *LabeledIPv6AddrPrefix: + label = n.Labels.String() + case *LabeledVPNIPAddrPrefix: + label = n.Labels.String() + case *LabeledVPNIPv6AddrPrefix: + label = n.Labels.String() + case *EVPNNLRI: + switch route := n.RouteTypeData.(type) { + case *EVPNEthernetAutoDiscoveryRoute: + label = fmt.Sprintf("[%d]", route.Label) + case *EVPNMacIPAdvertisementRoute: + ls := make([]string, len(route.Labels)) + for i, l := range route.Labels { + ls[i] = strconv.Itoa(int(l)) + } + label = fmt.Sprintf("[%s]", strings.Join(ls, ",")) + case *EVPNIPPrefixRoute: + label = fmt.Sprintf("[%d]", route.Label) + } + } + return label +} + +type PrefixDefault struct { + mu sync.Mutex + id uint32 + localId uint32 +} + +func (p *PrefixDefault) PathIdentifier() uint32 { + p.mu.Lock() + defer p.mu.Unlock() + + return p.id +} + +func (p *PrefixDefault) SetPathIdentifier(id uint32) { + p.mu.Lock() + defer p.mu.Unlock() + + p.id = id +} + +func (p *PrefixDefault) PathLocalIdentifier() uint32 { + p.mu.Lock() + defer p.mu.Unlock() + + return p.localId +} + +func (p *PrefixDefault) SetPathLocalIdentifier(id uint32) { + p.mu.Lock() + defer p.mu.Unlock() + + p.localId = id +} + +func (p *PrefixDefault) decodePathIdentifier(data []byte) ([]byte, error) { + if len(data) < 4 { + code := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + subcode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return nil, NewMessageError(code, subcode, nil, "prefix misses path identifier field") + } + p.SetPathIdentifier(binary.BigEndian.Uint32(data[:4])) + return data[4:], nil +} + +func (p *PrefixDefault) serializeIdentifier() ([]byte, error) { + buf := make([]byte, 4) + binary.BigEndian.PutUint32(buf, p.PathLocalIdentifier()) + return buf, nil +} + +type IPAddrPrefixDefault struct { + PrefixDefault + Length uint8 + Prefix net.IP +} + +func (r *IPAddrPrefixDefault) decodePrefix(data []byte, bitlen uint8, addrlen uint8) error { + bytelen := (int(bitlen) + 7) / 8 + if len(data) < bytelen { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "network bytes is short") + } + if bitlen > addrlen*8 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "network bit length is too long") + } + b := make([]byte, addrlen) + copy(b, data[:bytelen]) + // clear trailing bits in the last byte. rfc doesn't require + // this but some bgp implementations need this... + rem := bitlen % 8 + if rem != 0 { + mask := 0xff00 >> rem + lastByte := b[bytelen-1] & byte(mask) + b[bytelen-1] = lastByte + } + r.Prefix = b + return nil +} + +func (r *IPAddrPrefixDefault) serializePrefix(bitLen uint8) ([]byte, error) { + byteLen := (int(bitLen) + 7) / 8 + buf := make([]byte, byteLen) + copy(buf, r.Prefix) + return buf, nil +} + +func (r *IPAddrPrefixDefault) String() string { + return fmt.Sprintf("%s/%d", r.Prefix.String(), r.Length) +} + +func (r *IPAddrPrefixDefault) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Prefix string `json:"prefix"` + }{ + Prefix: r.String(), + }) +} + +type IPAddrPrefix struct { + IPAddrPrefixDefault + addrlen uint8 +} + +func (r *IPAddrPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if r.addrlen == 0 { + r.addrlen = 4 + } + f := RF_IPv4_UC + if r.addrlen == 16 { + f = RF_IPv6_UC + } + if IsAddPathEnabled(true, f, options) { + var err error + data, err = r.decodePathIdentifier(data) + if err != nil { + return err + } + } + if len(data) < 1 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "prefix misses length field") + } + r.Length = data[0] + return r.decodePrefix(data[1:], r.Length, r.addrlen) +} + +func (r *IPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + f := RF_IPv4_UC + if r.addrlen == 16 { + f = RF_IPv6_UC + } + var buf []byte + if IsAddPathEnabled(false, f, options) { + var err error + buf, err = r.serializeIdentifier() + if err != nil { + return nil, err + } + } + buf = append(buf, r.Length) + pbuf, err := r.serializePrefix(r.Length) + if err != nil { + return nil, err + } + return append(buf, pbuf...), nil +} + +func (r *IPAddrPrefix) AFI() uint16 { + return AFI_IP +} + +func (r *IPAddrPrefix) SAFI() uint8 { + return SAFI_UNICAST +} + +func (r *IPAddrPrefix) Len(options ...*MarshallingOption) int { + return 1 + ((int(r.Length) + 7) / 8) +} + +func NewIPAddrPrefix(length uint8, prefix string) *IPAddrPrefix { + p := &IPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length, + }, + 4, + } + p.IPAddrPrefixDefault.decodePrefix(net.ParseIP(prefix).To4(), length, 4) + return p +} + +func isIPv4MappedIPv6(ip net.IP) bool { + return len(ip) == net.IPv6len && ip.To4() != nil +} + +type IPv6AddrPrefix struct { + IPAddrPrefix +} + +func (r *IPv6AddrPrefix) AFI() uint16 { + return AFI_IP6 +} + +func (r *IPv6AddrPrefix) String() string { + prefix := r.Prefix.String() + if isIPv4MappedIPv6(r.Prefix) { + prefix = "::ffff:" + prefix + } + return fmt.Sprintf("%s/%d", prefix, r.Length) +} + +func NewIPv6AddrPrefix(length uint8, prefix string) *IPv6AddrPrefix { + p := &IPv6AddrPrefix{ + IPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length, + }, + 16, + }, + } + p.IPAddrPrefixDefault.decodePrefix(net.ParseIP(prefix), length, 16) + return p +} + +const ( + BGP_RD_TWO_OCTET_AS = iota + BGP_RD_IPV4_ADDRESS + BGP_RD_FOUR_OCTET_AS +) + +type RouteDistinguisherInterface interface { + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + Len() int + String() string + MarshalJSON() ([]byte, error) +} + +type DefaultRouteDistinguisher struct { + Type uint16 +} + +func (rd *DefaultRouteDistinguisher) serialize(value []byte) ([]byte, error) { + buf := make([]byte, 8) + binary.BigEndian.PutUint16(buf, rd.Type) + copy(buf[2:], value) + return buf, nil +} + +func (rd *DefaultRouteDistinguisher) Len() int { + return 8 +} + +type RouteDistinguisherTwoOctetAS struct { + DefaultRouteDistinguisher + Admin uint16 + Assigned uint32 +} + +func (rd *RouteDistinguisherTwoOctetAS) DecodeFromBytes(data []byte) error { + rd.Admin = binary.BigEndian.Uint16(data[0:2]) + rd.Assigned = binary.BigEndian.Uint32(data[2:6]) + return nil +} + +func (rd *RouteDistinguisherTwoOctetAS) Serialize() ([]byte, error) { + buf := make([]byte, 6) + binary.BigEndian.PutUint16(buf[0:2], rd.Admin) + binary.BigEndian.PutUint32(buf[2:6], rd.Assigned) + return rd.serialize(buf) +} + +func (rd *RouteDistinguisherTwoOctetAS) String() string { + return fmt.Sprintf("%d:%d", rd.Admin, rd.Assigned) +} + +func (rd *RouteDistinguisherTwoOctetAS) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint16 `json:"type"` + Admin uint16 `json:"admin"` + Assigned uint32 `json:"assigned"` + }{ + Type: rd.Type, + Admin: rd.Admin, + Assigned: rd.Assigned, + }) +} + +func NewRouteDistinguisherTwoOctetAS(admin uint16, assigned uint32) *RouteDistinguisherTwoOctetAS { + return &RouteDistinguisherTwoOctetAS{ + DefaultRouteDistinguisher: DefaultRouteDistinguisher{ + Type: BGP_RD_TWO_OCTET_AS, + }, + Admin: admin, + Assigned: assigned, + } +} + +type RouteDistinguisherIPAddressAS struct { + DefaultRouteDistinguisher + Admin net.IP + Assigned uint16 +} + +func (rd *RouteDistinguisherIPAddressAS) DecodeFromBytes(data []byte) error { + rd.Admin = data[0:4] + rd.Assigned = binary.BigEndian.Uint16(data[4:6]) + return nil +} + +func (rd *RouteDistinguisherIPAddressAS) Serialize() ([]byte, error) { + buf := make([]byte, 6) + copy(buf[0:4], rd.Admin.To4()) + binary.BigEndian.PutUint16(buf[4:6], rd.Assigned) + return rd.serialize(buf) +} + +func (rd *RouteDistinguisherIPAddressAS) String() string { + return fmt.Sprintf("%s:%d", rd.Admin.String(), rd.Assigned) +} + +func (rd *RouteDistinguisherIPAddressAS) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint16 `json:"type"` + Admin string `json:"admin"` + Assigned uint16 `json:"assigned"` + }{ + Type: rd.Type, + Admin: rd.Admin.String(), + Assigned: rd.Assigned, + }) +} + +func NewRouteDistinguisherIPAddressAS(admin string, assigned uint16) *RouteDistinguisherIPAddressAS { + return &RouteDistinguisherIPAddressAS{ + DefaultRouteDistinguisher: DefaultRouteDistinguisher{ + Type: BGP_RD_IPV4_ADDRESS, + }, + Admin: net.ParseIP(admin).To4(), + Assigned: assigned, + } +} + +type RouteDistinguisherFourOctetAS struct { + DefaultRouteDistinguisher + Admin uint32 + Assigned uint16 +} + +func (rd *RouteDistinguisherFourOctetAS) DecodeFromBytes(data []byte) error { + rd.Admin = binary.BigEndian.Uint32(data[0:4]) + rd.Assigned = binary.BigEndian.Uint16(data[4:6]) + return nil +} + +func (rd *RouteDistinguisherFourOctetAS) Serialize() ([]byte, error) { + buf := make([]byte, 6) + binary.BigEndian.PutUint32(buf[0:4], rd.Admin) + binary.BigEndian.PutUint16(buf[4:6], rd.Assigned) + return rd.serialize(buf) +} + +func (rd *RouteDistinguisherFourOctetAS) String() string { + fst := rd.Admin >> 16 & 0xffff + snd := rd.Admin & 0xffff + return fmt.Sprintf("%d.%d:%d", fst, snd, rd.Assigned) +} + +func (rd *RouteDistinguisherFourOctetAS) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint16 `json:"type"` + Admin uint32 `json:"admin"` + Assigned uint16 `json:"assigned"` + }{ + Type: rd.Type, + Admin: rd.Admin, + Assigned: rd.Assigned, + }) +} + +func NewRouteDistinguisherFourOctetAS(admin uint32, assigned uint16) *RouteDistinguisherFourOctetAS { + return &RouteDistinguisherFourOctetAS{ + DefaultRouteDistinguisher: DefaultRouteDistinguisher{ + Type: BGP_RD_FOUR_OCTET_AS, + }, + Admin: admin, + Assigned: assigned, + } +} + +type RouteDistinguisherUnknown struct { + DefaultRouteDistinguisher + Value []byte +} + +func (rd *RouteDistinguisherUnknown) DecodeFromBytes(data []byte) error { + rd.Value = data[0:6] + return nil +} + +func (rd *RouteDistinguisherUnknown) Serialize() ([]byte, error) { + return rd.DefaultRouteDistinguisher.serialize(rd.Value) +} + +func (rd *RouteDistinguisherUnknown) String() string { + return fmt.Sprintf("%v", rd.Value) +} + +func (rd *RouteDistinguisherUnknown) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint16 `json:"type"` + Value []byte `json:"value"` + }{ + Type: rd.Type, + Value: rd.Value, + }) +} + +func GetRouteDistinguisher(data []byte) RouteDistinguisherInterface { + typ := binary.BigEndian.Uint16(data[0:2]) + switch typ { + case BGP_RD_TWO_OCTET_AS: + return NewRouteDistinguisherTwoOctetAS(binary.BigEndian.Uint16(data[2:4]), binary.BigEndian.Uint32(data[4:8])) + case BGP_RD_IPV4_ADDRESS: + return NewRouteDistinguisherIPAddressAS(net.IP(data[2:6]).String(), binary.BigEndian.Uint16(data[6:8])) + case BGP_RD_FOUR_OCTET_AS: + return NewRouteDistinguisherFourOctetAS(binary.BigEndian.Uint32(data[2:6]), binary.BigEndian.Uint16(data[6:8])) + } + rd := &RouteDistinguisherUnknown{ + DefaultRouteDistinguisher: DefaultRouteDistinguisher{ + Type: typ, + }, + } + return rd +} + +func parseRdAndRt(input string) ([]string, error) { + elems := _regexpRouteDistinguisher.FindStringSubmatch(input) + if len(elems) != 11 { + return nil, errors.New("failed to parse") + } + return elems, nil +} + +func ParseRouteDistinguisher(rd string) (RouteDistinguisherInterface, error) { + elems, err := parseRdAndRt(rd) + if err != nil { + return nil, err + } + assigned, _ := strconv.ParseUint(elems[10], 10, 32) + ip := net.ParseIP(elems[1]) + switch { + case ip.To4() != nil: + return NewRouteDistinguisherIPAddressAS(elems[1], uint16(assigned)), nil + case elems[6] == "" && elems[7] == "": + asn, _ := strconv.ParseUint(elems[8], 10, 16) + return NewRouteDistinguisherTwoOctetAS(uint16(asn), uint32(assigned)), nil + default: + fst, _ := strconv.ParseUint(elems[7], 10, 16) + snd, _ := strconv.ParseUint(elems[8], 10, 16) + asn := fst<<16 | snd + return NewRouteDistinguisherFourOctetAS(uint32(asn), uint16(assigned)), nil + } +} + +// +// RFC3107 Carrying Label Information in BGP-4 +// +// 3. Carrying Label Mapping Information +// +// b) Label: +// +// The Label field carries one or more labels (that corresponds to +// the stack of labels [MPLS-ENCAPS(RFC3032)]). Each label is encoded as +// 4 octets, where the high-order 20 bits contain the label value, and +// the low order bit contains "Bottom of Stack" +// +// RFC3032 MPLS Label Stack Encoding +// +// 2.1. Encoding the Label Stack +// +// 0 1 2 3 +// 0 ... 9 0 ... 9 0 1 2 3 4 ... 9 0 1 +// +-----+-+-+---+-+-+-+-+-+-----+-+-+-+ +// | Label | Exp |S| TTL | +// +-----+-+-+---+-+-+-+-+-+-----+-+-+-+ +// + +// RFC3107 Carrying Label Information in BGP-4 +// +// 3. Carrying Label Mapping Information +// +// The label information carried (as part of NLRI) in the Withdrawn +// Routes field should be set to 0x800000. +const WITHDRAW_LABEL = uint32(0x800000) +const ZERO_LABEL = uint32(0) // some platform uses this as withdraw label + +type MPLSLabelStack struct { + Labels []uint32 +} + +func (l *MPLSLabelStack) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + labels := []uint32{} + foundBottom := false + bottomExpected := true + if IsAttributePresent(BGP_ATTR_TYPE_PREFIX_SID, options) { + // If Update carries Prefix SID attribute then one should not rely on BoS for the label stack processing, + // the first and only label carries transposed variable part of the SRv6 SID. + bottomExpected = false + } + for len(data) >= 3 { + label := uint32(data[0])<<16 | uint32(data[1])<<8 | uint32(data[2]) + if label == WITHDRAW_LABEL || label == ZERO_LABEL { + l.Labels = []uint32{label} + return nil + } + data = data[3:] + labels = append(labels, label>>4) + if !bottomExpected { + // Faking found bottom. + foundBottom = true + break + } + if label&1 == 1 { + foundBottom = true + break + } + } + + if !foundBottom { + l.Labels = []uint32{} + return nil + } + l.Labels = labels + return nil +} + +func (l *MPLSLabelStack) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, len(l.Labels)*3) + for i, label := range l.Labels { + if label == WITHDRAW_LABEL { + return []byte{128, 0, 0}, nil + } + label = label << 4 + buf[i*3] = byte((label >> 16) & 0xff) + buf[i*3+1] = byte((label >> 8) & 0xff) + buf[i*3+2] = byte(label & 0xff) + } + buf[len(buf)-1] |= 1 + return buf, nil +} + +func (l *MPLSLabelStack) Len() int { return 3 * len(l.Labels) } + +func (l *MPLSLabelStack) String() string { + if len(l.Labels) == 0 { + return "" + } + s := bytes.NewBuffer(make([]byte, 0, 64)) + s.WriteString("[") + ss := make([]string, 0, len(l.Labels)) + for _, label := range l.Labels { + ss = append(ss, fmt.Sprintf("%d", label)) + } + s.WriteString(strings.Join(ss, ", ")) + s.WriteString("]") + return s.String() +} + +func NewMPLSLabelStack(labels ...uint32) *MPLSLabelStack { + if len(labels) == 0 { + labels = []uint32{0} + } + return &MPLSLabelStack{labels} +} + +func ParseMPLSLabelStack(buf string) (*MPLSLabelStack, error) { + elems := strings.Split(buf, "/") + labels := make([]uint32, 0, len(elems)) + if len(elems) == 0 { + goto ERR + } + for _, elem := range elems { + i, err := strconv.ParseUint(elem, 10, 32) + if err != nil { + goto ERR + } + if i > ((1 << 20) - 1) { + goto ERR + } + labels = append(labels, uint32(i)) + } + return NewMPLSLabelStack(labels...), nil +ERR: + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid mpls label stack format") +} + +// +// RFC3107 Carrying Label Information in BGP-4 +// +// 3. Carrying Label Mapping Information +// +// +----------------------+ +// | Length (1 octet) | +// +----------------------+ +// | Label (3 octets) | +// +----------------------+ +// ....................... +// +----------------------+ +// | Prefix (variable) | +// +----------------------+ +// +// RFC4364 BGP/MPLS IP VPNs +// +// 4.3.4. How VPN-IPv4 NLRI Is Carried in BGP +// +// The labeled VPN-IPv4 NLRI itself is encoded as specified in +// [MPLS-BGP(RFC3107)], where the prefix consists of an 8-byte RD +// followed by an IPv4 prefix. +// + +type LabeledVPNIPAddrPrefix struct { + IPAddrPrefixDefault + Labels MPLSLabelStack + RD RouteDistinguisherInterface + addrlen uint8 +} + +func (l *LabeledVPNIPAddrPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + f := RF_IPv4_VPN + if l.addrlen == 16 { + f = RF_IPv6_VPN + } + if IsAddPathEnabled(true, f, options) { + var err error + data, err = l.decodePathIdentifier(data) + if err != nil { + return err + } + } + if len(data) < 1 { + return NewMessageError(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST), nil, "prefix misses length field") + } + l.Length = uint8(data[0]) + data = data[1:] + l.Labels.DecodeFromBytes(data, options...) + if int(l.Length)-8*(l.Labels.Len()) < 0 { + l.Labels.Labels = []uint32{} + } + data = data[l.Labels.Len():] + l.RD = GetRouteDistinguisher(data) + rdLen := l.RD.Len() + if len(data) < rdLen { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "bad labeled VPN-IPv4 NLRI length") + } + data = data[l.RD.Len():] + restbits := int(l.Length) - 8*(l.Labels.Len()+l.RD.Len()) + return l.decodePrefix(data, uint8(restbits), l.addrlen) +} + +func (l *LabeledVPNIPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + f := RF_IPv4_VPN + if l.addrlen == 16 { + f = RF_IPv6_VPN + } + var buf []byte + if IsAddPathEnabled(false, f, options) { + var err error + buf, err = l.serializeIdentifier() + if err != nil { + return nil, err + } + } + buf = append(buf, l.Length) + lbuf, err := l.Labels.Serialize(options...) + if err != nil { + return nil, err + } + buf = append(buf, lbuf...) + rbuf, err := l.RD.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, rbuf...) + restbits := int(l.Length) - 8*(l.Labels.Len()+l.RD.Len()) + pbuf, err := l.serializePrefix(uint8(restbits)) + if err != nil { + return nil, err + } + buf = append(buf, pbuf...) + return buf, nil +} + +func (l *LabeledVPNIPAddrPrefix) AFI() uint16 { + return AFI_IP +} + +func (l *LabeledVPNIPAddrPrefix) SAFI() uint8 { + return SAFI_MPLS_VPN +} + +func (l *LabeledVPNIPAddrPrefix) IPPrefixLen() uint8 { + return l.Length - 8*uint8(l.Labels.Len()+l.RD.Len()) +} + +func (l *LabeledVPNIPAddrPrefix) Len(options ...*MarshallingOption) int { + return 1 + l.Labels.Len() + l.RD.Len() + int((l.IPPrefixLen()+7)/8) +} + +func (l *LabeledVPNIPAddrPrefix) String() string { + return fmt.Sprintf("%s:%s", l.RD, l.IPPrefix()) +} + +func (l *LabeledVPNIPAddrPrefix) IPPrefix() string { + masklen := l.IPAddrPrefixDefault.Length - uint8(8*(l.Labels.Len()+l.RD.Len())) + return fmt.Sprintf("%s/%d", l.IPAddrPrefixDefault.Prefix, masklen) +} + +func (l *LabeledVPNIPAddrPrefix) MarshalJSON() ([]byte, error) { + masklen := l.IPAddrPrefixDefault.Length - uint8(8*(l.Labels.Len()+l.RD.Len())) + return json.Marshal(struct { + Prefix string `json:"prefix"` + Labels []uint32 `json:"labels"` + RD RouteDistinguisherInterface `json:"rd"` + }{ + Prefix: fmt.Sprintf("%s/%d", l.IPAddrPrefixDefault.Prefix, masklen), + Labels: l.Labels.Labels, + RD: l.RD, + }) +} + +func NewLabeledVPNIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabeledVPNIPAddrPrefix { + rdlen := 0 + if rd != nil { + rdlen = rd.Len() + } + return &LabeledVPNIPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length + uint8(8*(label.Len()+rdlen)), + Prefix: net.ParseIP(prefix).To4(), + }, + label, + rd, + 4, + } +} + +type LabeledVPNIPv6AddrPrefix struct { + LabeledVPNIPAddrPrefix +} + +func (l *LabeledVPNIPv6AddrPrefix) AFI() uint16 { + return AFI_IP6 +} + +func NewLabeledVPNIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabeledVPNIPv6AddrPrefix { + rdlen := 0 + if rd != nil { + rdlen = rd.Len() + } + return &LabeledVPNIPv6AddrPrefix{ + LabeledVPNIPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length + uint8(8*(label.Len()+rdlen)), + Prefix: net.ParseIP(prefix), + }, + label, + rd, + 16, + }, + } +} + +type LabeledIPAddrPrefix struct { + IPAddrPrefixDefault + Labels MPLSLabelStack + addrlen uint8 +} + +func (r *LabeledIPAddrPrefix) AFI() uint16 { + return AFI_IP +} + +func (r *LabeledIPAddrPrefix) SAFI() uint8 { + return SAFI_MPLS_LABEL +} + +func (l *LabeledIPAddrPrefix) IPPrefixLen() uint8 { + return l.Length - 8*uint8(l.Labels.Len()) +} + +func (l *LabeledIPAddrPrefix) Len(options ...*MarshallingOption) int { + return 1 + l.Labels.Len() + int((l.IPPrefixLen()+7)/8) +} + +func (l *LabeledIPAddrPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + f := RF_IPv4_MPLS + if l.addrlen == 16 { + f = RF_IPv6_MPLS + } + if IsAddPathEnabled(true, f, options) { + var err error + data, err = l.decodePathIdentifier(data) + if err != nil { + return err + } + } + l.Length = uint8(data[0]) + data = data[1:] + l.Labels.DecodeFromBytes(data) + + if int(l.Length)-8*(l.Labels.Len()) < 0 { + l.Labels.Labels = []uint32{} + } + restbits := int(l.Length) - 8*(l.Labels.Len()) + data = data[l.Labels.Len():] + return l.decodePrefix(data, uint8(restbits), l.addrlen) +} + +func (l *LabeledIPAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + f := RF_IPv4_MPLS + if l.addrlen == 16 { + f = RF_IPv6_MPLS + } + var buf []byte + if IsAddPathEnabled(false, f, options) { + var err error + buf, err = l.serializeIdentifier() + if err != nil { + return nil, err + } + } + buf = append(buf, l.Length) + restbits := int(l.Length) - 8*(l.Labels.Len()) + lbuf, err := l.Labels.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, lbuf...) + pbuf, err := l.serializePrefix(uint8(restbits)) + if err != nil { + return nil, err + } + buf = append(buf, pbuf...) + return buf, nil +} + +func (l *LabeledIPAddrPrefix) String() string { + prefix := l.Prefix.String() + if isIPv4MappedIPv6(l.Prefix) { + prefix = "::ffff:" + prefix + } + return fmt.Sprintf("%s/%d", prefix, int(l.Length)-l.Labels.Len()*8) +} + +func (l *LabeledIPAddrPrefix) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Prefix string `json:"prefix"` + Labels []uint32 `json:"labels"` + }{ + Prefix: l.String(), + Labels: l.Labels.Labels, + }) +} + +func NewLabeledIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPAddrPrefix { + return &LabeledIPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length + uint8(label.Len()*8), + Prefix: net.ParseIP(prefix).To4(), + }, + label, + 4, + } +} + +type LabeledIPv6AddrPrefix struct { + LabeledIPAddrPrefix +} + +func (l *LabeledIPv6AddrPrefix) AFI() uint16 { + return AFI_IP6 +} + +func NewLabeledIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPv6AddrPrefix { + return &LabeledIPv6AddrPrefix{ + LabeledIPAddrPrefix{ + IPAddrPrefixDefault{ + Length: length + uint8(label.Len()*8), + Prefix: net.ParseIP(prefix), + }, + label, + 16, + }, + } +} + +type RouteTargetMembershipNLRI struct { + PrefixDefault + Length uint8 + AS uint32 + RouteTarget ExtendedCommunityInterface +} + +func (n *RouteTargetMembershipNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if IsAddPathEnabled(true, RF_RTC_UC, options) { + var err error + data, err = n.decodePathIdentifier(data) + if err != nil { + return err + } + } + if len(data) < 1 { + return NewMessageError(uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR), uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST), nil, "prefix misses length field") + } + n.Length = data[0] + data = data[1 : n.Length/8+1] + if len(data) == 0 { + return nil + } else if len(data) != 12 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all RouteTargetMembershipNLRI bytes available") + } + n.AS = binary.BigEndian.Uint32(data[0:4]) + rt, err := ParseExtended(data[4:]) + n.RouteTarget = rt + if err != nil { + return err + } + return nil +} + +func (n *RouteTargetMembershipNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf []byte + if IsAddPathEnabled(false, RF_RTC_UC, options) { + var err error + buf, err = n.serializeIdentifier() + if err != nil { + return nil, err + } + } + if n.RouteTarget == nil { + return append(buf, 0), nil + } + offset := len(buf) + buf = append(buf, make([]byte, 5)...) + buf[offset] = 96 + binary.BigEndian.PutUint32(buf[offset+1:], n.AS) + ebuf, err := n.RouteTarget.Serialize() + if err != nil { + return nil, err + } + return append(buf, ebuf...), nil +} + +func (n *RouteTargetMembershipNLRI) AFI() uint16 { + return AFI_IP +} + +func (n *RouteTargetMembershipNLRI) SAFI() uint8 { + return SAFI_ROUTE_TARGET_CONSTRAINTS +} + +func (n *RouteTargetMembershipNLRI) Len(options ...*MarshallingOption) int { + if n.AS == 0 && n.RouteTarget == nil { + return 1 + } + return 13 +} + +func (n *RouteTargetMembershipNLRI) String() string { + target := "default" + if n.RouteTarget != nil { + target = n.RouteTarget.String() + } + return fmt.Sprintf("%d:%s", n.AS, target) +} + +func (n *RouteTargetMembershipNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Prefix string `json:"prefix"` + }{ + Prefix: n.String(), + }) +} + +func NewRouteTargetMembershipNLRI(as uint32, target ExtendedCommunityInterface) *RouteTargetMembershipNLRI { + l := 12 * 8 + if as == 0 && target == nil { + l = 1 + } + return &RouteTargetMembershipNLRI{ + Length: uint8(l), + AS: as, + RouteTarget: target, + } +} + +//go:generate stringer -type=ESIType +type ESIType uint8 + +const ( + ESI_ARBITRARY ESIType = iota + ESI_LACP + ESI_MSTP + ESI_MAC + ESI_ROUTERID + ESI_AS +) + +type EthernetSegmentIdentifier struct { + Type ESIType + Value []byte +} + +func (esi *EthernetSegmentIdentifier) DecodeFromBytes(data []byte) error { + if len(data) < 10 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("invalid %s length", esi.Type.String())) + } + esi.Type = ESIType(data[0]) + esi.Value = data[1:10] + switch esi.Type { + case ESI_LACP, ESI_MSTP, ESI_ROUTERID, ESI_AS: + if esi.Value[8] != 0x00 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("invalid %s. last octet must be 0x00 (0x%02x)", esi.Type.String(), esi.Value[8])) + } + } + return nil +} + +func (esi *EthernetSegmentIdentifier) Serialize() ([]byte, error) { + buf := make([]byte, 10) + buf[0] = uint8(esi.Type) + copy(buf[1:], esi.Value) + return buf, nil +} + +func isZeroBuf(buf []byte) bool { + for _, b := range buf { + if b != 0 { + return false + } + } + return true +} + +func (esi *EthernetSegmentIdentifier) String() string { + toHexArray := func(data []byte) string { + // Converts byte slice into the colon separated hex values and the + // number of elements are 9 at most (excluding Type field). + values := make([]string, 0, 9) + for _, v := range data { + values = append(values, fmt.Sprintf("%02x", v)) + } + return strings.Join(values, ":") + } + + s := bytes.NewBuffer(make([]byte, 0, 64)) + s.WriteString(fmt.Sprintf("%s | ", esi.Type.String())) + switch esi.Type { + case ESI_LACP: + s.WriteString(fmt.Sprintf("system mac %s, ", net.HardwareAddr(esi.Value[:6]).String())) + s.WriteString(fmt.Sprintf("port key %d", binary.BigEndian.Uint16(esi.Value[6:8]))) + case ESI_MSTP: + s.WriteString(fmt.Sprintf("bridge mac %s, ", net.HardwareAddr(esi.Value[:6]).String())) + s.WriteString(fmt.Sprintf("priority %d", binary.BigEndian.Uint16(esi.Value[6:8]))) + case ESI_MAC: + s.WriteString(fmt.Sprintf("system mac %s, ", net.HardwareAddr(esi.Value[:6]).String())) + s.WriteString(fmt.Sprintf("local discriminator %d", uint32(esi.Value[6])<<16|uint32(esi.Value[7])<<8|uint32(esi.Value[8]))) + case ESI_ROUTERID: + s.WriteString(fmt.Sprintf("router id %s, ", net.IP(esi.Value[:4]))) + s.WriteString(fmt.Sprintf("local discriminator %d", binary.BigEndian.Uint32(esi.Value[4:8]))) + case ESI_AS: + s.WriteString(fmt.Sprintf("as %d, ", binary.BigEndian.Uint32(esi.Value[:4]))) + s.WriteString(fmt.Sprintf("local discriminator %d", binary.BigEndian.Uint32(esi.Value[4:8]))) + case ESI_ARBITRARY: + if isZeroBuf(esi.Value) { + return "single-homed" + } + fallthrough + default: + s.WriteString(toHexArray(esi.Value)) + } + return s.String() +} + +// Decode Ethernet Segment Identifier (ESI) from string slice. +// +// The first element of args should be the Type field (e.g., "ARBITRARY", +// "arbitrary", "ESI_ARBITRARY" or "esi_arbitrary") and "single-homed" is +// the special keyword for all zeroed ESI. +// For the "ARBITRARY" Value field (Type 0), it should be the colon separated +// hex values and the number of elements should be 9 at most. +// +// e.g.) args := []string{"ARBITRARY", "11:22:33:44:55:66:77:88:99"} +// +// For the other types, the Value field format is the similar to the string +// format of ESI. +// +// e.g.) args := []string{"lacp", "aa:bb:cc:dd:ee:ff", "100"} +func ParseEthernetSegmentIdentifier(args []string) (EthernetSegmentIdentifier, error) { + esi := EthernetSegmentIdentifier{} + argLen := len(args) + if argLen == 0 || args[0] == "single-homed" { + return esi, nil + } + + typeStr := strings.TrimPrefix(strings.ToUpper(args[0]), "ESI_") + switch typeStr { + case "ARBITRARY": + esi.Type = ESI_ARBITRARY + case "LACP": + esi.Type = ESI_LACP + case "MSTP": + esi.Type = ESI_MSTP + case "MAC": + esi.Type = ESI_MAC + case "ROUTERID": + esi.Type = ESI_ROUTERID + case "AS": + esi.Type = ESI_AS + default: + typ, err := strconv.ParseUint(args[0], 10, 8) + if err != nil { + return esi, fmt.Errorf("invalid esi type: %s", args[0]) + } + esi.Type = ESIType(typ) + } + + invalidEsiValuesError := fmt.Errorf("invalid esi values for type %s: %s", esi.Type.String(), args[1:]) + esi.Value = make([]byte, 9) + switch esi.Type { + case ESI_LACP: + fallthrough + case ESI_MSTP: + if argLen < 3 { + return esi, invalidEsiValuesError + } + // MAC + mac, err := net.ParseMAC(args[1]) + if err != nil { + return esi, invalidEsiValuesError + } + copy(esi.Value[0:6], mac) + // Port Key or Bridge Priority + i, err := strconv.ParseUint(args[2], 10, 16) + if err != nil { + return esi, invalidEsiValuesError + } + binary.BigEndian.PutUint16(esi.Value[6:8], uint16(i)) + case ESI_MAC: + if argLen < 3 { + return esi, invalidEsiValuesError + } + // MAC + mac, err := net.ParseMAC(args[1]) + if err != nil { + return esi, invalidEsiValuesError + } + copy(esi.Value[0:6], mac) + // Local Discriminator + i, err := strconv.ParseUint(args[2], 10, 32) + if err != nil { + return esi, invalidEsiValuesError + } + iBuf := make([]byte, 4) + binary.BigEndian.PutUint32(iBuf, uint32(i)) + copy(esi.Value[6:9], iBuf[1:4]) + case ESI_ROUTERID: + if argLen < 3 { + return esi, invalidEsiValuesError + } + // Router ID + ip := net.ParseIP(args[1]) + if ip == nil || ip.To4() == nil { + return esi, invalidEsiValuesError + } + copy(esi.Value[0:4], ip.To4()) + // Local Discriminator + i, err := strconv.ParseUint(args[2], 10, 32) + if err != nil { + return esi, invalidEsiValuesError + } + binary.BigEndian.PutUint32(esi.Value[4:8], uint32(i)) + case ESI_AS: + if argLen < 3 { + return esi, invalidEsiValuesError + } + // AS + as, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return esi, invalidEsiValuesError + } + binary.BigEndian.PutUint32(esi.Value[0:4], uint32(as)) + // Local Discriminator + i, err := strconv.ParseUint(args[2], 10, 32) + if err != nil { + return esi, invalidEsiValuesError + } + binary.BigEndian.PutUint32(esi.Value[4:8], uint32(i)) + case ESI_ARBITRARY: + fallthrough + default: + if argLen < 2 { + // Assumes the Value field is omitted + break + } + values := make([]byte, 0, 9) + for _, e := range strings.SplitN(args[1], ":", 9) { + v, err := strconv.ParseUint(e, 16, 16) + if err != nil { + return esi, invalidEsiValuesError + } + values = append(values, byte(v)) + } + copy(esi.Value, values) + } + + return esi, nil +} + +// +// I-D bess-evpn-overlay-01 +// +// 5.1.3 Constructing EVPN BGP Routes +// +// For the balance of this memo, the MPLS label field will be +// referred to as the VNI/VSID field. The VNI/VSID field is used for +// both local and global VNIs/VSIDs, and for either case the entire 24- +// bit field is used to encode the VNI/VSID value. +// +// We can't use type MPLSLabelStack for EVPN NLRI, because EVPN NLRI's MPLS +// field can be filled with VXLAN VNI. In that case, we must avoid modifying +// bottom of stack bit. +// + +func labelDecode(data []byte) (uint32, error) { + if len(data) < 3 { + return 0, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all Label bytes available") + } + return uint32(data[0])<<16 | uint32(data[1])<<8 | uint32(data[2]), nil +} + +func labelSerialize(label uint32) ([]byte, error) { + if label > 0xffffff { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Out of range Label: %d", label)) + } + buf := make([]byte, 3) + buf[0] = byte((label >> 16) & 0xff) + buf[1] = byte((label >> 8) & 0xff) + buf[2] = byte(label & 0xff) + return buf, nil +} + +type EVPNEthernetAutoDiscoveryRoute struct { + RD RouteDistinguisherInterface + ESI EthernetSegmentIdentifier + ETag uint32 + Label uint32 +} + +func (er *EVPNEthernetAutoDiscoveryRoute) Len() int { + // RD(8) + ESI(10) + ETag(4) + Label(3) + return 25 +} + +func (er *EVPNEthernetAutoDiscoveryRoute) DecodeFromBytes(data []byte) error { + er.RD = GetRouteDistinguisher(data) + rdLen := er.RD.Len() + if len(data) < rdLen+14 { // 14 is 10 for + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "bad Ethernet Auto-discovery Route length") + } + data = data[er.RD.Len():] + err := er.ESI.DecodeFromBytes(data) + if err != nil { + return err + } + data = data[10:] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + data = data[4:] + if er.Label, err = labelDecode(data); err != nil { + return err + } + return nil +} + +func (er *EVPNEthernetAutoDiscoveryRoute) Serialize() ([]byte, error) { + var buf []byte + var err error + if er.RD != nil { + buf, err = er.RD.Serialize() + if err != nil { + return nil, err + } + } else { + buf = make([]byte, 8) + } + tbuf, err := er.ESI.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + var tagBuf [4]byte + binary.BigEndian.PutUint32(tagBuf[:4], er.ETag) + buf = append(buf, tagBuf[:4]...) + + tbuf, err = labelSerialize(er.Label) + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + return buf, nil +} + +func (er *EVPNEthernetAutoDiscoveryRoute) String() string { + // RFC7432: BGP MPLS-Based Ethernet VPN + // 7.1. Ethernet Auto-discovery Route + // For the purpose of BGP route key processing, only the Ethernet + // Segment Identifier and the Ethernet Tag ID are considered to be part + // of the prefix in the NLRI. The MPLS Label field is to be treated as + // a route attribute as opposed to being part of the route. + return fmt.Sprintf("[type:A-D][rd:%s][esi:%s][etag:%d]", er.RD, er.ESI.String(), er.ETag) +} + +func (er *EVPNEthernetAutoDiscoveryRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + ESI string `json:"esi"` + Etag uint32 `json:"etag"` + Label uint32 `json:"label"` + }{ + RD: er.RD, + ESI: er.ESI.String(), + Etag: er.ETag, + Label: er.Label, + }) +} + +func (er *EVPNEthernetAutoDiscoveryRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNEthernetAutoDiscoveryRoute(rd RouteDistinguisherInterface, esi EthernetSegmentIdentifier, etag uint32, label uint32) *EVPNNLRI { + return NewEVPNNLRI(EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY, &EVPNEthernetAutoDiscoveryRoute{ + RD: rd, + ESI: esi, + ETag: etag, + Label: label, + }) +} + +type EVPNMacIPAdvertisementRoute struct { + RD RouteDistinguisherInterface + ESI EthernetSegmentIdentifier + ETag uint32 + MacAddressLength uint8 + MacAddress net.HardwareAddr + IPAddressLength uint8 + IPAddress net.IP + Labels []uint32 +} + +func (er *EVPNMacIPAdvertisementRoute) Len() int { + // RD(8) + ESI(10) + ETag(4) + MacAddressLength(1) + MacAddress(6) + // + IPAddressLength(1) + IPAddress(0, 4 or 16) + Labels(3 or 6) + return 30 + int(er.IPAddressLength)/8 + len(er.Labels)*3 +} + +func (er *EVPNMacIPAdvertisementRoute) DecodeFromBytes(data []byte) error { + er.RD = GetRouteDistinguisher(data) + rdLen := er.RD.Len() + if len(data) < rdLen { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "bad length of MAC/IP Advertisement Route") + } + data = data[er.RD.Len():] + err := er.ESI.DecodeFromBytes(data) + if err != nil { + return err + } + data = data[10:] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + data = data[4:] + er.MacAddressLength = data[0] + er.MacAddress = net.HardwareAddr(data[1:7]) + er.IPAddressLength = data[7] + data = data[8:] + if er.IPAddressLength == 32 || er.IPAddressLength == 128 { + er.IPAddress = net.IP(data[0:((er.IPAddressLength) / 8)]) + } else if er.IPAddressLength != 0 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid IP address length: %d", er.IPAddressLength)) + } + data = data[(er.IPAddressLength / 8):] + var label uint32 + if label, err = labelDecode(data); err != nil { + return err + } + er.Labels = append(er.Labels, label) + data = data[3:] + if len(data) == 3 { + if label, err = labelDecode(data); err != nil { + return err + } + er.Labels = append(er.Labels, label) + } + return nil +} + +func (er *EVPNMacIPAdvertisementRoute) Serialize() ([]byte, error) { + var buf []byte + var err error + if er.RD != nil { + buf, err = er.RD.Serialize() + if err != nil { + return nil, err + } + } else { + buf = make([]byte, 8) + } + + esi, err := er.ESI.Serialize() + if err != nil { + return nil, err + } + + buf = append(buf, esi...) + var tbuf [7]byte + binary.BigEndian.PutUint32(tbuf[:4], er.ETag) + buf = append(buf, tbuf[:4]...) + tbuf[0] = er.MacAddressLength + copy(tbuf[1:], er.MacAddress) + buf = append(buf, tbuf[:7]...) + + buf = append(buf, er.IPAddressLength) + switch er.IPAddressLength { + case 0: + // IP address omitted + case 32: + buf = append(buf, []byte(er.IPAddress.To4())...) + case 128: + buf = append(buf, []byte(er.IPAddress.To16())...) + default: + return nil, fmt.Errorf("invalid IP address length: %d", er.IPAddressLength) + } + + for _, l := range er.Labels { + label, err := labelSerialize(l) + if err != nil { + return nil, err + } + buf = append(buf, label...) + } + return buf, nil +} + +func (er *EVPNMacIPAdvertisementRoute) String() string { + // RFC7432: BGP MPLS-Based Ethernet VPN + // 7.2. MAC/IP Advertisement Route + // For the purpose of BGP route key processing, only the Ethernet Tag + // ID, MAC Address Length, MAC Address, IP Address Length, and IP + // Address fields are considered to be part of the prefix in the NLRI. + // The Ethernet Segment Identifier, MPLS Label1, and MPLS Label2 fields + // are to be treated as route attributes as opposed to being part of the + // "route". + return fmt.Sprintf("[type:macadv][rd:%s][etag:%d][mac:%s][ip:%s]", er.RD, er.ETag, er.MacAddress, er.IPAddress) +} + +func (er *EVPNMacIPAdvertisementRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + ESI string `json:"esi"` + Etag uint32 `json:"etag"` + MacAddress string `json:"mac"` + IPAddress string `json:"ip"` + Labels []uint32 `json:"labels"` + }{ + RD: er.RD, + ESI: er.ESI.String(), + Etag: er.ETag, + MacAddress: er.MacAddress.String(), + IPAddress: er.IPAddress.String(), + Labels: er.Labels, + }) +} + +func (er *EVPNMacIPAdvertisementRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNMacIPAdvertisementRoute(rd RouteDistinguisherInterface, esi EthernetSegmentIdentifier, etag uint32, macAddress string, ipAddress string, labels []uint32) *EVPNNLRI { + mac, _ := net.ParseMAC(macAddress) + var ipLen uint8 + ip := net.ParseIP(ipAddress) + if ip != nil { + if ipv4 := ip.To4(); ipv4 != nil { + ipLen = 32 + ip = ipv4 + } else { + ipLen = 128 + } + } + return NewEVPNNLRI(EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, &EVPNMacIPAdvertisementRoute{ + RD: rd, + ESI: esi, + ETag: etag, + MacAddressLength: 48, + MacAddress: mac, + IPAddressLength: ipLen, + IPAddress: ip, + Labels: labels, + }) +} + +type EVPNMulticastEthernetTagRoute struct { + RD RouteDistinguisherInterface + ETag uint32 + IPAddressLength uint8 + IPAddress net.IP +} + +func (er *EVPNMulticastEthernetTagRoute) Len() int { + // RD(8) + ETag(4) + IPAddressLength(1) + IPAddress(4 or 16) + return 13 + int(er.IPAddressLength)/8 +} + +func (er *EVPNMulticastEthernetTagRoute) DecodeFromBytes(data []byte) error { + er.RD = GetRouteDistinguisher(data) + rdLen := er.RD.Len() + if len(data) < rdLen+4 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid length of multicast ethernet tag route") + } + data = data[er.RD.Len():] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + er.IPAddressLength = data[4] + data = data[5:] + if er.IPAddressLength == 32 || er.IPAddressLength == 128 { + er.IPAddress = net.IP(data[:er.IPAddressLength/8]) + } else { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid IP address length: %d", er.IPAddressLength)) + } + return nil +} + +func (er *EVPNMulticastEthernetTagRoute) Serialize() ([]byte, error) { + var buf []byte + var err error + if er.RD != nil { + buf, err = er.RD.Serialize() + if err != nil { + return nil, err + } + } else { + buf = make([]byte, 8) + } + var tbuf [4]byte + binary.BigEndian.PutUint32(tbuf[:4], er.ETag) + buf = append(buf, tbuf[:4]...) + buf = append(buf, er.IPAddressLength) + switch er.IPAddressLength { + case 32: + buf = append(buf, []byte(er.IPAddress.To4())...) + case 128: + buf = append(buf, []byte(er.IPAddress.To16())...) + default: + return nil, fmt.Errorf("invalid IP address length: %d", er.IPAddressLength) + } + return buf, nil +} + +func (er *EVPNMulticastEthernetTagRoute) String() string { + // RFC7432: BGP MPLS-Based Ethernet VPN + // 7.3. Inclusive Multicast Ethernet Tag Route + // ...(snip)... For the purpose of BGP route key + // processing, only the Ethernet Tag ID, IP Address Length, and + // Originating Router's IP Address fields are considered to be part of + // the prefix in the NLRI. + return fmt.Sprintf("[type:multicast][rd:%s][etag:%d][ip:%s]", er.RD, er.ETag, er.IPAddress) +} + +func (er *EVPNMulticastEthernetTagRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + Etag uint32 `json:"etag"` + IPAddress string `json:"ip"` + }{ + RD: er.RD, + Etag: er.ETag, + IPAddress: er.IPAddress.String(), + }) +} + +func (er *EVPNMulticastEthernetTagRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNMulticastEthernetTagRoute(rd RouteDistinguisherInterface, etag uint32, ipAddress string) *EVPNNLRI { + ipLen := uint8(32) + ip := net.ParseIP(ipAddress) + if ipv4 := ip.To4(); ipv4 != nil { + ip = ipv4 + } else { + ipLen = 128 + } + return NewEVPNNLRI(EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, &EVPNMulticastEthernetTagRoute{ + RD: rd, + ETag: etag, + IPAddressLength: ipLen, + IPAddress: ip, + }) +} + +type EVPNEthernetSegmentRoute struct { + RD RouteDistinguisherInterface + ESI EthernetSegmentIdentifier + IPAddressLength uint8 + IPAddress net.IP +} + +func (er *EVPNEthernetSegmentRoute) Len() int { + // RD(8) + ESI(10) + IPAddressLength(1) + IPAddress(4 or 16) + return 19 + int(er.IPAddressLength)/8 +} + +func (er *EVPNEthernetSegmentRoute) DecodeFromBytes(data []byte) error { + er.RD = GetRouteDistinguisher(data) + rdLen := er.RD.Len() + if len(data) < rdLen { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid Ethernet Segment Route length") + } + data = data[er.RD.Len():] + er.ESI.DecodeFromBytes(data) + data = data[10:] + er.IPAddressLength = data[0] + data = data[1:] + if er.IPAddressLength == 32 || er.IPAddressLength == 128 { + er.IPAddress = net.IP(data[:er.IPAddressLength/8]) + } else { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid IP address length: %d", er.IPAddressLength)) + } + return nil +} + +func (er *EVPNEthernetSegmentRoute) Serialize() ([]byte, error) { + var buf []byte + var err error + if er.RD != nil { + buf, err = er.RD.Serialize() + if err != nil { + return nil, err + } + } else { + buf = make([]byte, 8) + } + tbuf, err := er.ESI.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + buf = append(buf, er.IPAddressLength) + switch er.IPAddressLength { + case 32: + buf = append(buf, []byte(er.IPAddress.To4())...) + case 128: + buf = append(buf, []byte(er.IPAddress.To16())...) + default: + return nil, fmt.Errorf("invalid IP address length: %d", er.IPAddressLength) + } + return buf, nil +} + +func (er *EVPNEthernetSegmentRoute) String() string { + // RFC7432: BGP MPLS-Based Ethernet VPN + // 7.4. Ethernet Segment Route + // For the purpose of BGP route key processing, only the Ethernet + // Segment ID, IP Address Length, and Originating Router's IP Address + // fields are considered to be part of the prefix in the NLRI. + return fmt.Sprintf("[type:esi][rd:%s][esi:%s][ip:%s]", er.RD, er.ESI.String(), er.IPAddress) +} + +func (er *EVPNEthernetSegmentRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + ESI string `json:"esi"` + IPAddress string `json:"ip"` + }{ + RD: er.RD, + ESI: er.ESI.String(), + IPAddress: er.IPAddress.String(), + }) +} + +func (er *EVPNEthernetSegmentRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNEthernetSegmentRoute(rd RouteDistinguisherInterface, esi EthernetSegmentIdentifier, ipAddress string) *EVPNNLRI { + ipLen := uint8(32) + ip := net.ParseIP(ipAddress) + if ipv4 := ip.To4(); ipv4 != nil { + ip = ipv4 + } else { + ipLen = 128 + } + return NewEVPNNLRI(EVPN_ETHERNET_SEGMENT_ROUTE, &EVPNEthernetSegmentRoute{ + RD: rd, + ESI: esi, + IPAddressLength: ipLen, + IPAddress: ip, + }) +} + +type EVPNIPPrefixRoute struct { + RD RouteDistinguisherInterface + ESI EthernetSegmentIdentifier + ETag uint32 + IPPrefixLength uint8 + IPPrefix net.IP + GWIPAddress net.IP + Label uint32 +} + +func (er *EVPNIPPrefixRoute) Len() int { + if er.IPPrefix.To4() != nil { + return 34 + } + return 58 +} + +func (er *EVPNIPPrefixRoute) DecodeFromBytes(data []byte) error { + addrLen := net.IPv4len + switch len(data) { + case 34: + // RD(8) + ESI(10) + ETag(4) + IPPrefixLength(1) + IPv4 Prefix(4) + GW IPv4(4) + Label(3) + case 58: + // RD(8) + ESI(10) + ETag(4) + IPPrefixLength(1) + IPv6 Prefix(16) + GW IPv6(16) + Label(3) + addrLen = net.IPv6len + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all EVPN IP Prefix Route bytes available") + } + + er.RD = GetRouteDistinguisher(data[0:8]) + + err := er.ESI.DecodeFromBytes(data[8:18]) + if err != nil { + return err + } + + er.ETag = binary.BigEndian.Uint32(data[18:22]) + + er.IPPrefixLength = data[22] + + offset := 23 // RD(8) + ESI(10) + ETag(4) + IPPrefixLength(1) + er.IPPrefix = data[offset : offset+addrLen] + offset += addrLen + + er.GWIPAddress = data[offset : offset+addrLen] + offset += addrLen + + if er.Label, err = labelDecode(data[offset : offset+3]); err != nil { + return err + } + //offset += 3 + + return nil +} + +func (er *EVPNIPPrefixRoute) Serialize() ([]byte, error) { + buf := make([]byte, 23) // RD(8) + ESI(10) + ETag(4) + IPPrefixLength(1) + + if er.RD != nil { + tbuf, err := er.RD.Serialize() + if err != nil { + return nil, err + } + copy(buf[0:8], tbuf) + } + + tbuf, err := er.ESI.Serialize() + if err != nil { + return nil, err + } + copy(buf[8:18], tbuf) + + binary.BigEndian.PutUint32(buf[18:22], er.ETag) + + buf[22] = er.IPPrefixLength + + if er.IPPrefix == nil { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "IP Prefix is nil") + } else if er.IPPrefix.To4() != nil { + buf = append(buf, er.IPPrefix.To4()...) + if er.GWIPAddress == nil { + // draft-ietf-bess-evpn-prefix-advertisement: IP Prefix Advertisement in EVPN + // The GW IP field SHOULD be zero if it is not used as an Overlay Index. + er.GWIPAddress = net.IPv4zero + } + buf = append(buf, er.GWIPAddress.To4()...) + } else { + buf = append(buf, er.IPPrefix.To16()...) + if er.GWIPAddress == nil { + er.GWIPAddress = net.IPv6zero + } + buf = append(buf, er.GWIPAddress.To16()...) + } + + tbuf, err = labelSerialize(er.Label) + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + return buf, nil +} + +func (er *EVPNIPPrefixRoute) String() string { + // draft-ietf-bess-evpn-prefix-advertisement: IP Prefix Advertisement in EVPN + // 3.1 IP Prefix Route Encoding + // The RD, Eth-Tag ID, IP Prefix Length and IP Prefix will be part of + // the route key used by BGP to compare routes. The rest of the fields + // will not be part of the route key. + return fmt.Sprintf("[type:Prefix][rd:%s][etag:%d][prefix:%s/%d]", er.RD, er.ETag, er.IPPrefix, er.IPPrefixLength) +} + +func (er *EVPNIPPrefixRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + ESI string `json:"esi"` + Etag uint32 `json:"etag"` + Prefix string `json:"prefix"` + Gateway string `json:"gateway"` + Label uint32 `json:"label"` + }{ + RD: er.RD, + ESI: er.ESI.String(), + Etag: er.ETag, + Prefix: fmt.Sprintf("%s/%d", er.IPPrefix, er.IPPrefixLength), + Gateway: er.GWIPAddress.String(), + Label: er.Label, + }) +} + +func (er *EVPNIPPrefixRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNIPPrefixRoute(rd RouteDistinguisherInterface, esi EthernetSegmentIdentifier, etag uint32, ipPrefixLength uint8, ipPrefix string, gateway string, label uint32) *EVPNNLRI { + ip := net.ParseIP(ipPrefix) + gw := net.ParseIP(gateway) + if ipv4 := ip.To4(); ipv4 != nil { + ip = ipv4 + gw = gw.To4() + } + return NewEVPNNLRI(EVPN_IP_PREFIX, &EVPNIPPrefixRoute{ + RD: rd, + ESI: esi, + ETag: etag, + IPPrefixLength: ipPrefixLength, + IPPrefix: ip, + GWIPAddress: gw, + Label: label, + }) +} + +type EVPNIPMSIRoute struct { + RD RouteDistinguisherInterface + ETag uint32 + EC ExtendedCommunityInterface +} + +func (er *EVPNIPMSIRoute) Len() int { + // RD(8) + ETag(4) + EC(8) + return 20 +} + +func (er *EVPNIPMSIRoute) DecodeFromBytes(data []byte) error { + + er.RD = GetRouteDistinguisher(data[0:8]) + + data = data[er.RD.Len():] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + + data = data[4:] + ec, err := ParseExtended(data[0:8]) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Parse extended community interface failed") + } + er.EC = ec + return nil +} + +func (er *EVPNIPMSIRoute) Serialize() ([]byte, error) { + buf := make([]byte, 20) + + if er.RD != nil { + tbuf, err := er.RD.Serialize() + if err != nil { + return nil, err + } + copy(buf[0:8], tbuf) + } + + binary.BigEndian.PutUint32(buf[8:12], er.ETag) + + ec, err := er.EC.Serialize() + if err != nil { + return nil, err + } + + return append(buf, ec...), nil +} + +func (er *EVPNIPMSIRoute) String() string { + ec := "default" + if er.EC != nil { + ec = er.EC.String() + } + return fmt.Sprintf("[type:I-PMSI][rd:%s][etag:%d][EC:%s]", er.RD, er.ETag, ec) +} + +func (er *EVPNIPMSIRoute) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + ETag uint32 `json:"etag"` + EC string `json:"ec"` + }{ + RD: er.RD, + ETag: er.ETag, + EC: er.EC.String(), + }) +} + +func (er *EVPNIPMSIRoute) rd() RouteDistinguisherInterface { + return er.RD +} + +func NewEVPNIPMSIRoute(rd RouteDistinguisherInterface, etag uint32, ec ExtendedCommunityInterface) *EVPNNLRI { + + return NewEVPNNLRI(EVPN_I_PMSI, &EVPNIPMSIRoute{ + RD: rd, + ETag: etag, + EC: ec, + }) +} + +type EVPNRouteTypeInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + rd() RouteDistinguisherInterface + MarshalJSON() ([]byte, error) +} + +func getEVPNRouteType(t uint8) (EVPNRouteTypeInterface, error) { + switch t { + case EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY: + return &EVPNEthernetAutoDiscoveryRoute{}, nil + case EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: + return &EVPNMacIPAdvertisementRoute{}, nil + case EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + return &EVPNMulticastEthernetTagRoute{}, nil + case EVPN_ETHERNET_SEGMENT_ROUTE: + return &EVPNEthernetSegmentRoute{}, nil + case EVPN_IP_PREFIX: + return &EVPNIPPrefixRoute{}, nil + } + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Unknown EVPN Route type: %d", t)) +} + +const ( + EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY = 1 + EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT = 2 + EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG = 3 + EVPN_ETHERNET_SEGMENT_ROUTE = 4 + EVPN_IP_PREFIX = 5 + EVPN_I_PMSI = 9 +) + +type EVPNNLRI struct { + PrefixDefault + RouteType uint8 + Length uint8 + RouteTypeData EVPNRouteTypeInterface +} + +func (n *EVPNNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if IsAddPathEnabled(true, RF_EVPN, options) { + var err error + data, err = n.decodePathIdentifier(data) + if err != nil { + return err + } + } + if len(data) < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all EVPNNLRI bytes available") + } + n.RouteType = data[0] + n.Length = data[1] + data = data[2:] + if len(data) < int(n.Length) { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all EVPNNLRI Route type bytes available") + } + r, err := getEVPNRouteType(n.RouteType) + if err != nil { + return err + } + n.RouteTypeData = r + return n.RouteTypeData.DecodeFromBytes(data[:n.Length]) +} + +func (n *EVPNNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf []byte + if IsAddPathEnabled(false, RF_EVPN, options) { + var err error + buf, err = n.serializeIdentifier() + if err != nil { + return nil, err + } + } + offset := len(buf) + buf = append(buf, make([]byte, 2)...) + buf[offset] = n.RouteType + tbuf, err := n.RouteTypeData.Serialize() + buf[offset+1] = n.Length + if err != nil { + return nil, err + } + return append(buf, tbuf...), nil +} + +func (n *EVPNNLRI) AFI() uint16 { + return AFI_L2VPN +} + +func (n *EVPNNLRI) SAFI() uint8 { + return SAFI_EVPN +} + +func (n *EVPNNLRI) Len(options ...*MarshallingOption) int { + return int(n.Length) + 2 +} + +func (n *EVPNNLRI) String() string { + if n.RouteTypeData != nil { + return n.RouteTypeData.String() + } + return fmt.Sprintf("%d:%d", n.RouteType, n.Length) +} + +func (n *EVPNNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint8 `json:"type"` + Value EVPNRouteTypeInterface `json:"value"` + }{ + Type: n.RouteType, + Value: n.RouteTypeData, + }) +} + +func (n *EVPNNLRI) RD() RouteDistinguisherInterface { + return n.RouteTypeData.rd() +} + +func NewEVPNNLRI(routeType uint8, routeTypeData EVPNRouteTypeInterface) *EVPNNLRI { + var l uint8 + if routeTypeData != nil { + l = uint8(routeTypeData.Len()) + } + return &EVPNNLRI{ + RouteType: routeType, + Length: l, + RouteTypeData: routeTypeData, + } +} + +type EncapNLRI struct { + IPAddrPrefixDefault + addrlen uint8 +} + +func (n *EncapNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if n.addrlen == 0 { + n.addrlen = 4 + } + f := RF_IPv4_ENCAP + if n.addrlen == 16 { + f = RF_IPv6_ENCAP + } + if IsAddPathEnabled(true, f, options) { + var err error + data, err = n.decodePathIdentifier(data) + if err != nil { + return err + } + } + if len(data) < 4 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "prefix misses length field") + } + n.Length = data[0] + if n.addrlen == 0 { + n.addrlen = 4 + } + return n.decodePrefix(data[1:], n.Length, n.addrlen) +} + +func (n *EncapNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf []byte + f := RF_IPv4_ENCAP + if n.addrlen == 16 { + f = RF_IPv6_ENCAP + } + if IsAddPathEnabled(false, f, options) { + var err error + buf, err = n.serializeIdentifier() + if err != nil { + return nil, err + } + } + if n.Prefix.To4() != nil { + buf = append(buf, net.IPv4len*8) + n.Prefix = n.Prefix.To4() + } else { + buf = append(buf, net.IPv6len*8) + } + n.Length = buf[len(buf)-1] + pbuf, err := n.serializePrefix(n.Length) + if err != nil { + return nil, err + } + return append(buf, pbuf...), nil +} + +func (n *EncapNLRI) String() string { + return n.Prefix.String() +} + +func (n *EncapNLRI) AFI() uint16 { + return AFI_IP +} + +func (n *EncapNLRI) SAFI() uint8 { + return SAFI_ENCAPSULATION +} + +func (n *EncapNLRI) Len(options ...*MarshallingOption) int { + return 1 + len(n.Prefix) +} + +func NewEncapNLRI(endpoint string) *EncapNLRI { + return &EncapNLRI{ + IPAddrPrefixDefault{Length: 32, Prefix: net.ParseIP(endpoint).To4()}, + 4, + } +} + +type Encapv6NLRI struct { + EncapNLRI +} + +func (n *Encapv6NLRI) AFI() uint16 { + return AFI_IP6 +} + +func NewEncapv6NLRI(endpoint string) *Encapv6NLRI { + return &Encapv6NLRI{ + EncapNLRI{ + IPAddrPrefixDefault{Length: 128, Prefix: net.ParseIP(endpoint)}, + 16, + }, + } +} + +type BGPFlowSpecType uint8 + +const ( + FLOW_SPEC_TYPE_UNKNOWN BGPFlowSpecType = iota + FLOW_SPEC_TYPE_DST_PREFIX + FLOW_SPEC_TYPE_SRC_PREFIX + FLOW_SPEC_TYPE_IP_PROTO + FLOW_SPEC_TYPE_PORT + FLOW_SPEC_TYPE_DST_PORT + FLOW_SPEC_TYPE_SRC_PORT + FLOW_SPEC_TYPE_ICMP_TYPE + FLOW_SPEC_TYPE_ICMP_CODE + FLOW_SPEC_TYPE_TCP_FLAG + FLOW_SPEC_TYPE_PKT_LEN + FLOW_SPEC_TYPE_DSCP + FLOW_SPEC_TYPE_FRAGMENT + FLOW_SPEC_TYPE_LABEL + FLOW_SPEC_TYPE_ETHERNET_TYPE // 14 + FLOW_SPEC_TYPE_SRC_MAC + FLOW_SPEC_TYPE_DST_MAC + FLOW_SPEC_TYPE_LLC_DSAP + FLOW_SPEC_TYPE_LLC_SSAP + FLOW_SPEC_TYPE_LLC_CONTROL + FLOW_SPEC_TYPE_SNAP + FLOW_SPEC_TYPE_VID + FLOW_SPEC_TYPE_COS + FLOW_SPEC_TYPE_INNER_VID + FLOW_SPEC_TYPE_INNER_COS +) + +var FlowSpecNameMap = map[BGPFlowSpecType]string{ + FLOW_SPEC_TYPE_UNKNOWN: "unknown", + FLOW_SPEC_TYPE_DST_PREFIX: "destination", + FLOW_SPEC_TYPE_SRC_PREFIX: "source", + FLOW_SPEC_TYPE_IP_PROTO: "protocol", + FLOW_SPEC_TYPE_PORT: "port", + FLOW_SPEC_TYPE_DST_PORT: "destination-port", + FLOW_SPEC_TYPE_SRC_PORT: "source-port", + FLOW_SPEC_TYPE_ICMP_TYPE: "icmp-type", + FLOW_SPEC_TYPE_ICMP_CODE: "icmp-code", + FLOW_SPEC_TYPE_TCP_FLAG: "tcp-flags", + FLOW_SPEC_TYPE_PKT_LEN: "packet-length", + FLOW_SPEC_TYPE_DSCP: "dscp", + FLOW_SPEC_TYPE_FRAGMENT: "fragment", + FLOW_SPEC_TYPE_LABEL: "label", + FLOW_SPEC_TYPE_ETHERNET_TYPE: "ether-type", + FLOW_SPEC_TYPE_SRC_MAC: "source-mac", + FLOW_SPEC_TYPE_DST_MAC: "destination-mac", + FLOW_SPEC_TYPE_LLC_DSAP: "llc-dsap", + FLOW_SPEC_TYPE_LLC_SSAP: "llc-ssap", + FLOW_SPEC_TYPE_LLC_CONTROL: "llc-control", + FLOW_SPEC_TYPE_SNAP: "snap", + FLOW_SPEC_TYPE_VID: "vid", + FLOW_SPEC_TYPE_COS: "cos", + FLOW_SPEC_TYPE_INNER_VID: "inner-vid", + FLOW_SPEC_TYPE_INNER_COS: "inner-cos", +} + +var FlowSpecValueMap = map[string]BGPFlowSpecType{ + FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PREFIX]: FLOW_SPEC_TYPE_DST_PREFIX, + FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PREFIX]: FLOW_SPEC_TYPE_SRC_PREFIX, + FlowSpecNameMap[FLOW_SPEC_TYPE_IP_PROTO]: FLOW_SPEC_TYPE_IP_PROTO, + FlowSpecNameMap[FLOW_SPEC_TYPE_PORT]: FLOW_SPEC_TYPE_PORT, + FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PORT]: FLOW_SPEC_TYPE_DST_PORT, + FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PORT]: FLOW_SPEC_TYPE_SRC_PORT, + FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_TYPE]: FLOW_SPEC_TYPE_ICMP_TYPE, + FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_CODE]: FLOW_SPEC_TYPE_ICMP_CODE, + FlowSpecNameMap[FLOW_SPEC_TYPE_TCP_FLAG]: FLOW_SPEC_TYPE_TCP_FLAG, + FlowSpecNameMap[FLOW_SPEC_TYPE_PKT_LEN]: FLOW_SPEC_TYPE_PKT_LEN, + FlowSpecNameMap[FLOW_SPEC_TYPE_DSCP]: FLOW_SPEC_TYPE_DSCP, + FlowSpecNameMap[FLOW_SPEC_TYPE_FRAGMENT]: FLOW_SPEC_TYPE_FRAGMENT, + FlowSpecNameMap[FLOW_SPEC_TYPE_LABEL]: FLOW_SPEC_TYPE_LABEL, + FlowSpecNameMap[FLOW_SPEC_TYPE_ETHERNET_TYPE]: FLOW_SPEC_TYPE_ETHERNET_TYPE, + FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_MAC]: FLOW_SPEC_TYPE_SRC_MAC, + FlowSpecNameMap[FLOW_SPEC_TYPE_DST_MAC]: FLOW_SPEC_TYPE_DST_MAC, + FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_DSAP]: FLOW_SPEC_TYPE_LLC_DSAP, + FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_SSAP]: FLOW_SPEC_TYPE_LLC_SSAP, + FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_CONTROL]: FLOW_SPEC_TYPE_LLC_CONTROL, + FlowSpecNameMap[FLOW_SPEC_TYPE_SNAP]: FLOW_SPEC_TYPE_SNAP, + FlowSpecNameMap[FLOW_SPEC_TYPE_VID]: FLOW_SPEC_TYPE_VID, + FlowSpecNameMap[FLOW_SPEC_TYPE_COS]: FLOW_SPEC_TYPE_COS, + FlowSpecNameMap[FLOW_SPEC_TYPE_INNER_VID]: FLOW_SPEC_TYPE_INNER_VID, + FlowSpecNameMap[FLOW_SPEC_TYPE_INNER_COS]: FLOW_SPEC_TYPE_INNER_COS, +} + +// Joins the given and args into a single string and normalize it. +// Example: +// args := []string{" & <=80", " tcp != udp ", " =! SA & =U! F", " = is-fragment+last-fragment"} +// fmt.Printf("%q", normalizeFlowSpecOpValues(args)) +// >>> ["<=80" "tcp" "!=udp" "=!SA" "&=U" "!F" "=is-fragment+last-fragment"] +func normalizeFlowSpecOpValues(args []string) []string { + // Extracts keywords from the given args. + sub := "" + subs := make([]string, 0) + for _, s := range _regexpFlowSpecOperator.FindAllString(strings.Join(args, " "), -1) { + sub += s + if _regexpFlowSpecOperatorValue.MatchString(s) { + subs = append(subs, sub) + sub = "" + } + } + + // RFC5575 says "It should be unset in the first operator byte of a + // sequence". + if len(subs) > 0 { + subs[0] = strings.TrimPrefix(subs[0], "&") + } + + return subs +} + +// Parses the FlowSpec numeric operator using the given submatch which should be +// the return value of func (*Regexp) FindStringSubmatch. +func parseFlowSpecNumericOperator(submatch []string) (operator uint8, err error) { + if submatch[1] == "&" { + operator = DEC_NUM_OP_AND + } + value, ok := DECNumOpValueMap[submatch[2]] + if !ok { + return 0, fmt.Errorf("invalid numeric operator: %s%s", submatch[1], submatch[2]) + } + operator |= uint8(value) + return operator, nil +} + +// Parses the pairs of operator and value for the FlowSpec numeric type. The +// given validationFunc is applied to evaluate whether the parsed value is +// valid or not (e.g., if exceeds range or not). +// Note: Each of the args should be formatted in single pair of operator and +// value before calling this function. +// e.g.) "&==100", ">=200" or "&<300" +func parseFlowSpecNumericOpValues(typ BGPFlowSpecType, args []string, validationFunc func(uint64) error) (FlowSpecComponentInterface, error) { + argsLen := len(args) + items := make([]*FlowSpecComponentItem, 0, argsLen) + for idx, arg := range args { + m := _regexpFlowSpecNumericType.FindStringSubmatch(arg) + if len(m) < 4 { + return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) + } + operator, err := parseFlowSpecNumericOperator(m) + if err != nil { + return nil, err + } + // "true" and "false" is operator, but here handles them as value. + var value uint64 + switch m[3] { + case "true", "false": + if idx != argsLen-1 { + return nil, fmt.Errorf("%s should be the last of each rule", m[3]) + } + operator = uint8(DECNumOpValueMap[m[3]]) + default: + if value, err = strconv.ParseUint(m[3], 10, 64); err != nil { + return nil, fmt.Errorf("invalid numeric value: %s", m[3]) + } + if err = validationFunc(value); err != nil { + return nil, err + } + } + items = append(items, NewFlowSpecComponentItem(operator, value)) + } + + // Marks end-of-list bit + items[argsLen-1].Op |= uint8(DEC_NUM_OP_END) + + return NewFlowSpecComponent(typ, items), nil +} + +func flowSpecNumeric1ByteParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + args = normalizeFlowSpecOpValues(args) + + f := func(i uint64) error { + if i <= 0xff { // 1 byte + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecNumeric2BytesParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + args = normalizeFlowSpecOpValues(args) + + f := func(i uint64) error { + if i <= 0xffff { // 2 bytes + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +// Parses the FlowSpec bitmask operand using the given submatch which should be +// the return value of func (*Regexp) FindStringSubmatch. +func parseFlowSpecBitmaskOperand(submatch []string) (operand uint8, err error) { + if submatch[1] == "&" { + operand = BITMASK_FLAG_OP_AND + } + value, ok := BitmaskFlagOpValueMap[submatch[2]] + if !ok { + return 0, fmt.Errorf("invalid bitmask operand: %s%s", submatch[1], submatch[2]) + } + operand |= uint8(value) + return operand, nil +} + +func flowSpecPrefixParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args[0]: IP Prefix or IP Address (suppose prefix length is 32) + // args[1]: Offset in bit (IPv6 only) + // + // Example: + // - IPv4 Prefix + // args := []string{"192.168.0.0/24"} + // - IPv4 Address + // args := []string{"192.168.0.1"} + // - IPv6 Prefix + // args := []string{"2001:db8:1::/64"} + // - IPv6 Prefix with offset + // args := []string{"0:db8:1::/64/16"} + // args := []string{"0:db8:1::/64", "16"} + // - IPv6 Address + // args := []string{"2001:db8:1::1"} + // - IPv6 Address with offset + // args := []string{"0:db8:1::1", "16"} + afi, _ := RouteFamilyToAfiSafi(rf) + switch afi { + case AFI_IP: + if len(args) > 1 { + return nil, errors.New("cannot specify offset for ipv4 prefix") + } + invalidIPv4PrefixError := fmt.Errorf("invalid ipv4 prefix: %s", args[0]) + m := _regexpFindIPv4Prefix.FindStringSubmatch(args[0]) + if len(m) < 4 { + return nil, invalidIPv4PrefixError + } + prefix := net.ParseIP(m[1]) + if prefix.To4() == nil { + return nil, invalidIPv4PrefixError + } + var prefixLen uint64 = 32 + if m[3] != "" { + var err error + prefixLen, err = strconv.ParseUint(m[3], 10, 8) + if err != nil || prefixLen > 32 { + return nil, invalidIPv4PrefixError + } + } + switch typ { + case FLOW_SPEC_TYPE_DST_PREFIX: + return NewFlowSpecDestinationPrefix(NewIPAddrPrefix(uint8(prefixLen), prefix.String())), nil + case FLOW_SPEC_TYPE_SRC_PREFIX: + return NewFlowSpecSourcePrefix(NewIPAddrPrefix(uint8(prefixLen), prefix.String())), nil + } + return nil, fmt.Errorf("invalid traffic filtering rule type: %s", typ.String()) + case AFI_IP6: + if len(args) > 2 { + return nil, fmt.Errorf("invalid arguments for ipv6 prefix: %q", args) + } + invalidIPv6PrefixError := fmt.Errorf("invalid ipv6 prefix: %s", args[0]) + m := _regexpFindIPv6Prefix.FindStringSubmatch(args[0]) + if len(m) < 4 { + return nil, invalidIPv6PrefixError + } + prefix := net.ParseIP(m[1]) + if prefix.To16() == nil { + return nil, invalidIPv6PrefixError + } + var prefixLen uint64 = 128 + if m[3] != "" { + var err error + prefixLen, err = strconv.ParseUint(m[3], 10, 8) + if err != nil || prefixLen > 128 { + return nil, invalidIPv6PrefixError + } + } + var offset uint64 + if len(args) == 1 && m[5] != "" { + var err error + offset, err = strconv.ParseUint(m[5], 10, 8) + if err != nil || offset > 128 { + return nil, fmt.Errorf("invalid ipv6 prefix offset: %s", m[5]) + } + } else if len(args) == 2 { + if m[5] != "" { + return nil, fmt.Errorf("multiple ipv6 prefix offset arguments detected: %q", args) + } + var err error + offset, err = strconv.ParseUint(args[1], 10, 8) + if err != nil || offset > 128 { + return nil, fmt.Errorf("invalid ipv6 prefix offset: %s", args[1]) + } + } + switch typ { + case FLOW_SPEC_TYPE_DST_PREFIX: + return NewFlowSpecDestinationPrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), uint8(offset)), nil + case FLOW_SPEC_TYPE_SRC_PREFIX: + return NewFlowSpecSourcePrefix6(NewIPv6AddrPrefix(uint8(prefixLen), prefix.String()), uint8(offset)), nil + } + return nil, fmt.Errorf("invalid traffic filtering rule type: %s", typ.String()) + } + return nil, fmt.Errorf("invalid address family: %s", rf.String()) +} + +func flowSpecIpProtoParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args: List of pairs of Operator and IP protocol type + // + // Example: + // - TCP or UDP + // args := []string{"tcp", "==udp"} + // - Not TCP and not UDP + // args := []string{"!=tcp", "&!=udp"} + args = normalizeFlowSpecOpValues(args) + s := strings.Join(args, " ") + for i, name := range ProtocolNameMap { + s = strings.Replace(s, name, fmt.Sprintf("%d", i), -1) + } + args = strings.Split(s, " ") + + f := func(i uint64) error { + if i <= 0xff { // 1 byte + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecTcpFlagParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args: List of pairs of Operand and TCP Flags + // + // Example: + // - SYN or SYN/ACK + // args := []string{"==S", "==SA"} + // - Not FIN and not URG + // args := []string{"!=F", "&!=U"} + args = normalizeFlowSpecOpValues(args) + + argsLen := len(args) + items := make([]*FlowSpecComponentItem, 0, argsLen) + + for _, arg := range args { + m := _regexpFlowSpecTCPFlag.FindStringSubmatch(arg) + if len(m) < 6 { + return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) + } else if mLast := m[len(m)-1]; mLast != "" || m[3] != "" { + return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) + } + operand, err := parseFlowSpecBitmaskOperand(m) + if err != nil { + return nil, err + } + var value uint64 + for flag, name := range TCPFlagNameMap { + if strings.Contains(m[4], name) { + value |= uint64(flag) + } + } + items = append(items, NewFlowSpecComponentItem(operand, value)) + } + + // Marks end-of-list bit + items[argsLen-1].Op |= BITMASK_FLAG_OP_END + + return NewFlowSpecComponent(typ, items), nil +} + +func flowSpecDscpParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + args = normalizeFlowSpecOpValues(args) + + f := func(i uint64) error { + if i < 64 { // 6 bits + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecFragmentParser(_ RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args: List of pairs of Operator and Fragment flags + // + // Example: + // - is-fragment or last-fragment + // args := []string{"==is-fragment", "==last-fragment"} + // - is-fragment and last-fragment (exact match) + // args := []string{"==is-fragment+last-fragment"} + args = normalizeFlowSpecOpValues(args) + + argsLen := len(args) + items := make([]*FlowSpecComponentItem, 0, argsLen) + + for _, arg := range args { + m := _regexpFlowSpecFragment.FindStringSubmatch(arg) + if len(m) < 4 { + return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) + } else if mLast := m[len(m)-1]; mLast != "" { + return nil, fmt.Errorf("invalid argument for %s: %s in %q", typ.String(), arg, args) + } + operand, err := parseFlowSpecBitmaskOperand(m) + if err != nil { + return nil, err + } + var value uint64 + // Example: + // m[3] = "first-fragment+last-fragment" + for flag, name := range FragmentFlagNameMap { + if strings.Contains(m[3], name) { + value |= uint64(flag) + } + } + items = append(items, NewFlowSpecComponentItem(operand, value)) + } + + // Marks end-of-list bit + items[argsLen-1].Op |= BITMASK_FLAG_OP_END + + return NewFlowSpecComponent(typ, items), nil +} + +func flowSpecLabelParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + afi, _ := RouteFamilyToAfiSafi(rf) + if afi == AFI_IP { + return nil, fmt.Errorf("%s is not supported for ipv4", typ.String()) + } + + args = normalizeFlowSpecOpValues(args) + + f := func(i uint64) error { + if i <= 0xfffff { // 20 bits + return nil + } + return errors.New("flow label range exceeded") + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecEtherTypeParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args: List of pairs of Operator and Ether Types + // + // Example: + // - ARP or IPv4 + // args := []string{"==arp", "==ipv4"} + // - Not IPv4 and not IPv6 + // args := []string{"!=ipv4", "&!=ipv6"} + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + args = normalizeFlowSpecOpValues(args) + s := strings.Join(args, " ") + for i, name := range EthernetTypeNameMap { + s = strings.Replace(s, name, fmt.Sprintf("%d", i), -1) + } + args = strings.Split(s, " ") + + f := func(i uint64) error { + if i <= 0xffff { // 2 bytes + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecMacParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + // args[0]: MAC address + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + mac, err := net.ParseMAC(args[0]) + if err != nil { + return nil, fmt.Errorf("invalid mac address: %s", args[0]) + } + + switch typ { + case FLOW_SPEC_TYPE_DST_MAC: + return NewFlowSpecDestinationMac(mac), nil + case FLOW_SPEC_TYPE_SRC_MAC: + return NewFlowSpecSourceMac(mac), nil + } + return nil, fmt.Errorf("invalid traffic filtering rule type: %s", typ.String()) +} + +func flowSpecLlcParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + return flowSpecNumeric1ByteParser(rf, typ, args) +} + +func flowSpecSnapParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + args = normalizeFlowSpecOpValues(args) + + f := func(i uint64) error { + if i <= 0xffffffffff { // 5 bytes + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecVlanIDParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + args = normalizeFlowSpecOpValues(args) + s := strings.Join(args, " ") + for i, name := range EthernetTypeNameMap { + s = strings.Replace(s, name, fmt.Sprintf("%d", i), -1) + } + args = strings.Split(s, " ") + + f := func(i uint64) error { + if i <= 4095 { // 12 bits + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +func flowSpecVlanCosParser(rf RouteFamily, typ BGPFlowSpecType, args []string) (FlowSpecComponentInterface, error) { + if rf != RF_FS_L2_VPN { + return nil, fmt.Errorf("%s is supported for only l2vpn", typ.String()) + } + + args = normalizeFlowSpecOpValues(args) + s := strings.Join(args, " ") + for i, name := range EthernetTypeNameMap { + s = strings.Replace(s, name, fmt.Sprintf("%d", i), -1) + } + args = strings.Split(s, " ") + + f := func(i uint64) error { + if i <= 7 { // 3 bits + return nil + } + return fmt.Errorf("%s range exceeded", typ.String()) + } + + return parseFlowSpecNumericOpValues(typ, args, f) +} + +var flowSpecParserMap = map[BGPFlowSpecType]func(RouteFamily, BGPFlowSpecType, []string) (FlowSpecComponentInterface, error){ + FLOW_SPEC_TYPE_DST_PREFIX: flowSpecPrefixParser, + FLOW_SPEC_TYPE_SRC_PREFIX: flowSpecPrefixParser, + FLOW_SPEC_TYPE_IP_PROTO: flowSpecIpProtoParser, + FLOW_SPEC_TYPE_PORT: flowSpecNumeric2BytesParser, + FLOW_SPEC_TYPE_DST_PORT: flowSpecNumeric2BytesParser, + FLOW_SPEC_TYPE_SRC_PORT: flowSpecNumeric2BytesParser, + FLOW_SPEC_TYPE_ICMP_TYPE: flowSpecNumeric1ByteParser, + FLOW_SPEC_TYPE_ICMP_CODE: flowSpecNumeric1ByteParser, + FLOW_SPEC_TYPE_TCP_FLAG: flowSpecTcpFlagParser, + FLOW_SPEC_TYPE_PKT_LEN: flowSpecNumeric2BytesParser, + FLOW_SPEC_TYPE_DSCP: flowSpecDscpParser, + FLOW_SPEC_TYPE_FRAGMENT: flowSpecFragmentParser, + FLOW_SPEC_TYPE_LABEL: flowSpecLabelParser, + FLOW_SPEC_TYPE_ETHERNET_TYPE: flowSpecEtherTypeParser, + FLOW_SPEC_TYPE_DST_MAC: flowSpecMacParser, + FLOW_SPEC_TYPE_SRC_MAC: flowSpecMacParser, + FLOW_SPEC_TYPE_LLC_DSAP: flowSpecLlcParser, + FLOW_SPEC_TYPE_LLC_SSAP: flowSpecLlcParser, + FLOW_SPEC_TYPE_LLC_CONTROL: flowSpecLlcParser, + FLOW_SPEC_TYPE_SNAP: flowSpecSnapParser, + FLOW_SPEC_TYPE_VID: flowSpecVlanIDParser, + FLOW_SPEC_TYPE_COS: flowSpecVlanCosParser, + FLOW_SPEC_TYPE_INNER_VID: flowSpecVlanIDParser, + FLOW_SPEC_TYPE_INNER_COS: flowSpecVlanCosParser, +} + +func extractFlowSpecArgs(args []string) map[BGPFlowSpecType][]string { + m := make(map[BGPFlowSpecType][]string, len(FlowSpecValueMap)) + var typ BGPFlowSpecType + for _, arg := range args { + if t, ok := FlowSpecValueMap[arg]; ok { + typ = t + m[typ] = make([]string, 0) + } else { + m[typ] = append(m[typ], arg) + } + } + return m +} + +func ParseFlowSpecComponents(rf RouteFamily, arg string) ([]FlowSpecComponentInterface, error) { + _, safi := RouteFamilyToAfiSafi(rf) + switch safi { + case SAFI_FLOW_SPEC_UNICAST, SAFI_FLOW_SPEC_VPN: + // Valid + default: + return nil, fmt.Errorf("invalid address family: %s", rf.String()) + } + + typeArgs := extractFlowSpecArgs(strings.Split(arg, " ")) + rules := make([]FlowSpecComponentInterface, 0, len(typeArgs)) + for typ, args := range typeArgs { + parser, ok := flowSpecParserMap[typ] + if !ok { + return nil, fmt.Errorf("unsupported traffic filtering rule type: %s", typ.String()) + } + if len(args) == 0 { + return nil, fmt.Errorf("specify traffic filtering rules for %s", typ.String()) + } + rule, err := parser(rf, typ, args) + if err != nil { + return nil, err + } + rules = append(rules, rule) + } + return rules, nil +} + +func (t BGPFlowSpecType) String() string { + name, ok := FlowSpecNameMap[t] + if !ok { + return fmt.Sprintf("%s(%d)", FlowSpecNameMap[FLOW_SPEC_TYPE_UNKNOWN], t) + } + return name +} + +type FlowSpecComponentInterface interface { + DecodeFromBytes([]byte, ...*MarshallingOption) error + Serialize(...*MarshallingOption) ([]byte, error) + Len(...*MarshallingOption) int + Type() BGPFlowSpecType + String() string +} + +type flowSpecPrefix struct { + Prefix AddrPrefixInterface + typ BGPFlowSpecType +} + +func (p *flowSpecPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + p.typ = BGPFlowSpecType(data[0]) + return p.Prefix.DecodeFromBytes(data[1:], options...) +} + +func (p *flowSpecPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + bbuf, err := p.Prefix.Serialize(options...) + if err != nil { + return nil, err + } + buf := make([]byte, 1+len(bbuf)) + buf[0] = byte(p.Type()) + copy(buf[1:], bbuf) + return buf, nil +} + +func (p *flowSpecPrefix) Len(options ...*MarshallingOption) int { + buf, _ := p.Serialize(options...) + return len(buf) +} + +func (p *flowSpecPrefix) Type() BGPFlowSpecType { + return p.typ +} + +func (p *flowSpecPrefix) String() string { + return fmt.Sprintf("[%s: %s]", p.Type(), p.Prefix.String()) +} + +func (p *flowSpecPrefix) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPFlowSpecType `json:"type"` + Value AddrPrefixInterface `json:"value"` + }{ + Type: p.Type(), + Value: p.Prefix, + }) +} + +type flowSpecPrefix6 struct { + Prefix AddrPrefixInterface + Offset uint8 + typ BGPFlowSpecType +} + +// draft-ietf-idr-flow-spec-v6-06 +// +func (p *flowSpecPrefix6) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + p.typ = BGPFlowSpecType(data[0]) + p.Offset = data[2] + prefix := append([]byte{data[1]}, data[3:]...) + return p.Prefix.DecodeFromBytes(prefix, options...) +} + +func (p *flowSpecPrefix6) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := []byte{byte(p.Type())} + bbuf, err := p.Prefix.Serialize(options...) + if err != nil { + return nil, err + } + buf = append(buf, bbuf[0]) + buf = append(buf, p.Offset) + return append(buf, bbuf[1:]...), nil +} + +func (p *flowSpecPrefix6) Len(options ...*MarshallingOption) int { + buf, _ := p.Serialize(options...) + return len(buf) +} + +func (p *flowSpecPrefix6) Type() BGPFlowSpecType { + return p.typ +} + +func (p *flowSpecPrefix6) String() string { + return fmt.Sprintf("[%s: %s/%d]", p.Type(), p.Prefix.String(), p.Offset) +} + +func (p *flowSpecPrefix6) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPFlowSpecType `json:"type"` + Value AddrPrefixInterface `json:"value"` + Offset uint8 `json:"offset"` + }{ + Type: p.Type(), + Value: p.Prefix, + Offset: p.Offset, + }) +} + +type FlowSpecDestinationPrefix struct { + flowSpecPrefix +} + +func NewFlowSpecDestinationPrefix(prefix AddrPrefixInterface) *FlowSpecDestinationPrefix { + return &FlowSpecDestinationPrefix{flowSpecPrefix{prefix, FLOW_SPEC_TYPE_DST_PREFIX}} +} + +type FlowSpecSourcePrefix struct { + flowSpecPrefix +} + +func NewFlowSpecSourcePrefix(prefix AddrPrefixInterface) *FlowSpecSourcePrefix { + return &FlowSpecSourcePrefix{flowSpecPrefix{prefix, FLOW_SPEC_TYPE_SRC_PREFIX}} +} + +type FlowSpecDestinationPrefix6 struct { + flowSpecPrefix6 +} + +func NewFlowSpecDestinationPrefix6(prefix AddrPrefixInterface, offset uint8) *FlowSpecDestinationPrefix6 { + return &FlowSpecDestinationPrefix6{flowSpecPrefix6{prefix, offset, FLOW_SPEC_TYPE_DST_PREFIX}} +} + +type FlowSpecSourcePrefix6 struct { + flowSpecPrefix6 +} + +func NewFlowSpecSourcePrefix6(prefix AddrPrefixInterface, offset uint8) *FlowSpecSourcePrefix6 { + return &FlowSpecSourcePrefix6{flowSpecPrefix6{prefix, offset, FLOW_SPEC_TYPE_SRC_PREFIX}} +} + +type flowSpecMac struct { + Mac net.HardwareAddr + typ BGPFlowSpecType +} + +func (p *flowSpecMac) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if len(data) < 2 || len(data) < 2+int(data[1]) { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all mac bits available") + } + p.typ = BGPFlowSpecType(data[0]) + p.Mac = net.HardwareAddr(data[2 : 2+int(data[1])]) + return nil +} + +func (p *flowSpecMac) Serialize(options ...*MarshallingOption) ([]byte, error) { + if len(p.Mac) == 0 { + return nil, errors.New("mac unset") + } + buf := make([]byte, 2+len(p.Mac)) + buf[0] = byte(p.Type()) + buf[1] = byte(len(p.Mac)) + copy(buf[2:], p.Mac) + return buf, nil +} + +func (p *flowSpecMac) Len(options ...*MarshallingOption) int { + return 2 + len(p.Mac) +} + +func (p *flowSpecMac) Type() BGPFlowSpecType { + return p.typ +} + +func (p *flowSpecMac) String() string { + return fmt.Sprintf("[%s: %s]", p.Type(), p.Mac.String()) +} + +func (p *flowSpecMac) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPFlowSpecType `json:"type"` + Value string `json:"value"` + }{ + Type: p.Type(), + Value: p.Mac.String(), + }) +} + +type FlowSpecSourceMac struct { + flowSpecMac +} + +func NewFlowSpecSourceMac(mac net.HardwareAddr) *FlowSpecSourceMac { + return &FlowSpecSourceMac{flowSpecMac{Mac: mac, typ: FLOW_SPEC_TYPE_SRC_MAC}} +} + +type FlowSpecDestinationMac struct { + flowSpecMac +} + +func NewFlowSpecDestinationMac(mac net.HardwareAddr) *FlowSpecDestinationMac { + return &FlowSpecDestinationMac{flowSpecMac{Mac: mac, typ: FLOW_SPEC_TYPE_DST_MAC}} +} + +type FlowSpecComponentItem struct { + Op uint8 `json:"op"` + Value uint64 `json:"value"` +} + +func (v *FlowSpecComponentItem) Len() int { + return 1 << ((uint32(v.Op) >> 4) & 0x3) +} + +func (v *FlowSpecComponentItem) Serialize() ([]byte, error) { + order := uint32(math.Log2(float64(v.Len()))) + buf := make([]byte, 1+(1< 3 { + return nil + } + v.Op = uint8(uint32(v.Op) | order<<4) + return v +} + +type FlowSpecComponent struct { + Items []*FlowSpecComponentItem + typ BGPFlowSpecType +} + +func (p *FlowSpecComponent) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + p.typ = BGPFlowSpecType(data[0]) + data = data[1:] + p.Items = make([]*FlowSpecComponentItem, 0) + for { + if len(data) < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all flowspec component bytes available") + } + op := data[0] + end := op & 0x80 + l := 1 << ((op >> 4) & 0x3) // (min, max) = (1, 8) + v := make([]byte, 8) + copy(v[8-l:], data[1:1+l]) + i := binary.BigEndian.Uint64(v) + item := &FlowSpecComponentItem{op, i} + p.Items = append(p.Items, item) + if end > 0 { + break + } + data = data[1+l:] + } + return nil +} + +func (p *FlowSpecComponent) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := []byte{byte(p.Type())} + for _, v := range p.Items { + bbuf, err := v.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, bbuf...) + } + return buf, nil +} + +func (p *FlowSpecComponent) Len(options ...*MarshallingOption) int { + l := 1 + for _, item := range p.Items { + l += item.Len() + 1 + } + return l +} + +func (p *FlowSpecComponent) Type() BGPFlowSpecType { + return p.typ +} + +func formatRaw(op uint8, value uint64) string { + return fmt.Sprintf("op:%b,value:%d", op, value) +} + +func formatNumeric(op uint8, value uint64) string { + cmpFlag := DECNumOp(op & 0x7) // lower 3 bits + if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE { + // Omit value field + return DECNumOp(op).String() + } + return DECNumOp(op).String() + strconv.FormatUint(value, 10) +} + +func formatProto(op uint8, value uint64) string { + cmpFlag := DECNumOp(op & 0x7) // lower 3 bits + if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE { + // Omit value field + return DECNumOp(op).String() + } + return DECNumOp(op).String() + Protocol(value).String() +} + +func formatTCPFlag(op uint8, value uint64) string { + return BitmaskFlagOp(op).String() + TCPFlag(value).String() +} + +func formatFragment(op uint8, value uint64) string { + return BitmaskFlagOp(op).String() + FragmentFlag(value).String() +} + +func formatEtherType(op uint8, value uint64) string { + cmpFlag := DECNumOp(op & 0x7) // lower 3 bits + if cmpFlag == DEC_NUM_OP_TRUE || cmpFlag == DEC_NUM_OP_FALSE { + // Omit value field + return DECNumOp(op).String() + } + return DECNumOp(op).String() + EthernetType(value).String() +} + +var flowSpecFormatMap = map[BGPFlowSpecType]func(op uint8, value uint64) string{ + FLOW_SPEC_TYPE_UNKNOWN: formatRaw, + FLOW_SPEC_TYPE_IP_PROTO: formatProto, + FLOW_SPEC_TYPE_PORT: formatNumeric, + FLOW_SPEC_TYPE_DST_PORT: formatNumeric, + FLOW_SPEC_TYPE_SRC_PORT: formatNumeric, + FLOW_SPEC_TYPE_ICMP_TYPE: formatNumeric, + FLOW_SPEC_TYPE_ICMP_CODE: formatNumeric, + FLOW_SPEC_TYPE_TCP_FLAG: formatTCPFlag, + FLOW_SPEC_TYPE_PKT_LEN: formatNumeric, + FLOW_SPEC_TYPE_DSCP: formatNumeric, + FLOW_SPEC_TYPE_FRAGMENT: formatFragment, + FLOW_SPEC_TYPE_LABEL: formatNumeric, + FLOW_SPEC_TYPE_ETHERNET_TYPE: formatEtherType, + FLOW_SPEC_TYPE_LLC_DSAP: formatNumeric, + FLOW_SPEC_TYPE_LLC_SSAP: formatNumeric, + FLOW_SPEC_TYPE_LLC_CONTROL: formatNumeric, + FLOW_SPEC_TYPE_SNAP: formatNumeric, + FLOW_SPEC_TYPE_VID: formatNumeric, + FLOW_SPEC_TYPE_COS: formatNumeric, + FLOW_SPEC_TYPE_INNER_VID: formatNumeric, + FLOW_SPEC_TYPE_INNER_COS: formatNumeric, +} + +func (p *FlowSpecComponent) String() string { + f := flowSpecFormatMap[FLOW_SPEC_TYPE_UNKNOWN] + if _, ok := flowSpecFormatMap[p.typ]; ok { + f = flowSpecFormatMap[p.typ] + } + + items := make([]string, 0, len(p.Items)) + for _, i := range p.Items { + items = append(items, f(i.Op, i.Value)) + } + // Removes leading and tailing spaces + value := strings.TrimSpace(strings.Join(items, "")) + + return fmt.Sprintf("[%s: %s]", p.typ, value) +} + +func (p *FlowSpecComponent) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPFlowSpecType `json:"type"` + Value []*FlowSpecComponentItem `json:"value"` + }{ + Type: p.Type(), + Value: p.Items, + }) +} + +func NewFlowSpecComponent(typ BGPFlowSpecType, items []*FlowSpecComponentItem) *FlowSpecComponent { + // Set end-of-list bit on the last item and unset them on the others. + for i, v := range items { + if i == len(items)-1 { + v.Op |= 0x80 + } else { + v.Op &^= 0x80 + } + + } + return &FlowSpecComponent{ + Items: items, + typ: typ, + } +} + +type FlowSpecUnknown struct { + Value []byte +} + +func (p *FlowSpecUnknown) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + p.Value = data + return nil +} + +func (p *FlowSpecUnknown) Serialize(options ...*MarshallingOption) ([]byte, error) { + return p.Value, nil +} + +func (p *FlowSpecUnknown) Len(options ...*MarshallingOption) int { + return len(p.Value) +} + +func (p *FlowSpecUnknown) Type() BGPFlowSpecType { + if len(p.Value) > 0 { + return BGPFlowSpecType(p.Value[0]) + } + return FLOW_SPEC_TYPE_UNKNOWN +} + +func (p *FlowSpecUnknown) String() string { + return fmt.Sprintf("[unknown:%v]", p.Value) +} + +func (p *FlowSpecUnknown) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPFlowSpecType `json:"type"` + Value string `json:"value"` + }{ + Type: p.Type(), + Value: string(p.Value), + }) +} + +type FlowSpecNLRI struct { + PrefixDefault + Value []FlowSpecComponentInterface + rf RouteFamily + rd RouteDistinguisherInterface +} + +func (n *FlowSpecNLRI) AFI() uint16 { + afi, _ := RouteFamilyToAfiSafi(n.rf) + return afi +} + +func (n *FlowSpecNLRI) SAFI() uint8 { + _, safi := RouteFamilyToAfiSafi(n.rf) + return safi +} + +func (n *FlowSpecNLRI) RD() RouteDistinguisherInterface { + return n.rd +} + +func (n *FlowSpecNLRI) decodeFromBytes(rf RouteFamily, data []byte, options ...*MarshallingOption) error { + if IsAddPathEnabled(true, rf, options) { + var err error + data, err = n.decodePathIdentifier(data) + if err != nil { + return err + } + } + var length int + if (data[0]>>4) == 0xf && len(data) > 2 { + length = int(binary.BigEndian.Uint16(data[0:2])) + data = data[2:] + } else if len(data) > 1 { + length = int(data[0]) + data = data[1:] + } else { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all flowspec component bytes available") + } + if len(data) < length { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all flowspec component bytes available") + } + + n.rf = rf + + if n.SAFI() == SAFI_FLOW_SPEC_VPN { + if length < 8 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all flowspec component bytes available") + } + n.rd = GetRouteDistinguisher(data[:8]) + data = data[8:] + length -= 8 + } + + for l := length; l > 0; { + if len(data) == 0 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all flowspec component bytes available") + } + t := BGPFlowSpecType(data[0]) + var i FlowSpecComponentInterface + switch t { + case FLOW_SPEC_TYPE_DST_PREFIX: + switch { + case rf>>16 == AFI_IP: + i = NewFlowSpecDestinationPrefix(NewIPAddrPrefix(0, "")) + case rf>>16 == AFI_IP6: + i = NewFlowSpecDestinationPrefix6(NewIPv6AddrPrefix(0, ""), 0) + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid address family: %v", rf)) + } + case FLOW_SPEC_TYPE_SRC_PREFIX: + switch { + case rf>>16 == AFI_IP: + i = NewFlowSpecSourcePrefix(NewIPAddrPrefix(0, "")) + case rf>>16 == AFI_IP6: + i = NewFlowSpecSourcePrefix6(NewIPv6AddrPrefix(0, ""), 0) + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid address family: %v", rf)) + } + case FLOW_SPEC_TYPE_SRC_MAC: + switch rf { + case RF_FS_L2_VPN: + i = NewFlowSpecSourceMac(nil) + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid address family: %v", rf)) + } + case FLOW_SPEC_TYPE_DST_MAC: + switch rf { + case RF_FS_L2_VPN: + i = NewFlowSpecDestinationMac(nil) + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid address family: %v", rf)) + } + case FLOW_SPEC_TYPE_IP_PROTO, FLOW_SPEC_TYPE_PORT, FLOW_SPEC_TYPE_DST_PORT, FLOW_SPEC_TYPE_SRC_PORT, + FLOW_SPEC_TYPE_ICMP_TYPE, FLOW_SPEC_TYPE_ICMP_CODE, FLOW_SPEC_TYPE_TCP_FLAG, FLOW_SPEC_TYPE_PKT_LEN, + FLOW_SPEC_TYPE_DSCP, FLOW_SPEC_TYPE_FRAGMENT, FLOW_SPEC_TYPE_LABEL, FLOW_SPEC_TYPE_ETHERNET_TYPE, + FLOW_SPEC_TYPE_LLC_DSAP, FLOW_SPEC_TYPE_LLC_SSAP, FLOW_SPEC_TYPE_LLC_CONTROL, FLOW_SPEC_TYPE_SNAP, + FLOW_SPEC_TYPE_VID, FLOW_SPEC_TYPE_COS, FLOW_SPEC_TYPE_INNER_VID, FLOW_SPEC_TYPE_INNER_COS: + i = NewFlowSpecComponent(t, nil) + default: + i = &FlowSpecUnknown{} + } + + err := i.DecodeFromBytes(data, options...) + if err != nil { + i = &FlowSpecUnknown{data} + } + l -= i.Len(options...) + data = data[i.Len(options...):] + n.Value = append(n.Value, i) + } + + // Sort Traffic Filtering Rules in types order to avoid the unordered rules + // are determined different. + sort.SliceStable(n.Value, func(i, j int) bool { return n.Value[i].Type() < n.Value[j].Type() }) + + return nil +} + +func (n *FlowSpecNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 0, 32) + if n.SAFI() == SAFI_FLOW_SPEC_VPN { + if n.rd == nil { + return nil, errors.New("RD is nil") + } + b, err := n.rd.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, b...) + } + for _, v := range n.Value { + b, err := v.Serialize(options...) + if err != nil { + return nil, err + } + buf = append(buf, b...) + } + length := n.Len(options...) + if length > 0xfff { + return nil, fmt.Errorf("too large: %d", length) + } else if length < 0xf0 { + length -= 1 + buf = append([]byte{byte(length)}, buf...) + } else { + length -= 2 + b := make([]byte, 2) + binary.BigEndian.PutUint16(buf, uint16(length)) + buf = append(b, buf...) + } + + if IsAddPathEnabled(false, n.rf, options) { + id, err := n.serializeIdentifier() + if err != nil { + return nil, err + } + return append(id, buf...), nil + } + return buf, nil +} + +func (n *FlowSpecNLRI) Len(options ...*MarshallingOption) int { + l := 0 + if n.SAFI() == SAFI_FLOW_SPEC_VPN { + l += n.RD().Len() + } + for _, v := range n.Value { + l += v.Len(options...) + } + if l < 0xf0 { + return l + 1 + } else { + return l + 2 + } +} + +func (n *FlowSpecNLRI) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + if n.SAFI() == SAFI_FLOW_SPEC_VPN { + buf.WriteString(fmt.Sprintf("[rd: %s]", n.rd)) + } + for _, v := range n.Value { + buf.WriteString(v.String()) + } + return buf.String() +} + +func (n *FlowSpecNLRI) MarshalJSON() ([]byte, error) { + if n.rd != nil { + return json.Marshal(struct { + RD RouteDistinguisherInterface `json:"rd"` + Value []FlowSpecComponentInterface `json:"value"` + }{ + RD: n.rd, + Value: n.Value, + }) + } + return json.Marshal(struct { + Value []FlowSpecComponentInterface `json:"value"` + }{ + Value: n.Value, + }) + +} + +// CompareFlowSpecNLRI(n, m) returns +// -1 when m has precedence +// +// 0 when n and m have same precedence +// 1 when n has precedence +func CompareFlowSpecNLRI(n, m *FlowSpecNLRI) (int, error) { + family := AfiSafiToRouteFamily(n.AFI(), n.SAFI()) + if family != AfiSafiToRouteFamily(m.AFI(), m.SAFI()) { + return 0, errors.New("address family mismatch") + } + longer := n.Value + shorter := m.Value + invert := 1 + if n.SAFI() == SAFI_FLOW_SPEC_VPN { + k, _ := n.Serialize() + l, _ := m.Serialize() + if result := bytes.Compare(k, l); result != 0 { + return result, nil + } + } + if len(n.Value) < len(m.Value) { + longer = m.Value + shorter = n.Value + invert = -1 + } + for idx, v := range longer { + if len(shorter) < idx+1 { + return invert, nil + } + w := shorter[idx] + if v.Type() < w.Type() { + return invert, nil + } else if v.Type() > w.Type() { + return invert * -1, nil + } else if v.Type() == FLOW_SPEC_TYPE_DST_PREFIX || v.Type() == FLOW_SPEC_TYPE_SRC_PREFIX { + // RFC5575 5.1 + // + // For IP prefix values (IP destination and source prefix) precedence is + // given to the lowest IP value of the common prefix length; if the + // common prefix is equal, then the most specific prefix has precedence. + var p, q *IPAddrPrefixDefault + var pCommon, qCommon uint64 + if n.AFI() == AFI_IP { + if v.Type() == FLOW_SPEC_TYPE_DST_PREFIX { + p = &v.(*FlowSpecDestinationPrefix).Prefix.(*IPAddrPrefix).IPAddrPrefixDefault + q = &w.(*FlowSpecDestinationPrefix).Prefix.(*IPAddrPrefix).IPAddrPrefixDefault + } else { + p = &v.(*FlowSpecSourcePrefix).Prefix.(*IPAddrPrefix).IPAddrPrefixDefault + q = &w.(*FlowSpecSourcePrefix).Prefix.(*IPAddrPrefix).IPAddrPrefixDefault + } + min := p.Length + if q.Length < p.Length { + min = q.Length + } + pCommon = uint64(binary.BigEndian.Uint32([]byte(p.Prefix.To4())) >> (32 - min)) + qCommon = uint64(binary.BigEndian.Uint32([]byte(q.Prefix.To4())) >> (32 - min)) + } else if n.AFI() == AFI_IP6 { + if v.Type() == FLOW_SPEC_TYPE_DST_PREFIX { + p = &v.(*FlowSpecDestinationPrefix6).Prefix.(*IPv6AddrPrefix).IPAddrPrefixDefault + q = &w.(*FlowSpecDestinationPrefix6).Prefix.(*IPv6AddrPrefix).IPAddrPrefixDefault + } else { + p = &v.(*FlowSpecSourcePrefix6).Prefix.(*IPv6AddrPrefix).IPAddrPrefixDefault + q = &w.(*FlowSpecSourcePrefix6).Prefix.(*IPv6AddrPrefix).IPAddrPrefixDefault + } + min := uint(p.Length) + if q.Length < p.Length { + min = uint(q.Length) + } + var mask uint + if min-64 > 0 { + mask = min - 64 + } + pCommon = binary.BigEndian.Uint64([]byte(p.Prefix.To16()[:8])) >> mask + qCommon = binary.BigEndian.Uint64([]byte(q.Prefix.To16()[:8])) >> mask + if pCommon == qCommon && mask == 0 { + mask = 64 - min + pCommon = binary.BigEndian.Uint64([]byte(p.Prefix.To16()[8:])) >> mask + qCommon = binary.BigEndian.Uint64([]byte(q.Prefix.To16()[8:])) >> mask + } + } + + if pCommon < qCommon { + return invert, nil + } else if pCommon > qCommon { + return invert * -1, nil + } else if p.Length > q.Length { + return invert, nil + } else if p.Length < q.Length { + return invert * -1, nil + } + + } else { + // RFC5575 5.1 + // + // For all other component types, unless otherwise specified, the + // comparison is performed by comparing the component data as a binary + // string using the memcmp() function as defined by the ISO C standard. + // For strings of different lengths, the common prefix is compared. If + // equal, the longest string is considered to have higher precedence + // than the shorter one. + p, _ := v.Serialize() + q, _ := w.Serialize() + min := len(p) + if len(q) < len(p) { + min = len(q) + } + if result := bytes.Compare(p[:min], q[:min]); result < 0 { + return invert, nil + } else if result > 0 { + return invert * -1, nil + } else if len(p) > len(q) { + return invert, nil + } else if len(q) > len(p) { + return invert * -1, nil + } + } + } + return 0, nil +} + +type FlowSpecIPv4Unicast struct { + FlowSpecNLRI +} + +func (n *FlowSpecIPv4Unicast) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data, options...) +} + +func NewFlowSpecIPv4Unicast(value []FlowSpecComponentInterface) *FlowSpecIPv4Unicast { + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv4Unicast{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv4_UC, + }, + } +} + +type FlowSpecIPv4VPN struct { + FlowSpecNLRI +} + +func (n *FlowSpecIPv4VPN) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data, options...) +} + +func NewFlowSpecIPv4VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecIPv4VPN { + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv4VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv4_VPN, + rd: rd, + }, + } +} + +type FlowSpecIPv6Unicast struct { + FlowSpecNLRI +} + +func (n *FlowSpecIPv6Unicast) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data, options...) +} + +func NewFlowSpecIPv6Unicast(value []FlowSpecComponentInterface) *FlowSpecIPv6Unicast { + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv6Unicast{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv6_UC, + }, + } +} + +type FlowSpecIPv6VPN struct { + FlowSpecNLRI +} + +func (n *FlowSpecIPv6VPN) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data, options...) +} + +func NewFlowSpecIPv6VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecIPv6VPN { + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv6VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv6_VPN, + rd: rd, + }, + } +} + +type FlowSpecL2VPN struct { + FlowSpecNLRI +} + +func (n *FlowSpecL2VPN) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data) +} + +func NewFlowSpecL2VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecL2VPN { + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecL2VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_L2_VPN, + rd: rd, + }, + } +} + +type OpaqueNLRI struct { + PrefixDefault + Length uint16 + Key []byte + Value []byte +} + +func (n *OpaqueNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if len(data) < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all OpaqueNLRI bytes available") + } + if IsAddPathEnabled(true, RF_OPAQUE, options) { + var err error + data, err = n.decodePathIdentifier(data) + if err != nil { + return err + } + } + n.Length = binary.BigEndian.Uint16(data[0:2]) + if len(data)-2 < int(n.Length) { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all OpaqueNLRI bytes available") + } + n.Key = data[2 : 2+n.Length] + n.Value = data[2+n.Length:] + return nil +} + +func (n *OpaqueNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + keyLen := len(n.Key) + if keyLen > math.MaxUint16 { + return nil, errors.New("key length too big") + } + buf := make([]byte, 2, 2+keyLen+len(n.Value)) + binary.BigEndian.PutUint16(buf[:2], uint16(keyLen)) + buf = append(buf, n.Key...) + buf = append(buf, n.Value...) + if IsAddPathEnabled(false, RF_OPAQUE, options) { + id, err := n.serializeIdentifier() + if err != nil { + return nil, err + } + return append(id, buf...), nil + } + return buf, nil +} + +func (n *OpaqueNLRI) AFI() uint16 { + return AFI_OPAQUE +} + +func (n *OpaqueNLRI) SAFI() uint8 { + return SAFI_KEY_VALUE +} + +func (n *OpaqueNLRI) Len(options ...*MarshallingOption) int { + return 2 + len(n.Key) + len(n.Value) +} + +func (n *OpaqueNLRI) String() string { + return string(n.Key) +} + +func (n *OpaqueNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Key string `json:"key"` + Value string `json:"value"` + }{ + Key: string(n.Key), + Value: string(n.Value), + }) +} + +func NewOpaqueNLRI(key, value []byte) *OpaqueNLRI { + return &OpaqueNLRI{ + Key: key, + Value: value, + } +} + +type LsNLRIType uint16 + +const ( + LS_NLRI_TYPE_UNKNOWN LsNLRIType = iota + LS_NLRI_TYPE_NODE + LS_NLRI_TYPE_LINK + LS_NLRI_TYPE_PREFIX_IPV4 + LS_NLRI_TYPE_PREFIX_IPV6 +) + +type LsNLRIInterface interface { + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + Len() int + Type() LsNLRIType + String() string +} + +type LsProtocolID uint8 + +const ( + LS_PROTOCOL_UNKNOWN = iota + LS_PROTOCOL_ISIS_L1 + LS_PROTOCOL_ISIS_L2 + LS_PROTOCOL_OSPF_V2 + LS_PROTOCOL_DIRECT + LS_PROTOCOL_STATIC + LS_PROTOCOL_OSPF_V3 +) + +func (l LsProtocolID) String() string { + switch l { + case LS_PROTOCOL_ISIS_L1: + return "ISIS-L1" + case LS_PROTOCOL_ISIS_L2: + return "ISIS-L2" + case LS_PROTOCOL_OSPF_V2: + return "OSPFv2" + case LS_PROTOCOL_DIRECT: + return "DIRECT" + case LS_PROTOCOL_STATIC: + return "STATIC" + case LS_PROTOCOL_OSPF_V3: + return "OSPFv3" + default: + return fmt.Sprintf("LsProtocolID(%d)", uint8(l)) + } +} + +type LsNLRI struct { + NLRIType LsNLRIType + Length uint16 + ProtocolID LsProtocolID + Identifier uint64 +} + +const lsNLRIHdrLen = 9 + +func (l *LsNLRI) DecodeFromBytes(data []byte) error { + if len(data) < lsNLRIHdrLen { + return malformedAttrListErr("Malformed NLRI") + } + + l.ProtocolID = LsProtocolID(data[0]) + l.Identifier = binary.BigEndian.Uint64(data[1:lsNLRIHdrLen]) + + return nil +} + +func (l *LsNLRI) Serialize(value []byte) ([]byte, error) { + buf := make([]byte, lsNLRIHdrLen) + buf[0] = uint8(l.ProtocolID) + binary.BigEndian.PutUint64(buf[1:], l.Identifier) + buf = append(buf, value...) + + return buf, nil +} + +func (l *LsNLRI) Len() int { + return int(l.Length) +} + +func (l *LsNLRI) Type() LsNLRIType { + return l.NLRIType +} + +type LsNodeNLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface +} + +func (l *LsNodeNLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + if len(tlv) < tlvHdrLen { + return malformedAttrListErr("Malformed Node NLRI") + } + + tlvType := LsTLVType(binary.BigEndian.Uint16(tlv[:2])) + if tlvType != LS_TLV_LOCAL_NODE_DESC { + return malformedAttrListErr("Mandatory TLV missing") + } + + l.LocalNodeDesc = &LsTLVNodeDescriptor{} + if err := l.LocalNodeDesc.DecodeFromBytes(tlv); err != nil { + return malformedAttrListErr(fmt.Sprintf("Malformed Node NLRI: %v", err)) + } + + return nil +} + +func (l *LsNodeNLRI) String() string { + if l.LocalNodeDesc == nil { + return "NODE { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + return fmt.Sprintf("NODE { AS:%v BGP-LS ID:%v %v %v:%v }", local.Asn, local.BGPLsID, local.IGPRouterID, l.ProtocolID.String(), l.Identifier) +} + +func (l *LsNodeNLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, errors.New("local node descriptor missing") + } + ser, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + + return l.LsNLRI.Serialize(ser) +} + +func (l *LsNodeNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + }) +} + +type LsLinkDescriptor struct { + LinkLocalID *uint32 + LinkRemoteID *uint32 + InterfaceAddrIPv4 *net.IP + NeighborAddrIPv4 *net.IP + InterfaceAddrIPv6 *net.IP + NeighborAddrIPv6 *net.IP +} + +func (l *LsLinkDescriptor) ParseTLVs(tlvs []LsTLVInterface) { + for _, tlv := range tlvs { + switch v := tlv.(type) { + case *LsTLVLinkID: + l.LinkLocalID = &v.Local + l.LinkRemoteID = &v.Remote + + case *LsTLVIPv4InterfaceAddr: + l.InterfaceAddrIPv4 = &v.IP + + case *LsTLVIPv4NeighborAddr: + l.NeighborAddrIPv4 = &v.IP + + case *LsTLVIPv6InterfaceAddr: + l.InterfaceAddrIPv6 = &v.IP + + case *LsTLVIPv6NeighborAddr: + l.NeighborAddrIPv6 = &v.IP + } + } +} + +func (l *LsLinkDescriptor) String() string { + switch { + case l.InterfaceAddrIPv4 != nil && l.NeighborAddrIPv4 != nil: + return fmt.Sprintf("%v->%v", l.InterfaceAddrIPv4, l.NeighborAddrIPv4) + + case l.InterfaceAddrIPv6 != nil && l.NeighborAddrIPv6 != nil: + return fmt.Sprintf("%v->%v", l.InterfaceAddrIPv6, l.NeighborAddrIPv6) + + case l.LinkLocalID != nil && l.LinkRemoteID != nil: + return fmt.Sprintf("%v->%v", *l.LinkLocalID, *l.LinkRemoteID) + + case l.InterfaceAddrIPv4 != nil: + return fmt.Sprintf("%v->UNKNOWN", l.InterfaceAddrIPv4) + case l.NeighborAddrIPv4 != nil: + return fmt.Sprintf("UNKNOWN->%v", l.NeighborAddrIPv4) + + case l.InterfaceAddrIPv6 != nil: + return fmt.Sprintf("%v->UNKNOWN", l.InterfaceAddrIPv6) + case l.NeighborAddrIPv6 != nil: + return fmt.Sprintf("UNKNOWN->%v", l.NeighborAddrIPv6) + + case l.LinkLocalID != nil: + return fmt.Sprintf("%v->UNKNOWN", *l.LinkLocalID) + case l.LinkRemoteID != nil: + return fmt.Sprintf("UNKNOWN->%v", *l.LinkRemoteID) + + default: + return "UNKNOWN" + } +} + +type LsLinkNLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + RemoteNodeDesc LsTLVInterface + LinkDesc []LsTLVInterface +} + +func (l *LsLinkNLRI) String() string { + if l.LocalNodeDesc == nil || l.RemoteNodeDesc == nil { + return "LINK { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + remote := l.RemoteNodeDesc.(*LsTLVNodeDescriptor).Extract() + link := &LsLinkDescriptor{} + link.ParseTLVs(l.LinkDesc) + + return fmt.Sprintf("LINK { LOCAL_NODE: %v REMOTE_NODE: %v LINK: %v}", local.IGPRouterID, remote.IGPRouterID, link) +} + +func (l *LsLinkNLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC, LS_TLV_REMOTE_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_LINK_ID: + subTLV = &LsTLVLinkID{} + case LS_TLV_IPV4_INTERFACE_ADDR: + subTLV = &LsTLVIPv4InterfaceAddr{} + case LS_TLV_IPV4_NEIGHBOR_ADDR: + subTLV = &LsTLVIPv4NeighborAddr{} + case LS_TLV_IPV6_INTERFACE_ADDR: + subTLV = &LsTLVIPv6InterfaceAddr{} + case LS_TLV_IPV6_NEIGHBOR_ADDR: + subTLV = &LsTLVIPv6NeighborAddr{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + case LS_TLV_REMOTE_NODE_DESC: + l.RemoteNodeDesc = subTLV + default: + l.LinkDesc = append(l.LinkDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_LOCAL_NODE_DESC, LS_TLV_REMOTE_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + return nil +} + +func (l *LsLinkNLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil || l.RemoteNodeDesc == nil { + return nil, errors.New("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + s, err = l.RemoteNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.LinkDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsLinkNLRI) MarshalJSON() ([]byte, error) { + linkDesc := &LsLinkDescriptor{} + linkDesc.ParseTLVs(l.LinkDesc) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + RemoteNode LsNodeDescriptor `json:"remote_node_desc"` + LinkDesc LsLinkDescriptor `json:"link_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + RemoteNode: *l.RemoteNodeDesc.(*LsTLVNodeDescriptor).Extract(), + LinkDesc: *linkDesc, + }) +} + +type LsPrefixDescriptor struct { + IPReachability []net.IPNet + OSPFRouteType LsOspfRouteType +} + +func (l *LsPrefixDescriptor) ParseTLVs(tlvs []LsTLVInterface, ipv6 bool) { + for _, tlv := range tlvs { + switch v := tlv.(type) { + case *LsTLVIPReachability: + l.IPReachability = append(l.IPReachability, v.ToIPNet(ipv6)) + + case *LsTLVOspfRouteType: + l.OSPFRouteType = v.RouteType + } + } +} + +type LsPrefixV4NLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + PrefixDesc []LsTLVInterface +} + +func (l *LsPrefixV4NLRI) String() string { + if l.LocalNodeDesc == nil { + return "PREFIXv4 { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + prefix := &LsPrefixDescriptor{} + prefix.ParseTLVs(l.PrefixDesc, false) + ips := make([]string, len(prefix.IPReachability)) + for i, ip := range prefix.IPReachability { + ips[i] = ip.String() + } + + ospf := "" + if prefix.OSPFRouteType != LS_OSPF_ROUTE_TYPE_UNKNOWN { + ospf = fmt.Sprintf("OSPF_ROUTE_TYPE:%v ", prefix.OSPFRouteType) + } + + return fmt.Sprintf("PREFIXv4 { LOCAL_NODE: %s PREFIX: %v %s}", local.IGPRouterID, ips, ospf) +} + +func (l *LsPrefixV4NLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_OSPF_ROUTE_TYPE: + subTLV = &LsTLVOspfRouteType{} + case LS_TLV_IP_REACH_INFO: + subTLV = &LsTLVIPReachability{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + default: + l.PrefixDesc = append(l.PrefixDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_IP_REACH_INFO, LS_TLV_LOCAL_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + for _, tlv := range l.PrefixDesc { + switch v := tlv.(type) { + case *LsTLVIPReachability: + if v.PrefixLength > 8*net.IPv4len { + return malformedAttrListErr("Unexpected IP Reachability info") + } + } + } + + return nil +} + +func (l *LsPrefixV4NLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, errors.New("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.PrefixDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsPrefixV4NLRI) MarshalJSON() ([]byte, error) { + prefixDesc := &LsPrefixDescriptor{} + prefixDesc.ParseTLVs(l.PrefixDesc, false) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + PrefixDesc LsPrefixDescriptor `json:"prefix_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + PrefixDesc: *prefixDesc, + }) +} + +type LsPrefixV6NLRI struct { + LsNLRI + LocalNodeDesc LsTLVInterface + PrefixDesc []LsTLVInterface +} + +func (l *LsPrefixV6NLRI) String() string { + if l.LocalNodeDesc == nil { + return "PREFIXv6 { EMPTY }" + } + + local := l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract() + prefix := &LsPrefixDescriptor{} + prefix.ParseTLVs(l.PrefixDesc, true) + ips := []string{} + for _, ip := range prefix.IPReachability { + ips = append(ips, ip.String()) + } + + ospf := "" + if prefix.OSPFRouteType != LS_OSPF_ROUTE_TYPE_UNKNOWN { + ospf = fmt.Sprintf("OSPF_ROUTE_TYPE:%v ", prefix.OSPFRouteType) + } + + return fmt.Sprintf("PREFIXv6 { LOCAL_NODE: %v PREFIX: %v %v}", local.IGPRouterID, ips, ospf) +} + +func (l *LsPrefixV6NLRI) DecodeFromBytes(data []byte) error { + if err := l.LsNLRI.DecodeFromBytes(data); err != nil { + return nil + } + + tlv := data[lsNLRIHdrLen:] + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + subTLV = &LsTLVNodeDescriptor{} + case LS_TLV_OSPF_ROUTE_TYPE: + subTLV = &LsTLVOspfRouteType{} + case LS_TLV_IP_REACH_INFO: + subTLV = &LsTLVIPReachability{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + tlv = tlv[subTLV.Len():] + + switch sub.Type { + case LS_TLV_LOCAL_NODE_DESC: + l.LocalNodeDesc = subTLV + default: + l.PrefixDesc = append(l.PrefixDesc, subTLV) + } + } + + required := []LsTLVType{LS_TLV_IP_REACH_INFO, LS_TLV_LOCAL_NODE_DESC} + for _, tlv := range required { + if _, ok := m[tlv]; !ok { + return malformedAttrListErr("Required TLV missing") + } + } + + return nil +} + +func (l *LsPrefixV6NLRI) Serialize() ([]byte, error) { + if l.LocalNodeDesc == nil { + return nil, errors.New("required TLV missing") + } + + buf := make([]byte, 0) + s, err := l.LocalNodeDesc.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + + for _, tlv := range l.PrefixDesc { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return l.LsNLRI.Serialize(buf) +} + +func (l *LsPrefixV6NLRI) MarshalJSON() ([]byte, error) { + prefixDesc := &LsPrefixDescriptor{} + prefixDesc.ParseTLVs(l.PrefixDesc, true) + + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + LocalNode LsNodeDescriptor `json:"local_node_desc"` + PrefixDesc LsPrefixDescriptor `json:"prefix_desc"` + }{ + Type: l.Type(), + LocalNode: *l.LocalNodeDesc.(*LsTLVNodeDescriptor).Extract(), + PrefixDesc: *prefixDesc, + }) +} + +type LsTLVType uint16 + +// Based on https://www.iana.org/assignments/bgp-ls-parameters/bgp-ls-parameters.xhtml +const ( + LS_TLV_UNKNOWN LsTLVType = iota + + LS_TLV_LOCAL_NODE_DESC = 256 + LS_TLV_REMOTE_NODE_DESC = 257 + LS_TLV_LINK_ID = 258 + LS_TLV_IPV4_INTERFACE_ADDR = 259 + LS_TLV_IPV4_NEIGHBOR_ADDR = 260 + LS_TLV_IPV6_INTERFACE_ADDR = 261 + LS_TLV_IPV6_NEIGHBOR_ADDR = 262 + LS_TLV_MULTI_TOPO_ID = 263 + LS_TLV_OSPF_ROUTE_TYPE = 264 + LS_TLV_IP_REACH_INFO = 265 + + LS_TLV_AS = 512 + LS_TLV_BGP_LS_ID = 513 + LS_TLV_OSPF_AREA = 514 + LS_TLV_IGP_ROUTER_ID = 515 + LS_TLV_BGP_ROUTER_ID = 516 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_BGP_CONFEDERATION_MEMBER = 517 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + + LS_TLV_NODE_FLAG_BITS = 1024 + LS_TLV_OPAQUE_NODE_ATTR = 1025 + LS_TLV_NODE_NAME = 1026 + LS_TLV_ISIS_AREA = 1027 + LS_TLV_IPV4_LOCAL_ROUTER_ID = 1028 + LS_TLV_IPV6_LOCAL_ROUTER_ID = 1029 + LS_TLV_IPV4_REMOTE_ROUTER_ID = 1030 + LS_TLV_IPV6_REMOTE_ROUTER_ID = 1031 + + LS_TLV_SR_CAPABILITIES = 1034 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SR_ALGORITHM = 1035 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SR_LOCAL_BLOCK = 1036 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_SRMS_PREFERENCE = 1037 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + + LS_TLV_ADMIN_GROUP = 1088 + LS_TLV_MAX_LINK_BANDWIDTH = 1089 + LS_TLV_MAX_RESERVABLE_BANDWIDTH = 1090 + LS_TLV_UNRESERVED_BANDWIDTH = 1091 + LS_TLV_TE_DEFAULT_METRIC = 1092 + LS_TLV_LINK_PROTECTION_TYPE = 1093 // TODO + LS_TLV_MPLS_PROTOCOL_MASK = 1094 // TODO + LS_TLV_IGP_METRIC = 1095 + LS_TLV_SRLG = 1096 + LS_TLV_OPAQUE_LINK_ATTR = 1097 + LS_TLV_LINK_NAME = 1098 + LS_TLV_ADJACENCY_SID = 1099 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_LAN_ADJACENCY_SID = 1100 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_PEER_NODE_SID = 1101 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_PEER_ADJACENCY_SID = 1102 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + LS_TLV_PEER_SET_SID = 1103 // draft-ietf-idr-bgpls-segment-routing-epe, TODO + + LS_TLV_RTM_CAPABILITY = 1105 // RFC8169, TODO + + LS_TLV_IGP_FLAGS = 1152 + LS_TLV_IGP_ROUTE_TAG = 1153 // TODO + LS_TLV_EXTENDED_ROUTE_TAG = 1154 // TODO + LS_TLV_PREFIX_METRIC = 1155 // TODO + LS_TLV_OSPF_FORWARDING_ADDR = 1156 // TODO + LS_TLV_OPAQUE_PREFIX_ATTR = 1157 + LS_TLV_PREFIX_SID = 1158 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_RANGE = 1159 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_SID_LABEL_TLV = 1161 // draft-ietf-idr-bgp-ls-segment-routing-ext + LS_TLV_PREFIX_ATTRIBUTE_FLAGS = 1170 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_SOURCE_ROUTER_ID = 1171 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO + LS_TLV_L2_BUNDLE_MEMBER_TLV = 1172 // draft-ietf-idr-bgp-ls-segment-routing-ext, TODO +) + +type LsTLVInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + MarshalJSON() ([]byte, error) +} + +type LsTLV struct { + Type LsTLVType + Length uint16 +} + +func malformedAttrListErr(s string) error { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, s) +} + +const tlvHdrLen = 4 + +func (l *LsTLV) Len() int { + return int(l.Length) + tlvHdrLen +} + +func (l *LsTLV) Serialize(value []byte) ([]byte, error) { + if len(value) != int(l.Length) { + return nil, malformedAttrListErr("serialization failed: LS TLV malformed") + } + + buf := make([]byte, tlvHdrLen+len(value)) + binary.BigEndian.PutUint16(buf[:2], uint16(l.Type)) + binary.BigEndian.PutUint16(buf[2:4], uint16(l.Length)) + copy(buf[4:], value) + + return buf, nil +} + +func (l *LsTLV) DecodeFromBytes(data []byte) ([]byte, error) { + if len(data) < tlvHdrLen { + return nil, malformedAttrListErr("decoding failed: LS TLV malformed") + } + l.Type = LsTLVType(binary.BigEndian.Uint16(data[:2])) + l.Length = binary.BigEndian.Uint16(data[2:4]) + + if len(data) < l.Len() { + return nil, malformedAttrListErr("decoding failed: LS TLV malformed") + } + + return data[tlvHdrLen:l.Len()], nil +} + +type LsTLVLinkID struct { + LsTLV + Local uint32 + Remote uint32 +} + +func (l *LsTLVLinkID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LINK_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5307#section-1.1 + if len(value) != 8 { + return malformedAttrListErr("Incorrect Link ID length") + } + + l.Local = binary.BigEndian.Uint32(value[:4]) + l.Remote = binary.BigEndian.Uint32(value[4:]) + + return nil +} + +func (l *LsTLVLinkID) Serialize() ([]byte, error) { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[:4], l.Local) + binary.BigEndian.PutUint32(buf[4:], l.Remote) + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVLinkID) String() string { + return fmt.Sprintf("{Link ID Remote: %v Local: %v}", l.Local, l.Remote) +} + +func (l *LsTLVLinkID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Local uint32 `json:"local_link_id"` + Remote uint32 `json:"remote_link_id"` + }{ + Type: l.Type, + Local: l.Local, + Remote: l.Remote, + }) +} + +type LsTLVIPv4InterfaceAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv4InterfaceAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_INTERFACE_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.2 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVIPv4InterfaceAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv4InterfaceAddr) String() string { + return fmt.Sprintf("{IPv4 Interface Address: %v}", l.IP) +} + +func (l *LsTLVIPv4InterfaceAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv4_interface_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv4NeighborAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv4NeighborAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_NEIGHBOR_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVIPv4NeighborAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv4NeighborAddr) String() string { + return fmt.Sprintf("{IPv4 Neighbor Address: %v}", l.IP) +} + +func (l *LsTLVIPv4NeighborAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv4_neighbor_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv6InterfaceAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv6InterfaceAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_INTERFACE_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.2 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + if l.IP.IsLinkLocalUnicast() { + return malformedAttrListErr("Unexpected link local address") + } + + return nil +} + +func (l *LsTLVIPv6InterfaceAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv6InterfaceAddr) String() string { + return fmt.Sprintf("{IPv6 Interface Address: %v}", l.IP) +} + +func (l *LsTLVIPv6InterfaceAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv6_interface_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVIPv6NeighborAddr struct { + LsTLV + IP net.IP +} + +func (l *LsTLVIPv6NeighborAddr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_NEIGHBOR_ADDR { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.3 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + if l.IP.IsLinkLocalUnicast() { + return malformedAttrListErr("Unexpected link local address") + } + + return nil +} + +func (l *LsTLVIPv6NeighborAddr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVIPv6NeighborAddr) String() string { + return fmt.Sprintf("{IPv6 Neighbor Address: %v}", l.IP) +} + +func (l *LsTLVIPv6NeighborAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"ipv6_neighbor_address"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +// https://tools.ietf.org/html/rfc7752#section-3.3.1.1 +type LsNodeFlags struct { + Overload bool `json:"overload"` + Attached bool `json:"attached"` + External bool `json:"external"` + ABR bool `json:"abr"` + Router bool `json:"router"` + V6 bool `json:"v6"` +} + +type LsTLVNodeFlagBits struct { + LsTLV + Flags uint8 +} + +func (l *LsTLVNodeFlagBits) Extract() *LsNodeFlags { + return &LsNodeFlags{ + Overload: (l.Flags & (1 << 7)) > 0, + Attached: (l.Flags & (1 << 6)) > 0, + External: (l.Flags & (1 << 5)) > 0, + ABR: (l.Flags & (1 << 4)) > 0, + Router: (l.Flags & (1 << 3)) > 0, + V6: (l.Flags & (1 << 2)) > 0, + } +} + +func (l *LsTLVNodeFlagBits) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_NODE_FLAG_BITS { + return malformedAttrListErr("Unexpected TLV type") + } + + if l.Length != 1 { + return malformedAttrListErr("Node Flag Bits TLV malformed") + } + + l.Flags = value[0] + + return nil +} + +func (l *LsTLVNodeFlagBits) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte{l.Flags}) +} + +func (l *LsTLVNodeFlagBits) String() string { + flags := "XXVRBETO" + + var buf bytes.Buffer + + for i := 0; i < len(flags); i++ { + if l.Flags&(1< 0 { + buf.WriteString(flags[i : i+1]) + } else { + buf.WriteString("*") + } + } + + return fmt.Sprintf("{Node Flags: %s}", buf.String()) +} + +func (l *LsTLVNodeFlagBits) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags string `json:"node_flags"` + }{ + Type: l.Type, + Flags: l.String(), + }) +} + +type LsTLVNodeName struct { + LsTLV + Name string +} + +func (l *LsTLVNodeName) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_NODE_NAME { + return malformedAttrListErr("Unexpected TLV type") + } + + // RFC5301, section 3. + if l.Length < 1 || l.Length > 255 { + return malformedAttrListErr("Incorrect Node Name") + } + + l.Name = string(value) + + return nil +} + +func (l *LsTLVNodeName) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte(l.Name)) +} + +func (l *LsTLVNodeName) String() string { + return fmt.Sprintf("{Node Name: %s}", l.Name) +} + +func (l *LsTLVNodeName) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Name string `json:"node_name"` + }{ + Type: l.Type, + Name: l.Name, + }) +} + +type LsTLVIsisArea struct { + LsTLV + Area []byte +} + +func (l *LsTLVIsisArea) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ISIS_AREA { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 1 || len(value) > 13 { + return malformedAttrListErr("Incorrect ISIS Area size") + } + + l.Area = value + + return nil +} + +func (l *LsTLVIsisArea) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Area) +} + +func (l *LsTLVIsisArea) String() string { + return fmt.Sprintf("{ISIS Area ID: %v}", l.Area) +} + +func (l *LsTLVIsisArea) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Area string `json:"isis_area_id"` + }{ + Type: l.Type, + Area: fmt.Sprintf("%v", l.Area), + }) +} + +type LsTLVLocalIPv4RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVLocalIPv4RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_LOCAL_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-4.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVLocalIPv4RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVLocalIPv4RouterID) String() string { + return fmt.Sprintf("{Local RouterID IPv4: %v}", l.IP) +} + +func (l *LsTLVLocalIPv4RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_local_router_id_ipv4"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVRemoteIPv4RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVRemoteIPv4RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV4_REMOTE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-4.3 + if len(value) != 4 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVRemoteIPv4RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVRemoteIPv4RouterID) String() string { + return fmt.Sprintf("{Remote RouterID IPv4: %v}", l.IP) +} + +func (l *LsTLVRemoteIPv4RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_remote_router_id_ipv4"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVLocalIPv6RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVLocalIPv6RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_LOCAL_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.1 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVLocalIPv6RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVLocalIPv6RouterID) String() string { + return fmt.Sprintf("{Local RouterID IPv6: %v}", l.IP) +} + +func (l *LsTLVLocalIPv6RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_local_router_id_ipv6"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVRemoteIPv6RouterID struct { + LsTLV + IP net.IP +} + +func (l *LsTLVRemoteIPv6RouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IPV6_REMOTE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc6119#section-4.1 + if len(value) != 16 { + return malformedAttrListErr("Unexpected address size") + } + + l.IP = net.IP(value) + + return nil +} + +func (l *LsTLVRemoteIPv6RouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.IP) +} + +func (l *LsTLVRemoteIPv6RouterID) String() string { + return fmt.Sprintf("{Remote RouterID IPv6: %v}", l.IP) +} + +func (l *LsTLVRemoteIPv6RouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_remote_router_id_ipv6"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.IP), + }) +} + +type LsTLVOpaqueNodeAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaqueNodeAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_NODE_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaqueNodeAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaqueNodeAttr) String() string { + return fmt.Sprintf("{Opaque attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaqueNodeAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"node_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVAutonomousSystem struct { + LsTLV + ASN uint32 +} + +func (l *LsTLVAutonomousSystem) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_AS { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect AS length") + } + + l.ASN = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVAutonomousSystem) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.ASN) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVAutonomousSystem) String() string { + return fmt.Sprintf("{ASN: %d}", l.ASN) +} + +func (l *LsTLVAutonomousSystem) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + ASN uint32 `json:"asn"` + }{ + Type: l.Type, + ASN: l.ASN, + }) +} + +type LsTLVBgpLsID struct { + LsTLV + BGPLsID uint32 +} + +func (l *LsTLVBgpLsID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_BGP_LS_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect BGP-LS ID length") + } + + l.BGPLsID = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVBgpLsID) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.BGPLsID) + + return l.LsTLV.Serialize(buf[:4]) +} + +func (l *LsTLVBgpLsID) String() string { + return fmt.Sprintf("{BGP LS ID: %d}", l.BGPLsID) +} + +func (l *LsTLVBgpLsID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + BgpLsID uint32 `json:"bgp_ls_id"` + }{ + Type: l.Type, + BgpLsID: l.BGPLsID, + }) +} + +type LsTLVIgpRouterID struct { + LsTLV + RouterID []byte +} + +func (l *LsTLVIgpRouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + // 4, 6, 7, and 8 are the only valid values. + switch len(value) { + case 4, 6, 7, 8: + break + default: + return malformedAttrListErr(fmt.Sprintf("Incorrect IGP Router ID length: %d", len(value))) + } + + l.RouterID = value + + return nil +} + +func (l *LsTLVIgpRouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.RouterID) +} + +func (l *LsTLVIgpRouterID) String() string { + return fmt.Sprintf("{IGP Router ID: %v}", l.RouterID) +} + +func (l *LsTLVIgpRouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouterID string `json:"igp_router_id"` + }{ + Type: l.Type, + RouterID: fmt.Sprintf("%v", l.RouterID), + }) +} + +type LsTLVOspfAreaID struct { + LsTLV + AreaID uint32 +} + +func (l *LsTLVOspfAreaID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OSPF_AREA { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.1.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect OSPF Area ID length") + } + + l.AreaID = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVOspfAreaID) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.AreaID) + + return l.LsTLV.Serialize(buf[:4]) +} + +func (l *LsTLVOspfAreaID) String() string { + return fmt.Sprintf("{OSPF Area ID: %d}", l.AreaID) +} + +func (l *LsTLVOspfAreaID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + AreaID uint32 `json:"ospf_area_id"` + }{ + Type: l.Type, + AreaID: l.AreaID, + }) +} + +type LsOspfRouteType uint8 + +const ( + LS_OSPF_ROUTE_TYPE_UNKNOWN = iota + LS_OSPF_ROUTE_TYPE_INTRA_AREA + LS_OSPF_ROUTE_TYPE_INTER_AREA + LS_OSPF_ROUTE_TYPE_EXTERNAL1 + LS_OSPF_ROUTE_TYPE_EXTERNAL2 + LS_OSPF_ROUTE_TYPE_NSSA1 + LS_OSPF_ROUTE_TYPE_NSSA2 +) + +func (l LsOspfRouteType) String() string { + switch l { + case LS_OSPF_ROUTE_TYPE_INTRA_AREA: + return "INTRA-AREA" + case LS_OSPF_ROUTE_TYPE_INTER_AREA: + return "INTER-AREA" + case LS_OSPF_ROUTE_TYPE_EXTERNAL1: + return "EXTERNAL1" + case LS_OSPF_ROUTE_TYPE_EXTERNAL2: + return "EXTERNAL2" + case LS_OSPF_ROUTE_TYPE_NSSA1: + return "NSSA1" + case LS_OSPF_ROUTE_TYPE_NSSA2: + return "NSSA2" + default: + return fmt.Sprintf("LsOspfRouteType(%d)", uint8(l)) + } +} + +type LsTLVOspfRouteType struct { + LsTLV + RouteType LsOspfRouteType +} + +func (l *LsTLVOspfRouteType) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OSPF_ROUTE_TYPE { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.3.1 + if len(value) != 1 { + return malformedAttrListErr("Incorrect OSPF Route type length") + } + + if value[0] < byte(LS_OSPF_ROUTE_TYPE_INTRA_AREA) || value[0] > LS_OSPF_ROUTE_TYPE_NSSA2 { + return malformedAttrListErr("Incorrect OSPF Route type") + } + + l.RouteType = LsOspfRouteType(value[0]) + + return nil +} + +func (l *LsTLVOspfRouteType) Serialize() ([]byte, error) { + var buf [1]byte + buf[0] = byte(l.RouteType) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVOspfRouteType) String() string { + return fmt.Sprintf("{OSPF Route Type: %v}", l.RouteType) +} + +func (l *LsTLVOspfRouteType) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouteType string `json:"ospf_route_type"` + }{ + Type: l.Type, + RouteType: l.RouteType.String(), + }) +} + +type LsTLVIPReachability struct { + LsTLV + PrefixLength uint8 + Prefix []byte +} + +func (l *LsTLVIPReachability) ToIPNet(ipv6 bool) net.IPNet { + b := make([]byte, 16) + for i := 0; i < int(((l.PrefixLength-1)/8)+1); i++ { + b[i] = l.Prefix[i] + } + + ip := net.IPv4(b[0], b[1], b[2], b[3]).To4() + if ipv6 { + ip = net.IP(b).To16() + } + + _, n, err := net.ParseCIDR(fmt.Sprintf("%v/%v", ip, l.PrefixLength)) + if err != nil { + return net.IPNet{} + } + + return *n +} + +func (l *LsTLVIPReachability) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IP_REACH_INFO { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect IP reachability Info length") + } + + // https://tools.ietf.org/html/rfc7752#section-3.2.3.2 + if value[0] > 128 || value[0] == 0 { + return malformedAttrListErr("Incorrect IP prefix length") + } + + ll := int(((value[0] - 1) / 8) + 1) + if len(value[1:]) != ll { + return malformedAttrListErr("Malformed IP reachability TLV") + } + + l.PrefixLength = value[0] + l.Prefix = value[1 : 1+ll] + + return nil +} + +func (l *LsTLVIPReachability) Serialize() ([]byte, error) { + b := []byte{l.PrefixLength} + + return l.LsTLV.Serialize(append(b, l.Prefix...)) +} + +func (l *LsTLVIPReachability) String() string { + return fmt.Sprintf("{IP Reachability: %v/%v}", l.Prefix, l.PrefixLength) +} + +func (l *LsTLVIPReachability) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + PrefixLength uint8 `json:"prefix_length"` + Prefix string `json:"prefix"` + }{ + Type: l.Type, + PrefixLength: l.PrefixLength, + Prefix: fmt.Sprintf("%v", l.Prefix), + }) +} + +type LsTLVAdminGroup struct { + LsTLV + AdminGroup uint32 +} + +func (l *LsTLVAdminGroup) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ADMIN_GROUP { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.1 + if len(value) != 4 { + return malformedAttrListErr("Incorrect Admin Group length") + } + + l.AdminGroup = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVAdminGroup) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.AdminGroup) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVAdminGroup) String() string { + return fmt.Sprintf("{Admin Group: %08x}", l.AdminGroup) +} + +func (l *LsTLVAdminGroup) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + AdminGroup string `json:"admin_group"` + }{ + Type: l.Type, + AdminGroup: fmt.Sprintf("%08x", l.AdminGroup), + }) +} + +type LsTLVMaxLinkBw struct { + LsTLV + Bandwidth float32 +} + +func (l *LsTLVMaxLinkBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_MAX_LINK_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.4 + if len(value) != 4 { + return malformedAttrListErr("Incorrect maximum link bandwidth length") + } + + l.Bandwidth = math.Float32frombits(binary.BigEndian.Uint32(value)) + + if l.Bandwidth < 0 || math.IsNaN(float64(l.Bandwidth)) || math.IsInf(float64(l.Bandwidth), 0) { + return malformedAttrListErr("Incorrect maximum link bandwidth value") + } + + return nil +} + +func (l *LsTLVMaxLinkBw) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], math.Float32bits(l.Bandwidth)) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVMaxLinkBw) String() string { + return fmt.Sprintf("{Max Link BW: %v}", l.Bandwidth) +} + +func (l *LsTLVMaxLinkBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth float32 `json:"max_link_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVMaxReservableLinkBw struct { + LsTLV + Bandwidth float32 +} + +func (l *LsTLVMaxReservableLinkBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_MAX_RESERVABLE_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.5 + if len(value) != 4 { + return malformedAttrListErr("Incorrect maximum reservable link bandwidth length") + } + + l.Bandwidth = math.Float32frombits(binary.BigEndian.Uint32(value)) + + if l.Bandwidth < 0 || math.IsNaN(float64(l.Bandwidth)) || math.IsInf(float64(l.Bandwidth), 0) { + return malformedAttrListErr("Incorrect maximum reservable link bandwidth value") + } + + return nil +} + +func (l *LsTLVMaxReservableLinkBw) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], math.Float32bits(l.Bandwidth)) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVMaxReservableLinkBw) String() string { + return fmt.Sprintf("{Max Reservable Link BW: %v}", l.Bandwidth) +} + +func (l *LsTLVMaxReservableLinkBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth float32 `json:"max_reservable_link_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVUnreservedBw struct { + LsTLV + Bandwidth [8]float32 +} + +func (l *LsTLVUnreservedBw) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_UNRESERVED_BANDWIDTH { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc5305#section-3.6 + if len(value) != 32 { + return malformedAttrListErr("Incorrect unreserved bandwidth length") + } + + for i := 0; i < len(l.Bandwidth); i++ { + l.Bandwidth[i] = math.Float32frombits(binary.BigEndian.Uint32(value[:4])) + value = value[4:] + + if l.Bandwidth[i] < 0 || math.IsNaN(float64(l.Bandwidth[i])) || math.IsInf(float64(l.Bandwidth[i]), 0) { + return malformedAttrListErr("Incorrect unreserved bandwidth value") + } + } + + return nil +} + +func (l *LsTLVUnreservedBw) Serialize() ([]byte, error) { + buf := make([]byte, 0, 4*len(l.Bandwidth)) + + var b [4]byte + for i := 0; i < len(l.Bandwidth); i++ { + binary.BigEndian.PutUint32(b[:4], math.Float32bits(l.Bandwidth[i])) + buf = append(buf, b[:]...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVUnreservedBw) String() string { + return fmt.Sprintf("{Unreserved BW: %v}", l.Bandwidth) +} + +func (l *LsTLVUnreservedBw) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Bandwidth [8]float32 `json:"unreserved_bw"` + }{ + Type: l.Type, + Bandwidth: l.Bandwidth, + }) +} + +type LsTLVTEDefaultMetric struct { + LsTLV + Metric uint32 +} + +func (l *LsTLVTEDefaultMetric) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_TE_DEFAULT_METRIC { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.3 + if len(value) != 4 { + return malformedAttrListErr("Incorrect metric length length") + } + + l.Metric = binary.BigEndian.Uint32(value) + + return nil +} + +func (l *LsTLVTEDefaultMetric) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.Metric) + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVTEDefaultMetric) String() string { + return fmt.Sprintf("{TE Default metric: %d}", l.Metric) +} + +func (l *LsTLVTEDefaultMetric) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + DefaultMetric uint32 `json:"te_default_metric"` + }{ + Type: l.Type, + DefaultMetric: l.Metric, + }) +} + +type LsTLVIGPMetric struct { + LsTLV + Metric uint32 +} + +func (l *LsTLVIGPMetric) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_METRIC { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.4 + switch len(value) { + case 1: + l.Metric = uint32(value[0] & 0x3F) + + case 2: + l.Metric = uint32(binary.BigEndian.Uint16(value)) + + case 3: + l.Metric = binary.BigEndian.Uint32([]byte{0, value[0], value[1], value[2]}) + + default: + return malformedAttrListErr("Incorrect metric length") + } + + return nil +} + +func (l *LsTLVIGPMetric) Serialize() ([]byte, error) { + switch l.Length { + case 1: + return l.LsTLV.Serialize([]byte{uint8(l.Metric) & 0x3F}) + + case 2: + var buf [2]byte + binary.BigEndian.PutUint16(buf[:2], uint16(l.Metric)) + return l.LsTLV.Serialize(buf[:]) + + case 3: + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.Metric) + return l.LsTLV.Serialize(buf[1:]) + + default: + return nil, malformedAttrListErr("Incorrect metric length") + } +} + +func (l *LsTLVIGPMetric) String() string { + return fmt.Sprintf("{IGP metric: %d}", l.Metric) +} + +func (l *LsTLVIGPMetric) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Metric uint32 `json:"igp_metric"` + }{ + Type: l.Type, + Metric: l.Metric, + }) +} + +type LsTLVLinkName struct { + LsTLV + Name string +} + +func (l *LsTLVLinkName) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LINK_NAME { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/rfc7752#section-3.3.2.7 + if len(value) < 1 || len(value) > 255 { + return malformedAttrListErr("Incorrect Link Name") + } + + l.Name = string(value) + + return nil +} + +func (l *LsTLVLinkName) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte(l.Name)) +} + +func (l *LsTLVLinkName) String() string { + return fmt.Sprintf("{Link Name: %s}", l.Name) +} + +func (l *LsTLVLinkName) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Name string `json:"link_name"` + }{ + Type: l.Type, + Name: l.Name, + }) +} + +type LsTLVSrAlgorithm struct { + LsTLV + Algorithm []byte +} + +func (l *LsTLVSrAlgorithm) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_ALGORITHM { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 1 { + return malformedAttrListErr("Incorrect SR algorithm length") + } + + l.Algorithm = value + + return nil +} + +func (l *LsTLVSrAlgorithm) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Algorithm) +} + +func (l *LsTLVSrAlgorithm) String() string { + return fmt.Sprintf("{SR Algorithms: %v}", l.Algorithm) +} + +func (l *LsTLVSrAlgorithm) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Algorithms string `json:"sr_algorithm"` + }{ + Type: l.Type, + Algorithms: fmt.Sprintf("%v", l.Algorithm), + }) +} + +type LsSrLabelRange struct { + Range uint32 + FirstLabel LsTLVSIDLabel +} + +type LsTLVSrCapabilities struct { + LsTLV + Flags uint8 + Ranges []LsSrLabelRange +} + +type LsSrRange struct { + Begin uint32 `json:"begin"` + End uint32 `json:"end"` +} + +type LsSrCapabilities struct { + IPv4Supported bool `json:"ipv4_supported"` + IPv6Supported bool `json:"ipv6_supported"` + Ranges []LsSrRange `json:"ranges"` +} + +func (l *LsTLVSrCapabilities) Extract() *LsSrCapabilities { + lsc := &LsSrCapabilities{ + IPv4Supported: (l.Flags & (1 << 0)) > 0, + IPv6Supported: (l.Flags & (1 << 1)) > 0, + } + + for _, r := range l.Ranges { + lsc.Ranges = append(lsc.Ranges, LsSrRange{ + Begin: r.FirstLabel.SID, + End: r.FirstLabel.SID + r.Range, + }) + } + + return lsc +} + +func (l *LsTLVSrCapabilities) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_CAPABILITIES { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect SR Capabilities length") + } + l.Flags = value[0] + + // Skip two bytes: flags and reserved. + value = value[2:] + + // The value field should be at least eight bytes long. Three bytes + // for the range size and five or six bytes for the SID/Label TLV. + for len(value) > 8 { + // First, parse range size (3 bytes) + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + r := binary.BigEndian.Uint32(buf) + value = value[3:] + + // Second, parse SID/Label sub-TLV. + label := LsTLVSIDLabel{} + if err := label.DecodeFromBytes(value); err != nil { + return err + } + + l.Ranges = append(l.Ranges, LsSrLabelRange{ + Range: r, + FirstLabel: label, + }) + + value = value[label.Len():] + } + + if len(value) > 0 { + return malformedAttrListErr("Malformed SR Capabilities TLV") + } + + return nil +} + +func (l *LsTLVSrCapabilities) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, 0) + var b [4]byte + + for _, r := range l.Ranges { + binary.BigEndian.PutUint32(b[:4], r.Range) + buf = append(buf, b[1:]...) + ser, err := r.FirstLabel.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSrCapabilities) String() string { + var buf bytes.Buffer + + for _, r := range l.Ranges { + buf.WriteString(fmt.Sprintf("%v:%v ", r.FirstLabel.SID, r.FirstLabel.SID+r.Range)) + } + + return fmt.Sprintf("{SR Capabilities: Flags:%v SRGB Ranges: %v}", l.Flags, buf.String()) +} + +func (l *LsTLVSrCapabilities) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags uint8 `json:"flags"` + Ranges []LsSrLabelRange `json:"ranges"` + }{ + Type: l.Type, + Flags: l.Flags, + Ranges: l.Ranges, + }) +} + +type LsTLVSrLocalBlock struct { + LsTLV + Flags uint8 + Ranges []LsSrLabelRange +} + +type LsSrLocalBlock struct { + Ranges []LsSrRange `json:"ranges"` +} + +func (l *LsTLVSrLocalBlock) Extract() *LsSrLocalBlock { + lb := &LsSrLocalBlock{} + + for _, r := range l.Ranges { + lb.Ranges = append(lb.Ranges, LsSrRange{ + Begin: r.FirstLabel.SID, + End: r.FirstLabel.SID + r.Range, + }) + } + + return lb +} + +func (l *LsTLVSrLocalBlock) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SR_LOCAL_BLOCK { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value) < 2 { + return malformedAttrListErr("Incorrect SR Local Block length") + } + l.Flags = value[0] + + // Skip two bytes: flags and reserved. + value = value[2:] + + // The value field should be at least eight bytes long. Three bytes + // for the range size and five or six bytes for the SID/Label TLV. + for len(value) > 8 { + // First, parse range size (3 bytes) + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + r := binary.BigEndian.Uint32(buf) + value = value[3:] + + // Second, parse SID/Label sub-TLV. + label := LsTLVSIDLabel{} + if err := label.DecodeFromBytes(value); err != nil { + return err + } + + l.Ranges = append(l.Ranges, LsSrLabelRange{ + Range: r, + FirstLabel: label, + }) + + value = value[label.Len():] + } + + if len(value) > 0 { + return malformedAttrListErr("Malformed SR Local Block TLV") + } + + return nil +} + +func (l *LsTLVSrLocalBlock) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, 0) + var b [4]byte + + for _, r := range l.Ranges { + binary.BigEndian.PutUint32(b[:4], r.Range) + buf = append(buf, b[1:]...) + ser, err := r.FirstLabel.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSrLocalBlock) String() string { + var buf bytes.Buffer + + for _, r := range l.Ranges { + buf.WriteString(fmt.Sprintf("%v:%v ", r.FirstLabel.SID, r.FirstLabel.SID+r.Range)) + } + + return fmt.Sprintf("{SR LocalBlock: Flags:%v SRGB Ranges: %v}", l.Flags, buf.String()) +} + +func (l *LsTLVSrLocalBlock) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags uint8 `json:"flags"` + Ranges []LsSrLabelRange `json:"ranges"` + }{ + Type: l.Type, + Flags: l.Flags, + Ranges: l.Ranges, + }) +} + +type LsTLVAdjacencySID struct { + LsTLV + Flags uint8 + Weight uint8 + SID uint32 +} + +func (l *LsTLVAdjacencySID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_ADJACENCY_SID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.2.1 + if len(value) != 7 && len(value) != 8 { + return malformedAttrListErr("Incorrect Adjacency SID length") + } + + l.Flags = value[0] + l.Weight = value[1] + + v := value[4:] + if len(v) == 4 { + l.SID = binary.BigEndian.Uint32(v) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = v[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVAdjacencySID) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, l.Weight) + // Reserved + buf = append(buf, []byte{0, 0}...) + + var b [4]byte + binary.BigEndian.PutUint32(b[:4], l.SID) + + if l.Length == 7 { + return l.LsTLV.Serialize(append(buf, b[1:]...)) + } + + return l.LsTLV.Serialize(append(buf, b[:]...)) +} + +func (l *LsTLVAdjacencySID) String() string { + return fmt.Sprintf("{Adjacency SID: %v}", l.SID) +} + +func (l *LsTLVAdjacencySID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"adjacency_sid"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVSIDLabel struct { + LsTLV + SID uint32 +} + +func (l *LsTLVSIDLabel) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SID_LABEL_TLV { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.1.1 + if len(value) != 4 && len(value) != 3 { + return malformedAttrListErr("Incorrect SID length") + } + + if len(value) == 4 { + l.SID = binary.BigEndian.Uint32(value) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = value[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVSIDLabel) Serialize() ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], l.SID) + + if l.Length == 3 { + return l.LsTLV.Serialize(buf[1:]) + } + + return l.LsTLV.Serialize(buf[:]) +} + +func (l *LsTLVSIDLabel) String() string { + return fmt.Sprintf("{SID/Label: %v}", l.SID) +} + +func (l *LsTLVSIDLabel) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"sid_label"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVPrefixSID struct { + LsTLV + Flags uint8 + Algorithm uint8 + SID uint32 +} + +func (l *LsTLVPrefixSID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_PREFIX_SID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.3.1 + if len(value) != 7 && len(value) != 8 { + return malformedAttrListErr("Incorrect Prefix SID length") + } + + l.Flags = value[0] + l.Algorithm = value[1] + + // Flags (1) + Algorithm (1) + Reserved (2) + v := value[4:] + if len(v) == 4 { + l.SID = binary.BigEndian.Uint32(v) + } else { + buf := []byte{0, 0, 0, 0} + for i := 1; i < len(buf); i++ { + buf[i] = v[i-1] + } + // Label is represented by 20 rightmost bits. + l.SID = binary.BigEndian.Uint32(buf) & 0xfffff + } + + return nil +} + +func (l *LsTLVPrefixSID) Serialize() ([]byte, error) { + buf := make([]byte, 0) + buf = append(buf, l.Flags) + buf = append(buf, l.Algorithm) + // Reserved + buf = append(buf, []byte{0, 0}...) + + var b [4]byte + binary.BigEndian.PutUint32(b[:4], l.SID) + + if l.Length == 7 { + return l.LsTLV.Serialize(append(buf, b[1:]...)) + } + + return l.LsTLV.Serialize(append(buf, b[:]...)) +} + +func (l *LsTLVPrefixSID) String() string { + return fmt.Sprintf("{Prefix SID: %v}", l.SID) +} + +func (l *LsTLVPrefixSID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + SID uint32 `json:"prefix_sid"` + }{ + Type: l.Type, + SID: l.SID, + }) +} + +type LsTLVSourceRouterID struct { + LsTLV + RouterID []byte +} + +func (l *LsTLVSourceRouterID) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SOURCE_ROUTER_ID { + return malformedAttrListErr("Unexpected TLV type") + } + + // https://tools.ietf.org/html/draft-ietf-idr-bgp-ls-segment-routing-ext-08#section-2.3.3 + if len(value) != 4 && len(value) != 16 { + return malformedAttrListErr("Incorrect Source Router ID length") + } + + l.RouterID = value + + return nil +} + +func (l *LsTLVSourceRouterID) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.RouterID) +} + +func (l *LsTLVSourceRouterID) String() string { + return fmt.Sprintf("{Source Router ID: %v}", net.IP(l.RouterID)) +} + +func (l *LsTLVSourceRouterID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + RouterID string `json:"source_router_id"` + }{ + Type: l.Type, + RouterID: fmt.Sprintf("%v", net.IP(l.RouterID)), + }) +} + +type LsTLVOpaqueLinkAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaqueLinkAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_LINK_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaqueLinkAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaqueLinkAttr) String() string { + return fmt.Sprintf("{Opaque link attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaqueLinkAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"link_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVSrlg struct { + LsTLV + Srlgs []uint32 +} + +func (l *LsTLVSrlg) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_SRLG { + return malformedAttrListErr("Unexpected TLV type") + } + + if len(value)%4 != 0 { + return malformedAttrListErr("Incorrect SRLG length") + } + + for len(value) > 0 { + l.Srlgs = append(l.Srlgs, binary.BigEndian.Uint32(value[:4])) + value = value[4:] + } + + return nil +} + +func (l *LsTLVSrlg) Serialize() ([]byte, error) { + buf := make([]byte, 0, 4*len(l.Srlgs)) + + var b [4]byte + for i := 0; i < len(l.Srlgs); i++ { + binary.BigEndian.PutUint32(b[:4], l.Srlgs[i]) + buf = append(buf, b[:]...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVSrlg) String() string { + return fmt.Sprintf("{SRLG link attribute: %d}", l.Srlgs) +} + +func (l *LsTLVSrlg) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value []uint32 `json:"link_srlg_attribute"` + }{ + Type: l.Type, + Value: l.Srlgs, + }) +} + +type LsTLVIGPFlags struct { + LsTLV + Flags uint8 +} + +// https://tools.ietf.org/html/rfc7752#section-3.3.3.1 +type LsIGPFlags struct { + Down bool `json:"down"` + NoUnicast bool `json:"no_unicast"` + LocalAddress bool `json:"local_address"` + PropagateNSSA bool `json:"propagate_nssa"` +} + +func (l *LsTLVIGPFlags) Extract() *LsIGPFlags { + return &LsIGPFlags{ + Down: (l.Flags & (1 << 0)) > 0, + NoUnicast: (l.Flags & (1 << 1)) > 0, + LocalAddress: (l.Flags & (1 << 2)) > 0, + PropagateNSSA: (l.Flags & (1 << 3)) > 0, + } +} + +func (l *LsTLVIGPFlags) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_IGP_FLAGS { + return malformedAttrListErr("Unexpected TLV type") + } + + if l.Length != 1 { + return malformedAttrListErr("Node Flag Bits TLV malformed") + } + + l.Flags = value[0] + + return nil +} + +func (l *LsTLVIGPFlags) Serialize() ([]byte, error) { + return l.LsTLV.Serialize([]byte{l.Flags}) +} + +func (l *LsTLVIGPFlags) String() string { + flags := "XXXXPLND" + + var buf bytes.Buffer + + for i := 0; i < len(flags); i++ { + if l.Flags&(1< 0 { + buf.WriteString(flags[i : i+1]) + } else { + buf.WriteString("*") + } + } + + return fmt.Sprintf("{IGP Flags: %s}", buf.String()) +} + +func (l *LsTLVIGPFlags) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Flags string `json:"igp_flags"` + }{ + Type: l.Type, + Flags: l.String(), + }) +} + +type LsTLVOpaquePrefixAttr struct { + LsTLV + Attr []byte +} + +func (l *LsTLVOpaquePrefixAttr) DecodeFromBytes(data []byte) error { + value, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_OPAQUE_PREFIX_ATTR { + return malformedAttrListErr("Unexpected TLV type") + } + + l.Attr = value + + return nil +} + +func (l *LsTLVOpaquePrefixAttr) Serialize() ([]byte, error) { + return l.LsTLV.Serialize(l.Attr) +} + +func (l *LsTLVOpaquePrefixAttr) String() string { + return fmt.Sprintf("{Prefix opaque attribute: %v}", l.Attr) +} + +func (l *LsTLVOpaquePrefixAttr) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + Value string `json:"prefix_opaque_attribute"` + }{ + Type: l.Type, + Value: fmt.Sprintf("%v", l.Attr), + }) +} + +type LsTLVNodeDescriptor struct { + LsTLV + SubTLVs []LsTLVInterface +} + +func (l *LsTLVNodeDescriptor) DecodeFromBytes(data []byte) error { + tlv, err := l.LsTLV.DecodeFromBytes(data) + if err != nil { + return err + } + + if l.Type != LS_TLV_LOCAL_NODE_DESC && l.Type != LS_TLV_REMOTE_NODE_DESC { + return malformedAttrListErr("Unexpected TLV type") + } + + // RFC7752, 3.2.1.4 + // There can be at most one instance of each sub-TLV type present in + // any Node Descriptor. The sub-TLVs within a Node Descriptor MUST + // be arranged in ascending order by sub-TLV type. + prevType := uint16(0) + m := make(map[LsTLVType]bool) + + for len(tlv) >= tlvHdrLen { + sub := &LsTLV{} + _, err := sub.DecodeFromBytes(tlv) + if err != nil { + return err + } + + if uint16(sub.Type) < prevType { + return malformedAttrListErr("Incorrect TLV order") + } + if _, ok := m[sub.Type]; ok { + return malformedAttrListErr("Duplicate TLV") + } + prevType = uint16(sub.Type) + m[sub.Type] = true + + var subTLV LsTLVInterface + switch sub.Type { + case LS_TLV_AS: + subTLV = &LsTLVAutonomousSystem{} + case LS_TLV_BGP_LS_ID: + subTLV = &LsTLVBgpLsID{} + case LS_TLV_OSPF_AREA: + subTLV = &LsTLVOspfAreaID{} + case LS_TLV_IGP_ROUTER_ID: + subTLV = &LsTLVIgpRouterID{} + + default: + tlv = tlv[sub.Len():] + l.Length -= uint16(sub.Len()) + continue + } + + if err := subTLV.DecodeFromBytes(tlv); err != nil { + return err + } + l.SubTLVs = append(l.SubTLVs, subTLV) + tlv = tlv[subTLV.Len():] + } + + if _, ok := m[LS_TLV_IGP_ROUTER_ID]; !ok { + return malformedAttrListErr("Required TLV missing") + } + + return nil +} + +func (l *LsTLVNodeDescriptor) Serialize() ([]byte, error) { + buf := []byte{} + for _, tlv := range l.SubTLVs { + ser, err := tlv.Serialize() + if err != nil { + return nil, err + } + + buf = append(buf, ser...) + } + + return l.LsTLV.Serialize(buf) +} + +func (l *LsTLVNodeDescriptor) String() string { + nd := l.Extract() + + return fmt.Sprintf("{ASN: %v, BGP LS ID: %v, OSPF AREA: %v, IGP ROUTER ID: %v}", nd.Asn, nd.BGPLsID, nd.OspfAreaID, nd.IGPRouterID) +} + +func (l *LsTLVNodeDescriptor) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsTLVType `json:"type"` + LsNodeDescriptor + }{ + l.Type, + *l.Extract(), + }) +} + +type LsNodeDescriptor struct { + Asn uint32 `json:"asn"` + BGPLsID uint32 `json:"bgp_ls_id"` + OspfAreaID uint32 `json:"ospf_area_id"` + PseudoNode bool `json:"pseudo_node"` + IGPRouterID string `json:"igp_router_id"` +} + +func parseIGPRouterID(id []byte) (string, bool) { + switch len(id) { + // OSPF or OSPFv3 non-pseudonode + case 4: + return net.IP(id).String(), false + + // ISIS non-pseudonode + case 6: + return fmt.Sprintf("%0.2x%0.2x.%0.2x%0.2x.%0.2x%0.2x", id[0], id[1], id[2], id[3], id[4], id[5]), false + + // ISIS pseudonode + case 7: + return fmt.Sprintf("%0.2x%0.2x.%0.2x%0.2x.%0.2x%0.2x-%0.2x", id[0], id[1], id[2], id[3], id[4], id[5], id[6]), true + + // OSPF or OSPFv3 pseudonode + case 8: + return fmt.Sprintf("%v:%v", net.IP(id[:4]).String(), net.IP(id[4:]).String()), true + + default: + return fmt.Sprintf("%v", id), false + } +} + +func (l *LsTLVNodeDescriptor) Extract() *LsNodeDescriptor { + nd := &LsNodeDescriptor{} + + for _, tlv := range l.SubTLVs { + switch v := tlv.(type) { + case *LsTLVAutonomousSystem: + nd.Asn = v.ASN + case *LsTLVBgpLsID: + nd.BGPLsID = v.BGPLsID + case *LsTLVOspfAreaID: + nd.OspfAreaID = v.AreaID + case *LsTLVIgpRouterID: + nd.IGPRouterID, nd.PseudoNode = parseIGPRouterID(v.RouterID) + } + } + + return nd +} + +type LsAddrPrefix struct { + PrefixDefault + Type LsNLRIType + Length uint16 + NLRI LsNLRIInterface +} + +func (l *LsAddrPrefix) AFI() uint16 { + return AFI_LS +} + +func (l *LsAddrPrefix) SAFI() uint8 { + return SAFI_LS +} + +func (l *LsAddrPrefix) Len(...*MarshallingOption) int { + return int(4 + l.Length) +} + +func (l *LsAddrPrefix) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + if len(data) < 4 { + return malformedAttrListErr("Malformed BGP-LS Address Prefix") + } + + l.Type = LsNLRIType(binary.BigEndian.Uint16(data[:2])) + l.Length = binary.BigEndian.Uint16(data[2:4]) + + switch l.Type { + case LS_NLRI_TYPE_NODE: + node := &LsNodeNLRI{} + node.Length = l.Length + node.NLRIType = LS_NLRI_TYPE_NODE + l.NLRI = node + + case LS_NLRI_TYPE_LINK: + link := &LsLinkNLRI{} + link.Length = l.Length + link.NLRIType = LS_NLRI_TYPE_LINK + l.NLRI = link + + case LS_NLRI_TYPE_PREFIX_IPV4: + prefixv4 := &LsPrefixV4NLRI{} + prefixv4.Length = l.Length + prefixv4.NLRIType = LS_NLRI_TYPE_PREFIX_IPV4 + l.NLRI = prefixv4 + + case LS_NLRI_TYPE_PREFIX_IPV6: + prefixv6 := &LsPrefixV6NLRI{} + prefixv6.Length = l.Length + prefixv6.NLRIType = LS_NLRI_TYPE_PREFIX_IPV4 + l.NLRI = prefixv6 + + default: + return malformedAttrListErr("Unsupported BGP-LS NLRI") + } + + if l.NLRI != nil { + return l.NLRI.DecodeFromBytes(data[4:]) + } + + return nil +} + +func (l *LsAddrPrefix) Serialize(options ...*MarshallingOption) ([]byte, error) { + if l.NLRI == nil { + return nil, errors.New("empty NLRI") + } + + ser, err := l.NLRI.Serialize() + if err != nil { + return nil, err + } + + buf := make([]byte, 4+len(ser)) + binary.BigEndian.PutUint16(buf[:2], uint16(l.Type)) + binary.BigEndian.PutUint16(buf[2:], l.Length) + copy(buf[4:], ser) + + return buf, nil +} + +func (l *LsAddrPrefix) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type LsNLRIType `json:"type"` + Length uint16 `json:"length"` + NLRI string `json:"nlri"` + }{ + l.Type, + l.Length, + l.String(), + }) +} + +func (l *LsAddrPrefix) String() string { + if l.NLRI == nil { + return "NLRI: (nil)" + } + + return fmt.Sprintf("NLRI { %s }", l.NLRI.String()) +} + +func (l *LsAddrPrefix) Flat() map[string]string { + return map[string]string{} +} + +type LsAttributeNode struct { + Flags *LsNodeFlags `json:"flags,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + Name *string `json:"name,omitempty"` + IsisArea *[]byte `json:"isis_area,omitempty"` + LocalRouterID *net.IP `json:"local_router_id_ipv4,omitempty"` + LocalRouterIDv6 *net.IP `json:"local_router_id_ipv6,omitempty"` + + // Segment Routing + SrCapabilties *LsSrCapabilities `json:"sr_capabilities,omitempty"` + SrAlgorithms *[]byte `json:"sr_algorithms,omitempty"` + SrLocalBlock *LsSrLocalBlock `json:"sr_local_block,omitempty"` +} + +type LsAttributeLink struct { + Name *string `json:"name,omitempty"` + LocalRouterID *net.IP `json:"local_router_id_ipv4,omitempty"` + LocalRouterIDv6 *net.IP `json:"local_router_id_ipv6,omitempty"` + RemoteRouterID *net.IP `json:"remote_router_id_ipv4,omitempty"` + RemoteRouterIDv6 *net.IP `json:"remote_router_id_ipv6,omitempty"` + AdminGroup *uint32 `json:"admin_group,omitempty"` + DefaultTEMetric *uint32 `json:"default_te_metric,omitempty"` + IGPMetric *uint32 `json:"igp_metric,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + + // Bandwidth is expressed in bytes (not bits) per second. + Bandwidth *float32 `json:"bandwidth,omitempty"` + ReservableBandwidth *float32 `json:"reservable_bandwidth,omitempty"` + UnreservedBandwidth *[8]float32 `json:"unreserved_bandwidth,omitempty"` + Srlgs *[]uint32 `json:"srlgs,omitempty"` + + SrAdjacencySID *uint32 `json:"adjacency_sid,omitempty"` +} + +type LsAttributePrefix struct { + IGPFlags *LsIGPFlags `json:"igp_flags,omitempty"` + Opaque *[]byte `json:"opaque,omitempty"` + + SrPrefixSID *uint32 `json:"sr_prefix_sid,omitempty"` +} + +type LsAttribute struct { + Node LsAttributeNode `json:"node"` + Link LsAttributeLink `json:"link"` + Prefix LsAttributePrefix `json:"prefix"` +} + +type PathAttributeLs struct { + PathAttribute + TLVs []LsTLVInterface +} + +func (p *PathAttributeLs) Extract() *LsAttribute { + l := &LsAttribute{} + + for _, tlv := range p.TLVs { + switch v := tlv.(type) { + case *LsTLVNodeFlagBits: + l.Node.Flags = v.Extract() + + case *LsTLVOpaqueNodeAttr: + l.Node.Opaque = &v.Attr + + case *LsTLVNodeName: + l.Node.Name = &v.Name + + case *LsTLVIsisArea: + l.Node.IsisArea = &v.Area + + case *LsTLVLocalIPv4RouterID: + l.Node.LocalRouterID = &v.IP + l.Link.LocalRouterID = &v.IP + + case *LsTLVLocalIPv6RouterID: + l.Node.LocalRouterIDv6 = &v.IP + l.Link.LocalRouterIDv6 = &v.IP + + case *LsTLVSrCapabilities: + l.Node.SrCapabilties = v.Extract() + + case *LsTLVSrAlgorithm: + l.Node.SrAlgorithms = &v.Algorithm + + case *LsTLVSrLocalBlock: + l.Node.SrLocalBlock = v.Extract() + + case *LsTLVRemoteIPv4RouterID: + l.Link.RemoteRouterID = &v.IP + + case *LsTLVRemoteIPv6RouterID: + l.Link.RemoteRouterIDv6 = &v.IP + + case *LsTLVAdminGroup: + l.Link.AdminGroup = &v.AdminGroup + + case *LsTLVMaxLinkBw: + l.Link.Bandwidth = &v.Bandwidth + + case *LsTLVMaxReservableLinkBw: + l.Link.ReservableBandwidth = &v.Bandwidth + + case *LsTLVUnreservedBw: + l.Link.UnreservedBandwidth = &v.Bandwidth + + case *LsTLVSrlg: + l.Link.Srlgs = &v.Srlgs + + case *LsTLVTEDefaultMetric: + l.Link.DefaultTEMetric = &v.Metric + + case *LsTLVIGPMetric: + l.Link.IGPMetric = &v.Metric + + case *LsTLVOpaqueLinkAttr: + l.Link.Opaque = &v.Attr + + case *LsTLVLinkName: + l.Link.Name = &v.Name + + case *LsTLVAdjacencySID: + l.Link.SrAdjacencySID = &v.SID + + case *LsTLVIGPFlags: + l.Prefix.IGPFlags = v.Extract() + + case *LsTLVOpaquePrefixAttr: + l.Prefix.Opaque = &v.Attr + + case *LsTLVPrefixSID: + l.Prefix.SrPrefixSID = &v.SID + } + } + + return l +} + +func (p *PathAttributeLs) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + tlvs, err := p.PathAttribute.DecodeFromBytes(data) + if err != nil { + return err + } + + for len(tlvs) >= tlvHdrLen { + t := &LsTLV{} + _, err := t.DecodeFromBytes(tlvs) + if err != nil { + return err + } + + var tlv LsTLVInterface + switch t.Type { + // Node NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.1) + case LS_TLV_NODE_FLAG_BITS: + tlv = &LsTLVNodeFlagBits{} + + case LS_TLV_OPAQUE_NODE_ATTR: + tlv = &LsTLVOpaqueNodeAttr{} + + case LS_TLV_NODE_NAME: + tlv = &LsTLVNodeName{} + + case LS_TLV_ISIS_AREA: + tlv = &LsTLVIsisArea{} + + // Used by Link NLRI as well. + case LS_TLV_IPV4_LOCAL_ROUTER_ID: + tlv = &LsTLVLocalIPv4RouterID{} + + // Used by Link NLRI as well. + case LS_TLV_IPV6_LOCAL_ROUTER_ID: + tlv = &LsTLVLocalIPv6RouterID{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Node NLRI + case LS_TLV_SR_CAPABILITIES: + tlv = &LsTLVSrCapabilities{} + + case LS_TLV_SR_ALGORITHM: + tlv = &LsTLVSrAlgorithm{} + + case LS_TLV_SR_LOCAL_BLOCK: + tlv = &LsTLVSrLocalBlock{} + + // Link NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.2) + case LS_TLV_IPV4_REMOTE_ROUTER_ID: + tlv = &LsTLVRemoteIPv4RouterID{} + + case LS_TLV_IPV6_REMOTE_ROUTER_ID: + tlv = &LsTLVRemoteIPv6RouterID{} + + case LS_TLV_ADMIN_GROUP: + tlv = &LsTLVAdminGroup{} + + case LS_TLV_MAX_LINK_BANDWIDTH: + tlv = &LsTLVMaxLinkBw{} + + case LS_TLV_MAX_RESERVABLE_BANDWIDTH: + tlv = &LsTLVMaxReservableLinkBw{} + + case LS_TLV_UNRESERVED_BANDWIDTH: + tlv = &LsTLVUnreservedBw{} + + case LS_TLV_SRLG: + tlv = &LsTLVSrlg{} + + case LS_TLV_TE_DEFAULT_METRIC: + tlv = &LsTLVTEDefaultMetric{} + + case LS_TLV_IGP_METRIC: + tlv = &LsTLVIGPMetric{} + + case LS_TLV_OPAQUE_LINK_ATTR: + tlv = &LsTLVOpaqueLinkAttr{} + + case LS_TLV_LINK_NAME: + tlv = &LsTLVLinkName{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Link NLRI + case LS_TLV_ADJACENCY_SID: + tlv = &LsTLVAdjacencySID{} + + // Prefix NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.3) + case LS_TLV_IGP_FLAGS: + tlv = &LsTLVIGPFlags{} + + case LS_TLV_OPAQUE_PREFIX_ATTR: + tlv = &LsTLVOpaquePrefixAttr{} + + // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Prefix NLRI + case LS_TLV_PREFIX_SID: + tlv = &LsTLVPrefixSID{} + + default: + tlvs = tlvs[t.Len():] + continue + } + + if err := tlv.DecodeFromBytes(tlvs); err != nil { + return err + } + tlvs = tlvs[t.Len():] + + p.TLVs = append(p.TLVs, tlv) + } + + return nil +} + +func (p *PathAttributeLs) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := []byte{} + + for _, tlv := range p.TLVs { + s, err := tlv.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, s...) + } + + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeLs) String() string { + var buf bytes.Buffer + + for _, tlv := range p.TLVs { + buf.WriteString(fmt.Sprintf("%s ", tlv.String())) + } + + return fmt.Sprintf("{LsAttributes: %s}", buf.String()) +} + +func (p *PathAttributeLs) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Flags BGPAttrFlag `json:"flags"` + LsAttribute + }{ + p.GetType(), + p.GetFlags(), + *p.Extract(), + }) +} + +func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily { + return RouteFamily(int(afi)<<16 | int(safi)) +} + +func RouteFamilyToAfiSafi(rf RouteFamily) (uint16, uint8) { + return uint16(int(rf) >> 16), uint8(int(rf) & 0xff) +} + +type RouteFamily int + +func (f RouteFamily) String() string { + if n, y := AddressFamilyNameMap[f]; y { + return n + } + return fmt.Sprintf("UnknownFamily(%d)", f) +} + +const ( + RF_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_UNICAST + RF_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_UNICAST + RF_IPv4_MC RouteFamily = AFI_IP<<16 | SAFI_MULTICAST + RF_IPv6_MC RouteFamily = AFI_IP6<<16 | SAFI_MULTICAST + RF_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN + RF_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN + RF_IPv4_VPN_MC RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN_MULTICAST + RF_IPv6_VPN_MC RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN_MULTICAST + RF_IPv4_MPLS RouteFamily = AFI_IP<<16 | SAFI_MPLS_LABEL + RF_IPv6_MPLS RouteFamily = AFI_IP6<<16 | SAFI_MPLS_LABEL + RF_VPLS RouteFamily = AFI_L2VPN<<16 | SAFI_VPLS + RF_EVPN RouteFamily = AFI_L2VPN<<16 | SAFI_EVPN + RF_RTC_UC RouteFamily = AFI_IP<<16 | SAFI_ROUTE_TARGET_CONSTRAINTS + RF_IPv4_ENCAP RouteFamily = AFI_IP<<16 | SAFI_ENCAPSULATION + RF_IPv6_ENCAP RouteFamily = AFI_IP6<<16 | SAFI_ENCAPSULATION + RF_FS_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST + RF_FS_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_VPN + RF_FS_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_UNICAST + RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN + RF_FS_L2_VPN RouteFamily = AFI_L2VPN<<16 | SAFI_FLOW_SPEC_VPN + RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE + RF_LS RouteFamily = AFI_LS<<16 | SAFI_LS + RF_SR_POLICY_IPv4 RouteFamily = AFI_IP<<16 | SAFI_SRPOLICY + RF_SR_POLICY_IPv6 RouteFamily = AFI_IP6<<16 | SAFI_SRPOLICY + RF_MUP_IPv4 RouteFamily = AFI_IP<<16 | SAFI_MUP + RF_MUP_IPv6 RouteFamily = AFI_IP6<<16 | SAFI_MUP +) + +var AddressFamilyNameMap = map[RouteFamily]string{ + RF_IPv4_UC: "ipv4-unicast", + RF_IPv6_UC: "ipv6-unicast", + RF_IPv4_MC: "ipv4-multicast", + RF_IPv6_MC: "ipv6-multicast", + RF_IPv4_MPLS: "ipv4-labelled-unicast", + RF_IPv6_MPLS: "ipv6-labelled-unicast", + RF_IPv4_VPN: "l3vpn-ipv4-unicast", + RF_IPv6_VPN: "l3vpn-ipv6-unicast", + RF_IPv4_VPN_MC: "l3vpn-ipv4-multicast", + RF_IPv6_VPN_MC: "l3vpn-ipv6-multicast", + RF_VPLS: "l2vpn-vpls", + RF_EVPN: "l2vpn-evpn", + RF_RTC_UC: "rtc", + RF_IPv4_ENCAP: "ipv4-encap", + RF_IPv6_ENCAP: "ipv6-encap", + RF_FS_IPv4_UC: "ipv4-flowspec", + RF_FS_IPv4_VPN: "l3vpn-ipv4-flowspec", + RF_FS_IPv6_UC: "ipv6-flowspec", + RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec", + RF_FS_L2_VPN: "l2vpn-flowspec", + RF_OPAQUE: "opaque", + RF_LS: "ls", + RF_SR_POLICY_IPv4: "ipv4-srpolicy", + RF_SR_POLICY_IPv6: "ipv6-srpolicy", + RF_MUP_IPv4: "ipv4-mup", + RF_MUP_IPv6: "ipv6-mup", +} + +var AddressFamilyValueMap = map[string]RouteFamily{ + AddressFamilyNameMap[RF_IPv4_UC]: RF_IPv4_UC, + AddressFamilyNameMap[RF_IPv6_UC]: RF_IPv6_UC, + AddressFamilyNameMap[RF_IPv4_MC]: RF_IPv4_MC, + AddressFamilyNameMap[RF_IPv6_MC]: RF_IPv6_MC, + AddressFamilyNameMap[RF_IPv4_MPLS]: RF_IPv4_MPLS, + AddressFamilyNameMap[RF_IPv6_MPLS]: RF_IPv6_MPLS, + AddressFamilyNameMap[RF_IPv4_VPN]: RF_IPv4_VPN, + AddressFamilyNameMap[RF_IPv6_VPN]: RF_IPv6_VPN, + AddressFamilyNameMap[RF_IPv4_VPN_MC]: RF_IPv4_VPN_MC, + AddressFamilyNameMap[RF_IPv6_VPN_MC]: RF_IPv6_VPN_MC, + AddressFamilyNameMap[RF_VPLS]: RF_VPLS, + AddressFamilyNameMap[RF_EVPN]: RF_EVPN, + AddressFamilyNameMap[RF_RTC_UC]: RF_RTC_UC, + AddressFamilyNameMap[RF_IPv4_ENCAP]: RF_IPv4_ENCAP, + AddressFamilyNameMap[RF_IPv6_ENCAP]: RF_IPv6_ENCAP, + AddressFamilyNameMap[RF_FS_IPv4_UC]: RF_FS_IPv4_UC, + AddressFamilyNameMap[RF_FS_IPv4_VPN]: RF_FS_IPv4_VPN, + AddressFamilyNameMap[RF_FS_IPv6_UC]: RF_FS_IPv6_UC, + AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN, + AddressFamilyNameMap[RF_FS_L2_VPN]: RF_FS_L2_VPN, + AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE, + AddressFamilyNameMap[RF_LS]: RF_LS, + AddressFamilyNameMap[RF_SR_POLICY_IPv4]: RF_SR_POLICY_IPv4, + AddressFamilyNameMap[RF_SR_POLICY_IPv6]: RF_SR_POLICY_IPv6, + AddressFamilyNameMap[RF_MUP_IPv4]: RF_MUP_IPv4, + AddressFamilyNameMap[RF_MUP_IPv6]: RF_MUP_IPv6, +} + +func GetRouteFamily(name string) (RouteFamily, error) { + if v, ok := AddressFamilyValueMap[name]; ok { + return v, nil + } + return RouteFamily(0), fmt.Errorf("%s isn't a valid route family name", name) +} + +func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (prefix AddrPrefixInterface, err error) { + family := AfiSafiToRouteFamily(afi, safi) + + f := func(s string) AddrPrefixInterface { + addr, net, _ := net.ParseCIDR(s) + len, _ := net.Mask.Size() + switch family { + case RF_IPv4_UC, RF_IPv4_MC: + return NewIPAddrPrefix(uint8(len), addr.String()) + } + return NewIPv6AddrPrefix(uint8(len), addr.String()) + } + + switch family { + case RF_IPv4_UC, RF_IPv4_MC: + if len(prefixStr) > 0 { + prefix = f(prefixStr[0]) + } else { + prefix = NewIPAddrPrefix(0, "") + } + case RF_IPv6_UC, RF_IPv6_MC: + if len(prefixStr) > 0 { + prefix = f(prefixStr[0]) + } else { + prefix = NewIPv6AddrPrefix(0, "") + } + case RF_IPv4_VPN: + prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil) + case RF_IPv6_VPN: + prefix = NewLabeledVPNIPv6AddrPrefix(0, "", *NewMPLSLabelStack(), nil) + case RF_IPv4_MPLS: + prefix = NewLabeledIPAddrPrefix(0, "", *NewMPLSLabelStack()) + case RF_IPv6_MPLS: + prefix = NewLabeledIPv6AddrPrefix(0, "", *NewMPLSLabelStack()) + case RF_EVPN: + prefix = NewEVPNNLRI(0, nil) + + // TODO (sbezverk) Add processing SR Policy NLRI + case RF_SR_POLICY_IPv4: + prefix = &SRPolicyIPv4{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv4, + }, + } + case RF_SR_POLICY_IPv6: + prefix = &SRPolicyIPv6{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv6, + }, + } + case RF_RTC_UC: + prefix = &RouteTargetMembershipNLRI{} + case RF_IPv4_ENCAP: + prefix = NewEncapNLRI("") + case RF_IPv6_ENCAP: + prefix = NewEncapv6NLRI("") + case RF_FS_IPv4_UC: + prefix = &FlowSpecIPv4Unicast{FlowSpecNLRI{rf: RF_FS_IPv4_UC}} + case RF_FS_IPv4_VPN: + prefix = &FlowSpecIPv4VPN{FlowSpecNLRI{rf: RF_FS_IPv4_VPN}} + case RF_FS_IPv6_UC: + prefix = &FlowSpecIPv6Unicast{FlowSpecNLRI{rf: RF_FS_IPv6_UC}} + case RF_FS_IPv6_VPN: + prefix = &FlowSpecIPv6VPN{FlowSpecNLRI{rf: RF_FS_IPv6_VPN}} + case RF_FS_L2_VPN: + prefix = &FlowSpecL2VPN{FlowSpecNLRI{rf: RF_FS_L2_VPN}} + case RF_OPAQUE: + prefix = &OpaqueNLRI{} + case RF_LS: + prefix = &LsAddrPrefix{} + case RF_MUP_IPv4: + prefix = NewMUPNLRI(AFI_IP, 0, 0, nil) + case RF_MUP_IPv6: + prefix = NewMUPNLRI(AFI_IP6, 0, 0, nil) + default: + err = fmt.Errorf("unknown route family. AFI: %d, SAFI: %d", afi, safi) + } + return prefix, err +} + +type BGPAttrFlag uint8 + +const ( + BGP_ATTR_FLAG_EXTENDED_LENGTH BGPAttrFlag = 1 << 4 + BGP_ATTR_FLAG_PARTIAL BGPAttrFlag = 1 << 5 + BGP_ATTR_FLAG_TRANSITIVE BGPAttrFlag = 1 << 6 + BGP_ATTR_FLAG_OPTIONAL BGPAttrFlag = 1 << 7 +) + +func (f BGPAttrFlag) String() string { + strs := make([]string, 0, 4) + if f&BGP_ATTR_FLAG_EXTENDED_LENGTH > 0 { + strs = append(strs, "EXTENDED_LENGTH") + } + if f&BGP_ATTR_FLAG_PARTIAL > 0 { + strs = append(strs, "PARTIAL") + } + if f&BGP_ATTR_FLAG_TRANSITIVE > 0 { + strs = append(strs, "TRANSITIVE") + } + if f&BGP_ATTR_FLAG_OPTIONAL > 0 { + strs = append(strs, "OPTIONAL") + } + return strings.Join(strs, "|") +} + +//go:generate stringer -type=BGPAttrType +type BGPAttrType uint8 + +const ( + _ BGPAttrType = iota + BGP_ATTR_TYPE_ORIGIN + BGP_ATTR_TYPE_AS_PATH + BGP_ATTR_TYPE_NEXT_HOP + BGP_ATTR_TYPE_MULTI_EXIT_DISC + BGP_ATTR_TYPE_LOCAL_PREF + BGP_ATTR_TYPE_ATOMIC_AGGREGATE + BGP_ATTR_TYPE_AGGREGATOR + BGP_ATTR_TYPE_COMMUNITIES + BGP_ATTR_TYPE_ORIGINATOR_ID + BGP_ATTR_TYPE_CLUSTER_LIST + _ + _ + _ + BGP_ATTR_TYPE_MP_REACH_NLRI // = 14 + BGP_ATTR_TYPE_MP_UNREACH_NLRI + BGP_ATTR_TYPE_EXTENDED_COMMUNITIES + BGP_ATTR_TYPE_AS4_PATH + BGP_ATTR_TYPE_AS4_AGGREGATOR + _ + _ + _ + BGP_ATTR_TYPE_PMSI_TUNNEL // = 22 + BGP_ATTR_TYPE_TUNNEL_ENCAP + _ + BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES // = 25 + BGP_ATTR_TYPE_AIGP // = 26 + _ + _ + BGP_ATTR_TYPE_LS // = 29 + BGP_ATTR_TYPE_LARGE_COMMUNITY BGPAttrType = 32 + BGP_ATTR_TYPE_PREFIX_SID BGPAttrType = 40 +) + +// NOTIFICATION Error Code RFC 4271 4.5. +const ( + _ = iota + BGP_ERROR_MESSAGE_HEADER_ERROR + BGP_ERROR_OPEN_MESSAGE_ERROR + BGP_ERROR_UPDATE_MESSAGE_ERROR + BGP_ERROR_HOLD_TIMER_EXPIRED + BGP_ERROR_FSM_ERROR + BGP_ERROR_CEASE + BGP_ERROR_ROUTE_REFRESH_MESSAGE_ERROR +) + +// NOTIFICATION Error Subcode for BGP_ERROR_MESSAGE_HEADER_ERROR +const ( + _ = iota + BGP_ERROR_SUB_CONNECTION_NOT_SYNCHRONIZED + BGP_ERROR_SUB_BAD_MESSAGE_LENGTH + BGP_ERROR_SUB_BAD_MESSAGE_TYPE +) + +// NOTIFICATION Error Subcode for BGP_ERROR_OPEN_MESSAGE_ERROR +const ( + _ = iota + BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER + BGP_ERROR_SUB_BAD_PEER_AS + BGP_ERROR_SUB_BAD_BGP_IDENTIFIER + BGP_ERROR_SUB_UNSUPPORTED_OPTIONAL_PARAMETER + BGP_ERROR_SUB_DEPRECATED_AUTHENTICATION_FAILURE + BGP_ERROR_SUB_UNACCEPTABLE_HOLD_TIME + BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY +) + +// NOTIFICATION Error Subcode for BGP_ERROR_UPDATE_MESSAGE_ERROR +const ( + _ = iota + BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST + BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE + BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE + BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR + BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR + BGP_ERROR_SUB_INVALID_ORIGIN_ATTRIBUTE + BGP_ERROR_SUB_DEPRECATED_ROUTING_LOOP + BGP_ERROR_SUB_INVALID_NEXT_HOP_ATTRIBUTE + BGP_ERROR_SUB_OPTIONAL_ATTRIBUTE_ERROR + BGP_ERROR_SUB_INVALID_NETWORK_FIELD + BGP_ERROR_SUB_MALFORMED_AS_PATH +) + +// NOTIFICATION Error Subcode for BGP_ERROR_HOLD_TIMER_EXPIRED +const ( + _ = iota + BGP_ERROR_SUB_HOLD_TIMER_EXPIRED +) + +// NOTIFICATION Error Subcode for BGP_ERROR_FSM_ERROR +const ( + _ = iota + BGP_ERROR_SUB_RECEIVE_UNEXPECTED_MESSAGE_IN_OPENSENT_STATE + BGP_ERROR_SUB_RECEIVE_UNEXPECTED_MESSAGE_IN_OPENCONFIRM_STATE + BGP_ERROR_SUB_RECEIVE_UNEXPECTED_MESSAGE_IN_ESTABLISHED_STATE +) + +// NOTIFICATION Error Subcode for BGP_ERROR_CEASE (RFC 4486) +const ( + _ = iota + BGP_ERROR_SUB_MAXIMUM_NUMBER_OF_PREFIXES_REACHED + BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN + BGP_ERROR_SUB_PEER_DECONFIGURED + BGP_ERROR_SUB_ADMINISTRATIVE_RESET + BGP_ERROR_SUB_CONNECTION_REJECTED + BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE + BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION + BGP_ERROR_SUB_OUT_OF_RESOURCES + BGP_ERROR_SUB_HARD_RESET //draft-ietf-idr-bgp-gr-notification-07 +) + +// Constants for BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN and BGP_ERROR_SUB_ADMINISTRATIVE_RESET +const ( + BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX = 128 +) + +// NOTIFICATION Error Subcode for BGP_ERROR_ROUTE_REFRESH +const ( + _ = iota + BGP_ERROR_SUB_INVALID_MESSAGE_LENGTH +) + +type NotificationErrorCode uint16 + +func (c NotificationErrorCode) String() string { + code := uint8(uint16(c) >> 8) + subcode := uint8(uint16(c) & 0xff) + UNDEFINED := "undefined" + codeStr := UNDEFINED + subcodeList := []string{} + switch code { + case BGP_ERROR_MESSAGE_HEADER_ERROR: + codeStr = "header" + subcodeList = []string{ + UNDEFINED, + "connection not synchronized", + "bad message length", + "bad message type"} + case BGP_ERROR_OPEN_MESSAGE_ERROR: + codeStr = "open" + subcodeList = []string{ + UNDEFINED, + "unsupported version number", + "bad peer as", + "bad bgp identifier", + "unsupported optional parameter", + "deprecated authentication failure", + "unacceptable hold time", + "unsupported capability"} + case BGP_ERROR_UPDATE_MESSAGE_ERROR: + codeStr = "update" + subcodeList = []string{ + UNDEFINED, + "malformed attribute list", + "unrecognized well known attribute", + "missing well known attribute", + "attribute flags error", + "attribute length error", + "invalid origin attribute", + "deprecated routing loop", + "invalid next hop attribute", + "optional attribute error", + "invalid network field", + "sub malformed as path"} + case BGP_ERROR_HOLD_TIMER_EXPIRED: + codeStr = "hold timer expired" + subcodeList = []string{ + UNDEFINED, + "hold timer expired"} + case BGP_ERROR_FSM_ERROR: + codeStr = "fsm" + subcodeList = []string{ + UNDEFINED, + "receive unexpected message in opensent state", + "receive unexpected message in openconfirm state", + "receive unexpected message in established state"} + case BGP_ERROR_CEASE: + codeStr = "cease" + subcodeList = []string{ + UNDEFINED, + "maximum number of prefixes reached", + "administrative shutdown", + "peer deconfigured", + "administrative reset", + "connection rejected", + "other configuration change", + "connection collision resolution", + "out of resources"} + case BGP_ERROR_ROUTE_REFRESH_MESSAGE_ERROR: + codeStr = "route refresh" + subcodeList = []string{"invalid message length"} + } + subcodeStr := func(idx uint8, l []string) string { + if len(l) == 0 || int(idx) > len(l)-1 { + return UNDEFINED + } + return l[idx] + }(subcode, subcodeList) + return fmt.Sprintf("code %v(%v) subcode %v(%v)", code, codeStr, subcode, subcodeStr) +} + +func NewNotificationErrorCode(code, subcode uint8) NotificationErrorCode { + return NotificationErrorCode(uint16(code)<<8 | uint16(subcode)) +} + +var PathAttrFlags map[BGPAttrType]BGPAttrFlag = map[BGPAttrType]BGPAttrFlag{ + BGP_ATTR_TYPE_ORIGIN: BGP_ATTR_FLAG_TRANSITIVE, + BGP_ATTR_TYPE_AS_PATH: BGP_ATTR_FLAG_TRANSITIVE, + BGP_ATTR_TYPE_NEXT_HOP: BGP_ATTR_FLAG_TRANSITIVE, + BGP_ATTR_TYPE_MULTI_EXIT_DISC: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_LOCAL_PREF: BGP_ATTR_FLAG_TRANSITIVE, + BGP_ATTR_TYPE_ATOMIC_AGGREGATE: BGP_ATTR_FLAG_TRANSITIVE, + BGP_ATTR_TYPE_AGGREGATOR: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_COMMUNITIES: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_ORIGINATOR_ID: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_CLUSTER_LIST: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_MP_REACH_NLRI: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_MP_UNREACH_NLRI: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_EXTENDED_COMMUNITIES: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_AS4_PATH: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_AS4_AGGREGATOR: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_PMSI_TUNNEL: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_TUNNEL_ENCAP: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_IP6_EXTENDED_COMMUNITIES: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_AIGP: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_LARGE_COMMUNITY: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_LS: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_PREFIX_SID: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, +} + +// getPathAttrFlags returns BGP Path Attribute flags value from its type and +// length (byte length of value field). +func getPathAttrFlags(typ BGPAttrType, length int) BGPAttrFlag { + flags := PathAttrFlags[typ] + if length > 255 { + flags |= BGP_ATTR_FLAG_EXTENDED_LENGTH + } + return flags +} + +type PathAttributeInterface interface { + DecodeFromBytes([]byte, ...*MarshallingOption) error + Serialize(...*MarshallingOption) ([]byte, error) + Len(...*MarshallingOption) int + GetFlags() BGPAttrFlag + GetType() BGPAttrType + String() string + MarshalJSON() ([]byte, error) + Flat() map[string]string +} + +type PathAttribute struct { + Flags BGPAttrFlag + Type BGPAttrType + Length uint16 // length of Value +} + +func (p *PathAttribute) Len(options ...*MarshallingOption) int { + if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 { + return 4 + int(p.Length) + } + return 3 + int(p.Length) +} + +func (p *PathAttribute) GetFlags() BGPAttrFlag { + return p.Flags +} + +func (p *PathAttribute) GetType() BGPAttrType { + return p.Type +} + +func (p *PathAttribute) DecodeFromBytes(data []byte, options ...*MarshallingOption) (value []byte, err error) { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + if len(data) < 2 { + return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short") + } + p.Flags = BGPAttrFlag(data[0]) + p.Type = BGPAttrType(data[1]) + if eMsg := validatePathAttributeFlags(p.Type, p.Flags); eMsg != "" { + return nil, NewMessageError(eCode, BGP_ERROR_SUB_ATTRIBUTE_FLAGS_ERROR, data, eMsg) + } + + if p.Flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 { + if len(data) < 4 { + return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short") + } + p.Length = binary.BigEndian.Uint16(data[2:4]) + data = data[4:] + } else { + if len(data) < 3 { + return nil, NewMessageError(eCode, eSubCode, data, "attribute header length is short") + } + p.Length = uint16(data[2]) + data = data[3:] + } + if len(data) < int(p.Length) { + return nil, NewMessageError(eCode, eSubCode, data, "attribute value length is short") + } + + return data[:p.Length], nil +} + +func (p *PathAttribute) Serialize(value []byte, options ...*MarshallingOption) ([]byte, error) { + // Note: Do not update "p.Flags" and "p.Length" to avoid data race. + flags := p.Flags + length := uint16(len(value)) + if flags&BGP_ATTR_FLAG_EXTENDED_LENGTH == 0 && length > 255 { + flags |= BGP_ATTR_FLAG_EXTENDED_LENGTH + } + var buf []byte + if flags&BGP_ATTR_FLAG_EXTENDED_LENGTH != 0 { + buf = append(make([]byte, 4), value...) + binary.BigEndian.PutUint16(buf[2:4], length) + } else { + buf = append(make([]byte, 3), value...) + buf[2] = byte(length) + } + buf[0] = uint8(flags) + buf[1] = uint8(p.Type) + return buf, nil +} + +type PathAttributeOrigin struct { + PathAttribute + Value uint8 +} + +func (p *PathAttributeOrigin) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 1 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "Origin attribute length is incorrect") + } + p.Value = value[0] + return nil +} + +func (p *PathAttributeOrigin) Serialize(options ...*MarshallingOption) ([]byte, error) { + return p.PathAttribute.Serialize([]byte{p.Value}, options...) +} + +func (p *PathAttributeOrigin) String() string { + typ := "-" + switch p.Value { + case BGP_ORIGIN_ATTR_TYPE_IGP: + typ = "i" + case BGP_ORIGIN_ATTR_TYPE_EGP: + typ = "e" + case BGP_ORIGIN_ATTR_TYPE_INCOMPLETE: + typ = "?" + } + return fmt.Sprintf("{Origin: %s}", typ) +} + +func (p *PathAttributeOrigin) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value uint8 `json:"value"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeOrigin(value uint8) *PathAttributeOrigin { + t := BGP_ATTR_TYPE_ORIGIN + return &PathAttributeOrigin{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 1, + }, + Value: value, + } +} + +type AsPathParamFormat struct { + start string + end string + separator string +} + +var asPathParamFormatMap = map[uint8]*AsPathParamFormat{ + BGP_ASPATH_ATTR_TYPE_SET: {"{", "}", ","}, + BGP_ASPATH_ATTR_TYPE_SEQ: {"", "", " "}, + BGP_ASPATH_ATTR_TYPE_CONFED_SET: {"(", ")", " "}, + BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: {"[", "]", ","}, +} + +type AsPathParamInterface interface { + GetType() uint8 + GetAS() []uint32 + Serialize() ([]byte, error) + DecodeFromBytes([]byte) error + Len() int + ASLen() int + MarshalJSON() ([]byte, error) + String() string +} + +func AsPathString(aspath *PathAttributeAsPath) string { + s := bytes.NewBuffer(make([]byte, 0, 64)) + for i, param := range aspath.Value { + segType := param.GetType() + asList := param.GetAS() + if i != 0 { + s.WriteString(" ") + } + + sep := " " + switch segType { + case BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + s.WriteString("(") + case BGP_ASPATH_ATTR_TYPE_CONFED_SET: + s.WriteString("[") + sep = "," + case BGP_ASPATH_ATTR_TYPE_SET: + s.WriteString("{") + sep = "," + } + for j, as := range asList { + s.WriteString(fmt.Sprintf("%d", as)) + if j != len(asList)-1 { + s.WriteString(sep) + } + } + switch segType { + case BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + s.WriteString(")") + case BGP_ASPATH_ATTR_TYPE_CONFED_SET: + s.WriteString("]") + case BGP_ASPATH_ATTR_TYPE_SET: + s.WriteString("}") + } + } + return s.String() +} + +type AsPathParam struct { + Type uint8 + Num uint8 + AS []uint16 +} + +func (a *AsPathParam) GetType() uint8 { + return a.Type +} + +func (a *AsPathParam) GetAS() []uint32 { + nums := make([]uint32, 0, len(a.AS)) + for _, as := range a.AS { + nums = append(nums, uint32(as)) + } + return nums +} + +func (a *AsPathParam) Serialize() ([]byte, error) { + buf := make([]byte, 2+len(a.AS)*2) + buf[0] = uint8(a.Type) + buf[1] = a.Num + for j, as := range a.AS { + binary.BigEndian.PutUint16(buf[2+j*2:], as) + } + return buf, nil +} + +func (a *AsPathParam) DecodeFromBytes(data []byte) error { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH) + if len(data) < 2 { + return NewMessageError(eCode, eSubCode, nil, "AS param header length is short") + } + a.Type = data[0] + a.Num = data[1] + data = data[2:] + if len(data) < int(a.Num*2) { + return NewMessageError(eCode, eSubCode, nil, "AS param data length is short") + } + for i := 0; i < int(a.Num); i++ { + a.AS = append(a.AS, binary.BigEndian.Uint16(data)) + data = data[2:] + } + return nil +} + +func (a *AsPathParam) Len() int { + return 2 + len(a.AS)*2 +} + +func (a *AsPathParam) ASLen() int { + switch a.Type { + case BGP_ASPATH_ATTR_TYPE_SEQ: + return len(a.AS) + case BGP_ASPATH_ATTR_TYPE_SET: + return 1 + case BGP_ASPATH_ATTR_TYPE_CONFED_SET, BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + return 0 + } + return 0 +} + +func (a *AsPathParam) String() string { + format, ok := asPathParamFormatMap[a.Type] + if !ok { + return fmt.Sprintf("%v", a.AS) + } + aspath := make([]string, 0, len(a.AS)) + for _, asn := range a.AS { + aspath = append(aspath, strconv.FormatUint(uint64(asn), 10)) + } + s := bytes.NewBuffer(make([]byte, 0, 32)) + s.WriteString(format.start) + s.WriteString(strings.Join(aspath, format.separator)) + s.WriteString(format.end) + return s.String() +} + +func (a *AsPathParam) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint8 `json:"segment_type"` + Num uint8 `json:"num"` + AS []uint16 `json:"asns"` + }{ + Type: a.Type, + Num: a.Num, + AS: a.AS, + }) +} + +func NewAsPathParam(segType uint8, as []uint16) *AsPathParam { + return &AsPathParam{ + Type: segType, + Num: uint8(len(as)), + AS: as, + } +} + +type As4PathParam struct { + Type uint8 + Num uint8 + AS []uint32 +} + +func (a *As4PathParam) GetType() uint8 { + return a.Type +} + +func (a *As4PathParam) GetAS() []uint32 { + return a.AS +} + +func (a *As4PathParam) Serialize() ([]byte, error) { + buf := make([]byte, 2+len(a.AS)*4) + buf[0] = a.Type + buf[1] = a.Num + for j, as := range a.AS { + binary.BigEndian.PutUint32(buf[2+j*4:], as) + } + return buf, nil +} + +func (a *As4PathParam) DecodeFromBytes(data []byte) error { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH) + if len(data) < 2 { + return NewMessageError(eCode, eSubCode, nil, "AS4 param header length is short") + } + a.Type = data[0] + a.Num = data[1] + data = data[2:] + if len(data) < int(a.Num)*4 { + return NewMessageError(eCode, eSubCode, nil, "AS4 param data length is short") + } + for i := 0; i < int(a.Num); i++ { + a.AS = append(a.AS, binary.BigEndian.Uint32(data)) + data = data[4:] + } + return nil +} + +func (a *As4PathParam) Len() int { + return 2 + len(a.AS)*4 +} + +func (a *As4PathParam) ASLen() int { + switch a.Type { + case BGP_ASPATH_ATTR_TYPE_SEQ: + return len(a.AS) + case BGP_ASPATH_ATTR_TYPE_SET: + return 1 + case BGP_ASPATH_ATTR_TYPE_CONFED_SET, BGP_ASPATH_ATTR_TYPE_CONFED_SEQ: + return 0 + } + return 0 +} + +func (a *As4PathParam) String() string { + format, ok := asPathParamFormatMap[a.Type] + if !ok { + return fmt.Sprintf("%v", a.AS) + } + aspath := make([]string, 0, len(a.AS)) + for _, asn := range a.AS { + aspath = append(aspath, strconv.FormatUint(uint64(asn), 10)) + } + s := bytes.NewBuffer(make([]byte, 0, 32)) + s.WriteString(format.start) + s.WriteString(strings.Join(aspath, format.separator)) + s.WriteString(format.end) + return s.String() +} + +func (a *As4PathParam) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type uint8 `json:"segment_type"` + Num uint8 `json:"num"` + AS []uint32 `json:"asns"` + }{ + Type: a.Type, + Num: a.Num, + AS: a.AS, + }) +} + +func NewAs4PathParam(segType uint8, as []uint32) *As4PathParam { + return &As4PathParam{ + Type: segType, + Num: uint8(len(as)), + AS: as, + } +} + +type PathAttributeAsPath struct { + PathAttribute + Value []AsPathParamInterface +} + +func (p *PathAttributeAsPath) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length == 0 { + // ibgp or something + return nil + } + isAs4, err := validateAsPathValueBytes(value) + if err != nil { + err.(*MessageError).Data, _ = p.PathAttribute.Serialize(value, options...) + return err + } + for len(value) > 0 { + var tuple AsPathParamInterface + if isAs4 { + tuple = &As4PathParam{} + } else { + tuple = &AsPathParam{} + } + err := tuple.DecodeFromBytes(value) + if err != nil { + return err + } + p.Value = append(p.Value, tuple) + value = value[tuple.Len():] + } + return nil +} + +func (p *PathAttributeAsPath) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 0) + for _, v := range p.Value { + vbuf, err := v.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, vbuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeAsPath) String() string { + params := make([]string, 0, len(p.Value)) + for _, param := range p.Value { + params = append(params, param.String()) + } + return strings.Join(params, " ") +} + +func (p *PathAttributeAsPath) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []AsPathParamInterface `json:"as_paths"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeAsPath(value []AsPathParamInterface) *PathAttributeAsPath { + var l int + for _, v := range value { + l += v.Len() + } + t := BGP_ATTR_TYPE_AS_PATH + return &PathAttributeAsPath{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: value, + } +} + +type PathAttributeNextHop struct { + PathAttribute + Value net.IP +} + +func (p *PathAttributeNextHop) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 4 && p.Length != 16 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "nexthop length isn't correct") + } + p.Value = value + return nil +} + +func (p *PathAttributeNextHop) Serialize(options ...*MarshallingOption) ([]byte, error) { + return p.PathAttribute.Serialize(p.Value, options...) +} + +func (p *PathAttributeNextHop) String() string { + return fmt.Sprintf("{Nexthop: %s}", p.Value) +} + +func (p *PathAttributeNextHop) MarshalJSON() ([]byte, error) { + value := "0.0.0.0" + if p.Value != nil { + value = p.Value.String() + } + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value string `json:"nexthop"` + }{ + Type: p.GetType(), + Value: value, + }) +} + +func NewPathAttributeNextHop(addr string) *PathAttributeNextHop { + t := BGP_ATTR_TYPE_NEXT_HOP + ip := net.ParseIP(addr) + l := net.IPv4len + if ip.To4() == nil { + l = net.IPv6len + } else { + ip = ip.To4() + } + return &PathAttributeNextHop{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: uint16(l), + }, + Value: ip, + } +} + +type PathAttributeMultiExitDisc struct { + PathAttribute + Value uint32 +} + +func (p *PathAttributeMultiExitDisc) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 4 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "med length isn't correct") + } + p.Value = binary.BigEndian.Uint32(value) + return nil +} + +func (p *PathAttributeMultiExitDisc) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], p.Value) + return p.PathAttribute.Serialize(buf[:], options...) +} + +func (p *PathAttributeMultiExitDisc) String() string { + return fmt.Sprintf("{Med: %d}", p.Value) +} + +func (p *PathAttributeMultiExitDisc) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value uint32 `json:"metric"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeMultiExitDisc(value uint32) *PathAttributeMultiExitDisc { + t := BGP_ATTR_TYPE_MULTI_EXIT_DISC + return &PathAttributeMultiExitDisc{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 4, + }, + Value: value, + } +} + +type PathAttributeLocalPref struct { + PathAttribute + Value uint32 +} + +func (p *PathAttributeLocalPref) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 4 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "local pref length isn't correct") + } + p.Value = binary.BigEndian.Uint32(value) + return nil +} + +func (p *PathAttributeLocalPref) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], p.Value) + return p.PathAttribute.Serialize(buf[:], options...) +} + +func (p *PathAttributeLocalPref) String() string { + return fmt.Sprintf("{LocalPref: %d}", p.Value) +} + +func (p *PathAttributeLocalPref) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value uint32 `json:"value"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeLocalPref(value uint32) *PathAttributeLocalPref { + t := BGP_ATTR_TYPE_LOCAL_PREF + return &PathAttributeLocalPref{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 4, + }, + Value: value, + } +} + +type PathAttributeAtomicAggregate struct { + PathAttribute +} + +func (p *PathAttributeAtomicAggregate) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + _, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 0 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "atomic aggregate should have no value") + } + return nil +} + +func (p *PathAttributeAtomicAggregate) Serialize(options ...*MarshallingOption) ([]byte, error) { + return p.PathAttribute.Serialize(nil, options...) +} + +func (p *PathAttributeAtomicAggregate) String() string { + return "{AtomicAggregate}" +} + +func (p *PathAttributeAtomicAggregate) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + }{ + Type: p.GetType(), + }) +} + +func NewPathAttributeAtomicAggregate() *PathAttributeAtomicAggregate { + t := BGP_ATTR_TYPE_ATOMIC_AGGREGATE + return &PathAttributeAtomicAggregate{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 0, + }, + } +} + +type PathAttributeAggregatorParam struct { + AS uint32 + Askind reflect.Kind + Address net.IP +} + +type PathAttributeAggregator struct { + PathAttribute + Value PathAttributeAggregatorParam +} + +func (p *PathAttributeAggregator) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + switch p.Length { + case 6: + p.Value.Askind = reflect.Uint16 + p.Value.AS = uint32(binary.BigEndian.Uint16(value[0:2])) + p.Value.Address = value[2:] + case 8: + p.Value.Askind = reflect.Uint32 + p.Value.AS = binary.BigEndian.Uint32(value[0:4]) + p.Value.Address = value[4:] + default: + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "aggregator length isn't correct") + } + return nil +} + +func (p *PathAttributeAggregator) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf []byte + switch p.Value.Askind { + case reflect.Uint16: + buf = make([]byte, 6) + binary.BigEndian.PutUint16(buf, uint16(p.Value.AS)) + copy(buf[2:], p.Value.Address) + case reflect.Uint32: + buf = make([]byte, 8) + binary.BigEndian.PutUint32(buf, p.Value.AS) + copy(buf[4:], p.Value.Address) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeAggregator) String() string { + return fmt.Sprintf("{Aggregate: {AS: %d, Address: %s}}", p.Value.AS, p.Value.Address) +} + +func (p *PathAttributeAggregator) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + AS uint32 `json:"as"` + Address string `json:"address"` + }{ + Type: p.GetType(), + AS: p.Value.AS, + Address: p.Value.Address.String(), + }) +} + +func NewPathAttributeAggregator(as interface{}, address string) *PathAttributeAggregator { + v := reflect.ValueOf(as) + asKind := v.Kind() + var l uint16 + switch asKind { + case reflect.Uint16: + l = 6 + case reflect.Uint32: + l = 8 + default: + // Invalid type + return nil + } + t := BGP_ATTR_TYPE_AGGREGATOR + return &PathAttributeAggregator{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: l, + }, + Value: PathAttributeAggregatorParam{ + AS: uint32(v.Uint()), + Askind: asKind, + Address: net.ParseIP(address).To4(), + }, + } +} + +type PathAttributeCommunities struct { + PathAttribute + Value []uint32 +} + +func (p *PathAttributeCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length%4 != 0 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "communities length isn't correct") + } + for len(value) >= 4 { + p.Value = append(p.Value, binary.BigEndian.Uint32(value)) + value = value[4:] + } + return nil +} + +func (p *PathAttributeCommunities) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, len(p.Value)*4) + for i, v := range p.Value { + binary.BigEndian.PutUint32(buf[i*4:], v) + } + return p.PathAttribute.Serialize(buf, options...) +} + +type WellKnownCommunity uint32 + +const ( + COMMUNITY_INTERNET WellKnownCommunity = 0x00000000 + COMMUNITY_PLANNED_SHUT WellKnownCommunity = 0xffff0000 + COMMUNITY_ACCEPT_OWN WellKnownCommunity = 0xffff0001 + COMMUNITY_ROUTE_FILTER_TRANSLATED_v4 WellKnownCommunity = 0xffff0002 + COMMUNITY_ROUTE_FILTER_v4 WellKnownCommunity = 0xffff0003 + COMMUNITY_ROUTE_FILTER_TRANSLATED_v6 WellKnownCommunity = 0xffff0004 + COMMUNITY_ROUTE_FILTER_v6 WellKnownCommunity = 0xffff0005 + COMMUNITY_LLGR_STALE WellKnownCommunity = 0xffff0006 + COMMUNITY_NO_LLGR WellKnownCommunity = 0xffff0007 + COMMUNITY_BLACKHOLE WellKnownCommunity = 0xffff029a + COMMUNITY_NO_EXPORT WellKnownCommunity = 0xffffff01 + COMMUNITY_NO_ADVERTISE WellKnownCommunity = 0xffffff02 + COMMUNITY_NO_EXPORT_SUBCONFED WellKnownCommunity = 0xffffff03 + COMMUNITY_NO_PEER WellKnownCommunity = 0xffffff04 +) + +var WellKnownCommunityNameMap = map[WellKnownCommunity]string{ + COMMUNITY_INTERNET: "internet", + COMMUNITY_PLANNED_SHUT: "planned-shut", + COMMUNITY_ACCEPT_OWN: "accept-own", + COMMUNITY_ROUTE_FILTER_TRANSLATED_v4: "route-filter-translated-v4", + COMMUNITY_ROUTE_FILTER_v4: "route-filter-v4", + COMMUNITY_ROUTE_FILTER_TRANSLATED_v6: "route-filter-translated-v6", + COMMUNITY_ROUTE_FILTER_v6: "route-filter-v6", + COMMUNITY_LLGR_STALE: "llgr-stale", + COMMUNITY_NO_LLGR: "no-llgr", + COMMUNITY_BLACKHOLE: "blackhole", + COMMUNITY_NO_EXPORT: "no-export", + COMMUNITY_NO_ADVERTISE: "no-advertise", + COMMUNITY_NO_EXPORT_SUBCONFED: "no-export-subconfed", + COMMUNITY_NO_PEER: "no-peer", +} + +var WellKnownCommunityValueMap = map[string]WellKnownCommunity{ + WellKnownCommunityNameMap[COMMUNITY_INTERNET]: COMMUNITY_INTERNET, + WellKnownCommunityNameMap[COMMUNITY_PLANNED_SHUT]: COMMUNITY_PLANNED_SHUT, + WellKnownCommunityNameMap[COMMUNITY_ACCEPT_OWN]: COMMUNITY_ACCEPT_OWN, + WellKnownCommunityNameMap[COMMUNITY_ROUTE_FILTER_TRANSLATED_v4]: COMMUNITY_ROUTE_FILTER_TRANSLATED_v4, + WellKnownCommunityNameMap[COMMUNITY_ROUTE_FILTER_v4]: COMMUNITY_ROUTE_FILTER_v4, + WellKnownCommunityNameMap[COMMUNITY_ROUTE_FILTER_TRANSLATED_v6]: COMMUNITY_ROUTE_FILTER_TRANSLATED_v6, + WellKnownCommunityNameMap[COMMUNITY_ROUTE_FILTER_v6]: COMMUNITY_ROUTE_FILTER_v6, + WellKnownCommunityNameMap[COMMUNITY_LLGR_STALE]: COMMUNITY_LLGR_STALE, + WellKnownCommunityNameMap[COMMUNITY_NO_LLGR]: COMMUNITY_NO_LLGR, + WellKnownCommunityNameMap[COMMUNITY_NO_EXPORT]: COMMUNITY_NO_EXPORT, + WellKnownCommunityNameMap[COMMUNITY_BLACKHOLE]: COMMUNITY_BLACKHOLE, + WellKnownCommunityNameMap[COMMUNITY_NO_ADVERTISE]: COMMUNITY_NO_ADVERTISE, + WellKnownCommunityNameMap[COMMUNITY_NO_EXPORT_SUBCONFED]: COMMUNITY_NO_EXPORT_SUBCONFED, + WellKnownCommunityNameMap[COMMUNITY_NO_PEER]: COMMUNITY_NO_PEER, +} + +func (p *PathAttributeCommunities) String() string { + l := make([]string, 0, len(p.Value)) + for _, v := range p.Value { + n, ok := WellKnownCommunityNameMap[WellKnownCommunity(v)] + if ok { + l = append(l, n) + } else { + l = append(l, fmt.Sprintf("%d:%d", (0xffff0000&v)>>16, 0xffff&v)) + } + } + return fmt.Sprintf("{Communities: %s}", strings.Join(l, ", ")) +} + +func (p *PathAttributeCommunities) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []uint32 `json:"communities"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeCommunities(value []uint32) *PathAttributeCommunities { + l := len(value) * 4 + t := BGP_ATTR_TYPE_COMMUNITIES + return &PathAttributeCommunities{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: value, + } +} + +type PathAttributeOriginatorId struct { + PathAttribute + Value net.IP +} + +func (p *PathAttributeOriginatorId) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 4 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "originator id length isn't correct") + } + p.Value = value + return nil +} + +func (p *PathAttributeOriginatorId) String() string { + return fmt.Sprintf("{Originator: %s}", p.Value) +} + +func (p *PathAttributeOriginatorId) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value string `json:"value"` + }{ + Type: p.GetType(), + Value: p.Value.String(), + }) +} + +func (p *PathAttributeOriginatorId) Serialize(options ...*MarshallingOption) ([]byte, error) { + var buf [4]byte + copy(buf[:], p.Value) + return p.PathAttribute.Serialize(buf[:], options...) +} + +func NewPathAttributeOriginatorId(value string) *PathAttributeOriginatorId { + t := BGP_ATTR_TYPE_ORIGINATOR_ID + return &PathAttributeOriginatorId{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 4, + }, + Value: net.ParseIP(value).To4(), + } +} + +type PathAttributeClusterList struct { + PathAttribute + Value []net.IP +} + +func (p *PathAttributeClusterList) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length%4 != 0 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "clusterlist length isn't correct") + } + for len(value) >= 4 { + p.Value = append(p.Value, value[:4]) + value = value[4:] + } + return nil +} + +func (p *PathAttributeClusterList) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, len(p.Value)*4) + for i, v := range p.Value { + copy(buf[i*4:], v) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeClusterList) String() string { + return fmt.Sprintf("{ClusterList: %v}", p.Value) +} + +func (p *PathAttributeClusterList) MarshalJSON() ([]byte, error) { + value := make([]string, 0, len(p.Value)) + for _, v := range p.Value { + value = append(value, v.String()) + } + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []string `json:"value"` + }{ + Type: p.GetType(), + Value: value, + }) +} + +func NewPathAttributeClusterList(value []string) *PathAttributeClusterList { + l := len(value) * 4 + list := make([]net.IP, len(value)) + for i, v := range value { + list[i] = net.ParseIP(v).To4() + } + t := BGP_ATTR_TYPE_CLUSTER_LIST + return &PathAttributeClusterList{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: list, + } +} + +type PathAttributeMpReachNLRI struct { + PathAttribute + Nexthop net.IP + LinkLocalNexthop net.IP + AFI uint16 + SAFI uint8 + Value []AddrPrefixInterface +} + +func (p *PathAttributeMpReachNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + eData, _ := p.PathAttribute.Serialize(value, options...) + if p.Length < 3 { + return NewMessageError(eCode, eSubCode, value, "mpreach header length is short") + } + afi := binary.BigEndian.Uint16(value[0:2]) + safi := value[2] + p.AFI = afi + p.SAFI = safi + _, err = NewPrefixFromRouteFamily(afi, safi) + if err != nil { + return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error()) + } + nexthoplen := int(value[3]) + if len(value) < 4+nexthoplen { + return NewMessageError(eCode, eSubCode, value, "mpreach nexthop length is short") + } + nexthopbin := value[4 : 4+nexthoplen] + if nexthoplen > 0 { + v4addrlen := 4 + v6addrlen := 16 + offset := 0 + if safi == SAFI_MPLS_VPN { + offset = 8 + } + switch nexthoplen { + case 2 * (offset + v6addrlen): + p.LinkLocalNexthop = nexthopbin[offset+v6addrlen+offset : 2*(offset+v6addrlen)] + fallthrough + case offset + v6addrlen: + p.Nexthop = nexthopbin[offset : offset+v6addrlen] + case offset + v4addrlen: + p.Nexthop = nexthopbin[offset : offset+v4addrlen] + default: + return NewMessageError(eCode, eSubCode, value, "mpreach nexthop length is incorrect") + } + } + value = value[4+nexthoplen:] + // skip reserved + if len(value) == 0 { + return NewMessageError(eCode, eSubCode, value, "no skip byte") + } + value = value[1:] + addpathLen := 0 + if IsAddPathEnabled(true, AfiSafiToRouteFamily(afi, safi), options) { + addpathLen = 4 + } + for len(value) > 0 { + prefix, err := NewPrefixFromRouteFamily(afi, safi) + if err != nil { + return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error()) + } + err = prefix.DecodeFromBytes(value, options...) + if err != nil { + return err + } + if prefix.Len(options...)+addpathLen > len(value) { + return NewMessageError(eCode, eSubCode, value, "prefix length is incorrect") + } + value = value[prefix.Len(options...)+addpathLen:] + p.Value = append(p.Value, prefix) + } + return nil +} + +func (p *PathAttributeMpReachNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + afi := p.AFI + safi := p.SAFI + nexthoplen := 4 + if afi == AFI_IP6 || p.Nexthop.To4() == nil { + nexthoplen = BGP_ATTR_NHLEN_IPV6_GLOBAL + } + offset := 0 + switch safi { + case SAFI_MPLS_VPN: + offset = 8 + nexthoplen += offset + case SAFI_FLOW_SPEC_VPN, SAFI_FLOW_SPEC_UNICAST: + nexthoplen = 0 + } + if p.LinkLocalNexthop != nil && p.LinkLocalNexthop.IsLinkLocalUnicast() { + nexthoplen = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL + } + buf := make([]byte, 4+nexthoplen) + binary.BigEndian.PutUint16(buf[0:], afi) + buf[2] = safi + buf[3] = uint8(nexthoplen) + if nexthoplen != 0 { + if p.Nexthop.To4() == nil { + copy(buf[4+offset:], p.Nexthop.To16()) + if nexthoplen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL { + copy(buf[4+offset+16:], p.LinkLocalNexthop.To16()) + } + } else { + copy(buf[4+offset:], p.Nexthop) + } + } + buf = append(buf, 0) + for _, prefix := range p.Value { + pbuf, err := prefix.Serialize(options...) + if err != nil { + return nil, err + } + buf = append(buf, pbuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeMpReachNLRI) MarshalJSON() ([]byte, error) { + nexthop := p.Nexthop.String() + if p.Nexthop == nil { + switch p.AFI { + case AFI_IP: + nexthop = "0.0.0.0" + case AFI_IP6: + nexthop = "::" + default: + nexthop = "fictitious" + } + } + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Nexthop string `json:"nexthop"` + AFI uint16 `json:"afi"` + SAFI uint8 `json:"safi"` + Value []AddrPrefixInterface `json:"value"` + }{ + Type: p.GetType(), + Nexthop: nexthop, + AFI: p.AFI, + SAFI: p.SAFI, + Value: p.Value, + }) +} + +func (p *PathAttributeMpReachNLRI) String() string { + return fmt.Sprintf("{MpReach(%s): {Nexthop: %s, NLRIs: %s}}", AfiSafiToRouteFamily(p.AFI, p.SAFI), p.Nexthop, p.Value) +} + +func NewPathAttributeMpReachNLRI(nexthop string, nlri []AddrPrefixInterface) *PathAttributeMpReachNLRI { + // AFI(2) + SAFI(1) + NexthopLength(1) + Nexthop(variable) + // + Reserved(1) + NLRI(variable) + l := 5 + var afi uint16 + var safi uint8 + if len(nlri) > 0 { + afi = nlri[0].AFI() + safi = nlri[0].SAFI() + } + nh := net.ParseIP(nexthop) + if nh.To4() != nil && afi != AFI_IP6 { + nh = nh.To4() + switch safi { + case SAFI_MPLS_VPN: + l += 12 + case SAFI_FLOW_SPEC_VPN, SAFI_FLOW_SPEC_UNICAST: + // Should not have Nexthop + default: + l += 4 + } + } else { + switch safi { + case SAFI_MPLS_VPN: + l += 24 + case SAFI_FLOW_SPEC_VPN, SAFI_FLOW_SPEC_UNICAST: + // Should not have Nexthop + default: + l += 16 + } + } + var nlriLen int + for _, n := range nlri { + l += n.Len() + nBuf, _ := n.Serialize() + nlriLen += len(nBuf) + } + t := BGP_ATTR_TYPE_MP_REACH_NLRI + return &PathAttributeMpReachNLRI{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Nexthop: nh, + AFI: afi, + SAFI: safi, + Value: nlri, + } +} + +type PathAttributeMpUnreachNLRI struct { + PathAttribute + AFI uint16 + SAFI uint8 + Value []AddrPrefixInterface +} + +func (p *PathAttributeMpUnreachNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + eData, _ := p.PathAttribute.Serialize(value, options...) + if p.Length < 3 { + return NewMessageError(eCode, eSubCode, value, "unreach header length is incorrect") + } + afi := binary.BigEndian.Uint16(value[0:2]) + safi := value[2] + _, err = NewPrefixFromRouteFamily(afi, safi) + if err != nil { + return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error()) + } + value = value[3:] + p.AFI = afi + p.SAFI = safi + addpathLen := 0 + if IsAddPathEnabled(true, AfiSafiToRouteFamily(afi, safi), options) { + addpathLen = 4 + } + for len(value) > 0 { + prefix, err := NewPrefixFromRouteFamily(afi, safi) + if err != nil { + return NewMessageError(eCode, BGP_ERROR_SUB_INVALID_NETWORK_FIELD, eData, err.Error()) + } + err = prefix.DecodeFromBytes(value, options...) + if err != nil { + return err + } + if prefix.Len(options...)+addpathLen > len(value) { + return NewMessageError(eCode, eSubCode, eData, "prefix length is incorrect") + } + value = value[prefix.Len(options...)+addpathLen:] + p.Value = append(p.Value, prefix) + } + return nil +} + +func (p *PathAttributeMpUnreachNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 3) + binary.BigEndian.PutUint16(buf, p.AFI) + buf[2] = p.SAFI + for _, prefix := range p.Value { + pbuf, err := prefix.Serialize(options...) + if err != nil { + return nil, err + } + buf = append(buf, pbuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeMpUnreachNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + AFI uint16 `json:"afi"` + SAFI uint8 `json:"safi"` + Value []AddrPrefixInterface `json:"value"` + }{ + Type: p.GetType(), + AFI: p.AFI, + SAFI: p.SAFI, + Value: p.Value, + }) +} + +func (p *PathAttributeMpUnreachNLRI) String() string { + if len(p.Value) > 0 { + return fmt.Sprintf("{MpUnreach(%s): {NLRIs: %s}}", AfiSafiToRouteFamily(p.AFI, p.SAFI), p.Value) + } + return fmt.Sprintf("{MpUnreach(%s): End-of-Rib}", AfiSafiToRouteFamily(p.AFI, p.SAFI)) +} + +func NewPathAttributeMpUnreachNLRI(nlri []AddrPrefixInterface) *PathAttributeMpUnreachNLRI { + // AFI(2) + SAFI(1) + NLRI(variable) + l := 3 + var afi uint16 + var safi uint8 + if len(nlri) > 0 { + afi = nlri[0].AFI() + safi = nlri[0].SAFI() + } + for _, n := range nlri { + l += n.Len() + } + t := BGP_ATTR_TYPE_MP_UNREACH_NLRI + return &PathAttributeMpUnreachNLRI{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + AFI: afi, + SAFI: safi, + Value: nlri, + } +} + +type ExtendedCommunityInterface interface { + Serialize() ([]byte, error) + String() string + GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) + MarshalJSON() ([]byte, error) + Flat() map[string]string +} + +type TwoOctetAsSpecificExtended struct { + SubType ExtendedCommunityAttrSubType + AS uint16 + LocalAdmin uint32 + IsTransitive bool +} + +func (e *TwoOctetAsSpecificExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + if e.IsTransitive { + buf[0] = byte(EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC) + } else { + buf[0] = byte(EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC) + } + buf[1] = byte(e.SubType) + binary.BigEndian.PutUint16(buf[2:], e.AS) + binary.BigEndian.PutUint32(buf[4:], e.LocalAdmin) + return buf, nil +} + +func (e *TwoOctetAsSpecificExtended) String() string { + return fmt.Sprintf("%d:%d", e.AS, e.LocalAdmin) +} + +func (e *TwoOctetAsSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.String(), + }) +} + +func (e *TwoOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + t := EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC + if !e.IsTransitive { + t = EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC + } + return t, e.SubType +} + +func NewTwoOctetAsSpecificExtended(subtype ExtendedCommunityAttrSubType, as uint16, localAdmin uint32, isTransitive bool) *TwoOctetAsSpecificExtended { + return &TwoOctetAsSpecificExtended{ + SubType: subtype, + AS: as, + LocalAdmin: localAdmin, + IsTransitive: isTransitive, + } +} + +type IPv4AddressSpecificExtended struct { + SubType ExtendedCommunityAttrSubType + IPv4 net.IP + LocalAdmin uint16 + IsTransitive bool +} + +func (e *IPv4AddressSpecificExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + if e.IsTransitive { + buf[0] = byte(EC_TYPE_TRANSITIVE_IP4_SPECIFIC) + } else { + buf[0] = byte(EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC) + } + buf[1] = byte(e.SubType) + copy(buf[2:6], e.IPv4) + binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin) + return buf, nil +} + +func (e *IPv4AddressSpecificExtended) String() string { + return fmt.Sprintf("%s:%d", e.IPv4.String(), e.LocalAdmin) +} + +func (e *IPv4AddressSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.String(), + }) +} + +func (e *IPv4AddressSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + t := EC_TYPE_TRANSITIVE_IP4_SPECIFIC + if !e.IsTransitive { + t = EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC + } + return t, e.SubType +} + +func NewIPv4AddressSpecificExtended(subtype ExtendedCommunityAttrSubType, ip string, localAdmin uint16, isTransitive bool) *IPv4AddressSpecificExtended { + ipv4 := net.ParseIP(ip) + if ipv4.To4() == nil { + return nil + } + return &IPv4AddressSpecificExtended{ + SubType: subtype, + IPv4: ipv4.To4(), + LocalAdmin: localAdmin, + IsTransitive: isTransitive, + } +} + +type IPv6AddressSpecificExtended struct { + SubType ExtendedCommunityAttrSubType + IPv6 net.IP + LocalAdmin uint16 + IsTransitive bool +} + +func (e *IPv6AddressSpecificExtended) Serialize() ([]byte, error) { + buf := make([]byte, 20) + if e.IsTransitive { + buf[0] = byte(EC_TYPE_TRANSITIVE_IP6_SPECIFIC) + } else { + buf[0] = byte(EC_TYPE_NON_TRANSITIVE_IP6_SPECIFIC) + } + buf[1] = byte(e.SubType) + copy(buf[2:18], e.IPv6) + binary.BigEndian.PutUint16(buf[18:], e.LocalAdmin) + return buf, nil +} + +func (e *IPv6AddressSpecificExtended) String() string { + return fmt.Sprintf("%s:%d", e.IPv6.String(), e.LocalAdmin) +} + +func (e *IPv6AddressSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.String(), + }) +} + +func (e *IPv6AddressSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + t := EC_TYPE_TRANSITIVE_IP6_SPECIFIC + if !e.IsTransitive { + t = EC_TYPE_NON_TRANSITIVE_IP6_SPECIFIC + } + return t, e.SubType +} + +func NewIPv6AddressSpecificExtended(subtype ExtendedCommunityAttrSubType, ip string, localAdmin uint16, isTransitive bool) *IPv6AddressSpecificExtended { + ipv6 := net.ParseIP(ip) + if ipv6.To16() == nil { + return nil + } + return &IPv6AddressSpecificExtended{ + SubType: subtype, + IPv6: ipv6.To16(), + LocalAdmin: localAdmin, + IsTransitive: isTransitive, + } +} + +type FourOctetAsSpecificExtended struct { + SubType ExtendedCommunityAttrSubType + AS uint32 + LocalAdmin uint16 + IsTransitive bool +} + +func (e *FourOctetAsSpecificExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + if e.IsTransitive { + buf[0] = byte(EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC) + } else { + buf[0] = byte(EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC) + } + buf[1] = byte(e.SubType) + binary.BigEndian.PutUint32(buf[2:], e.AS) + binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin) + return buf, nil +} + +func (e *FourOctetAsSpecificExtended) String() string { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:4], e.AS) + asUpper := binary.BigEndian.Uint16(buf[0:2]) + asLower := binary.BigEndian.Uint16(buf[2:4]) + return fmt.Sprintf("%d.%d:%d", asUpper, asLower, e.LocalAdmin) +} + +func (e *FourOctetAsSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.String(), + }) +} + +func (e *FourOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + t := EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC + if !e.IsTransitive { + t = EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC + } + return t, e.SubType +} + +func NewFourOctetAsSpecificExtended(subtype ExtendedCommunityAttrSubType, as uint32, localAdmin uint16, isTransitive bool) *FourOctetAsSpecificExtended { + return &FourOctetAsSpecificExtended{ + SubType: subtype, + AS: as, + LocalAdmin: localAdmin, + IsTransitive: isTransitive, + } +} + +func ParseExtendedCommunity(subtype ExtendedCommunityAttrSubType, com string) (ExtendedCommunityInterface, error) { + if subtype == EC_SUBTYPE_ENCAPSULATION { + var t TunnelType + switch com { + case TUNNEL_TYPE_L2TP3.String(): + t = TUNNEL_TYPE_L2TP3 + case TUNNEL_TYPE_GRE.String(): + t = TUNNEL_TYPE_GRE + case TUNNEL_TYPE_IP_IN_IP.String(): + t = TUNNEL_TYPE_IP_IN_IP + case TUNNEL_TYPE_VXLAN.String(): + t = TUNNEL_TYPE_VXLAN + case TUNNEL_TYPE_NVGRE.String(): + t = TUNNEL_TYPE_NVGRE + case TUNNEL_TYPE_MPLS.String(): + t = TUNNEL_TYPE_MPLS + case TUNNEL_TYPE_MPLS_IN_GRE.String(): + t = TUNNEL_TYPE_MPLS_IN_GRE + case TUNNEL_TYPE_VXLAN_GRE.String(): + t = TUNNEL_TYPE_VXLAN_GRE + case TUNNEL_TYPE_MPLS_IN_UDP.String(): + t = TUNNEL_TYPE_MPLS_IN_UDP + case TUNNEL_TYPE_GENEVE.String(): + t = TUNNEL_TYPE_GENEVE + case "L2TPv3 over IP": + t = TUNNEL_TYPE_L2TP3 + case "GRE": + t = TUNNEL_TYPE_GRE + case "IP in IP": + t = TUNNEL_TYPE_IP_IN_IP + case "VXLAN": + t = TUNNEL_TYPE_VXLAN + case "NVGRE": + t = TUNNEL_TYPE_NVGRE + case "MPLS": + t = TUNNEL_TYPE_MPLS + case "MPLS in GRE": + t = TUNNEL_TYPE_MPLS_IN_GRE + case "VXLAN GRE": + t = TUNNEL_TYPE_VXLAN_GRE + case "MPLS in UDP": + t = TUNNEL_TYPE_MPLS_IN_UDP + case "GENEVE": + t = TUNNEL_TYPE_GENEVE + default: + return nil, fmt.Errorf("invalid encap type %s", com) + } + return NewEncapExtended(t), nil + } + + if subtype == EC_SUBTYPE_ORIGIN_VALIDATION { + var state ValidationState + switch com { + case VALIDATION_STATE_VALID.String(): + state = VALIDATION_STATE_VALID + case VALIDATION_STATE_NOT_FOUND.String(): + state = VALIDATION_STATE_NOT_FOUND + case VALIDATION_STATE_INVALID.String(): + state = VALIDATION_STATE_INVALID + default: + return nil, errors.New("invalid validation state") + } + return &ValidationExtended{ + State: state, + }, nil + } + elems, err := parseRdAndRt(com) + if err != nil { + return nil, err + } + localAdmin, _ := strconv.ParseUint(elems[10], 10, 32) + if subtype == EC_SUBTYPE_SOURCE_AS { + localAdmin = 0 + } + ip := net.ParseIP(elems[1]) + isTransitive := true + switch { + case subtype == EC_SUBTYPE_LINK_BANDWIDTH: + asn, _ := strconv.ParseUint(elems[8], 10, 16) + return NewLinkBandwidthExtended(uint16(asn), float32(localAdmin)), nil + case ip.To4() != nil: + return NewIPv4AddressSpecificExtended(subtype, elems[1], uint16(localAdmin), isTransitive), nil + case ip.To16() != nil: + return NewIPv6AddressSpecificExtended(subtype, elems[1], uint16(localAdmin), isTransitive), nil + case elems[6] == "" && elems[7] == "": + asn, _ := strconv.ParseUint(elems[8], 10, 16) + return NewTwoOctetAsSpecificExtended(subtype, uint16(asn), uint32(localAdmin), isTransitive), nil + default: + fst, _ := strconv.ParseUint(elems[7], 10, 16) + snd, _ := strconv.ParseUint(elems[8], 10, 16) + asn := fst<<16 | snd + return NewFourOctetAsSpecificExtended(subtype, uint32(asn), uint16(localAdmin), isTransitive), nil + } +} + +func ParseRouteTarget(rt string) (ExtendedCommunityInterface, error) { + return ParseExtendedCommunity(EC_SUBTYPE_ROUTE_TARGET, rt) +} + +func SerializeExtendedCommunities(comms []ExtendedCommunityInterface) ([][]byte, error) { + bufs := make([][]byte, len(comms)) + var err error + for i, c := range comms { + bufs[i], err = c.Serialize() + if err != nil { + return nil, err + } + } + return bufs, err +} + +type ValidationState uint8 + +const ( + VALIDATION_STATE_VALID ValidationState = 0 + VALIDATION_STATE_NOT_FOUND ValidationState = 1 + VALIDATION_STATE_INVALID ValidationState = 2 +) + +func (s ValidationState) String() string { + switch s { + case VALIDATION_STATE_VALID: + return "valid" + case VALIDATION_STATE_NOT_FOUND: + return "not-found" + case VALIDATION_STATE_INVALID: + return "invalid" + } + return fmt.Sprintf("unknown validation state(%d)", s) +} + +type ValidationExtended struct { + State ValidationState +} + +func (e *ValidationExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + typ, subType := e.GetTypes() + buf[0] = byte(typ) + buf[1] = byte(subType) + buf[7] = byte(e.State) + return buf, nil +} + +func (e *ValidationExtended) String() string { + return e.State.String() +} + +func (e *ValidationExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_NON_TRANSITIVE_OPAQUE, EC_SUBTYPE_ORIGIN_VALIDATION +} + +func (e *ValidationExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + SubType ExtendedCommunityAttrSubType `json:"subtype"` + State ValidationState `json:"value"` + }{ + Type: t, + SubType: s, + State: e.State, + }) +} + +func NewValidationExtended(state ValidationState) *ValidationExtended { + return &ValidationExtended{ + State: state, + } +} + +type LinkBandwidthExtended struct { + AS uint16 + Bandwidth float32 +} + +func (e *LinkBandwidthExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_NON_TRANSITIVE_LINK_BANDWIDTH, EC_SUBTYPE_LINK_BANDWIDTH +} + +func (e *LinkBandwidthExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + typ, subType := e.GetTypes() + buf[0] = byte(typ) + buf[1] = byte(subType) + binary.BigEndian.PutUint16(buf[2:4], e.AS) + binary.BigEndian.PutUint32(buf[4:8], math.Float32bits(e.Bandwidth)) + return buf, nil +} + +func (e *LinkBandwidthExtended) String() string { + return fmt.Sprintf("%d:%d", e.AS, uint32(e.Bandwidth)) +} + +func (e *LinkBandwidthExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + SubType ExtendedCommunityAttrSubType `json:"subtype"` + AS uint16 `json:"asn"` + Bandwidth float32 `json:"bandwidth"` + }{ + Type: t, + SubType: s, + AS: e.AS, + Bandwidth: e.Bandwidth, + }) +} + +func NewLinkBandwidthExtended(as uint16, bw float32) *LinkBandwidthExtended { + return &LinkBandwidthExtended{ + AS: as, + Bandwidth: bw, + } +} + +type ColorExtended struct { + Color uint32 +} + +func (e *ColorExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + typ, subType := e.GetTypes() + buf[0] = byte(typ) + buf[1] = byte(subType) + binary.BigEndian.PutUint32(buf[4:8], uint32(e.Color)) + return buf, nil +} + +func (e *ColorExtended) String() string { + return fmt.Sprintf("%d", e.Color) +} + +func (e *ColorExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_COLOR +} + +func (e *ColorExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + SubType ExtendedCommunityAttrSubType `json:"subtype"` + Color uint32 `json:"color"` + }{ + Type: t, + SubType: s, + Color: e.Color, + }) +} + +func NewColorExtended(color uint32) *ColorExtended { + return &ColorExtended{ + Color: color, + } +} + +type EncapExtended struct { + TunnelType TunnelType +} + +func (e *EncapExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + typ, subType := e.GetTypes() + buf[0] = byte(typ) + buf[1] = byte(subType) + binary.BigEndian.PutUint16(buf[6:8], uint16(e.TunnelType)) + return buf, nil +} + +func (e *EncapExtended) String() string { + switch e.TunnelType { + case TUNNEL_TYPE_L2TP3: + return "L2TPv3 over IP" + case TUNNEL_TYPE_GRE: + return "GRE" + case TUNNEL_TYPE_IP_IN_IP: + return "IP in IP" + case TUNNEL_TYPE_VXLAN: + return "VXLAN" + case TUNNEL_TYPE_NVGRE: + return "NVGRE" + case TUNNEL_TYPE_MPLS: + return "MPLS" + case TUNNEL_TYPE_MPLS_IN_GRE: + return "MPLS in GRE" + case TUNNEL_TYPE_VXLAN_GRE: + return "VXLAN GRE" + case TUNNEL_TYPE_MPLS_IN_UDP: + return "MPLS in UDP" + case TUNNEL_TYPE_SR_POLICY: + return "SR Policy" + case TUNNEL_TYPE_GENEVE: + return "GENEVE" + default: + return fmt.Sprintf("tunnel: %d", e.TunnelType) + } +} + +func (e *EncapExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_ENCAPSULATION +} + +func (e *EncapExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + SubType ExtendedCommunityAttrSubType `json:"subtype"` + TunnelType TunnelType `json:"tunnel_type"` + }{ + Type: t, + SubType: s, + TunnelType: e.TunnelType, + }) +} + +func NewEncapExtended(tunnelType TunnelType) *EncapExtended { + return &EncapExtended{ + TunnelType: tunnelType, + } +} + +type DefaultGatewayExtended struct { +} + +func (e *DefaultGatewayExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + typ, subType := e.GetTypes() + buf[0] = byte(typ) + buf[1] = byte(subType) + return buf, nil +} + +func (e *DefaultGatewayExtended) String() string { + return "default-gateway" +} + +func (e *DefaultGatewayExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_TRANSITIVE_OPAQUE, EC_SUBTYPE_DEFAULT_GATEWAY +} + +func (e *DefaultGatewayExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + SubType ExtendedCommunityAttrSubType `json:"subtype"` + }{ + Type: t, + SubType: s, + }) +} + +func NewDefaultGatewayExtended() *DefaultGatewayExtended { + return &DefaultGatewayExtended{} +} + +type OpaqueExtended struct { + IsTransitive bool + Value []byte +} + +func (e *OpaqueExtended) Serialize() ([]byte, error) { + if len(e.Value) != 7 { + return nil, fmt.Errorf("invalid value length for opaque extended community: %d", len(e.Value)) + } + buf := make([]byte, 8) + if e.IsTransitive { + buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE) + } else { + buf[0] = byte(EC_TYPE_NON_TRANSITIVE_OPAQUE) + } + copy(buf[1:], e.Value) + return buf, nil +} + +func (e *OpaqueExtended) String() string { + var buf [8]byte + copy(buf[1:], e.Value) + return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf[:])) +} + +func (e *OpaqueExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + var subType ExtendedCommunityAttrSubType + if len(e.Value) > 0 { + // Use the first byte of value as the sub type + subType = ExtendedCommunityAttrSubType(e.Value[0]) + } + if e.IsTransitive { + return EC_TYPE_TRANSITIVE_OPAQUE, subType + } + return EC_TYPE_NON_TRANSITIVE_OPAQUE, subType +} + +func (e *OpaqueExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value []byte `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.Value, + }) +} + +func NewOpaqueExtended(isTransitive bool, value []byte) *OpaqueExtended { + v := make([]byte, 7) + copy(v, value) + return &OpaqueExtended{ + IsTransitive: isTransitive, + Value: v, + } +} + +func parseOpaqueExtended(data []byte) (ExtendedCommunityInterface, error) { + typ := ExtendedCommunityAttrType(data[0]) + isTransitive := false + switch typ { + case EC_TYPE_TRANSITIVE_OPAQUE: + isTransitive = true + case EC_TYPE_NON_TRANSITIVE_OPAQUE: + // isTransitive = false + default: + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("invalid opaque extended community type: %d", data[0])) + } + subType := ExtendedCommunityAttrSubType(data[1]) + + if isTransitive { + switch subType { + case EC_SUBTYPE_COLOR: + return &ColorExtended{ + Color: binary.BigEndian.Uint32(data[4:8]), + }, nil + case EC_SUBTYPE_ENCAPSULATION: + return &EncapExtended{ + TunnelType: TunnelType(binary.BigEndian.Uint16(data[6:8])), + }, nil + case EC_SUBTYPE_DEFAULT_GATEWAY: + return &DefaultGatewayExtended{}, nil + } + } else { + switch subType { + case EC_SUBTYPE_ORIGIN_VALIDATION: + return &ValidationExtended{ + State: ValidationState(data[7]), + }, nil + } + } + return NewOpaqueExtended(isTransitive, data[1:8]), nil +} + +type ESILabelExtended struct { + Label uint32 + IsSingleActive bool +} + +func (e *ESILabelExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_ESI_LABEL) + if e.IsSingleActive { + buf[2] = byte(1) + } + buf[3] = 0 + buf[4] = 0 + buf[5] = byte((e.Label >> 16) & 0xff) + buf[6] = byte((e.Label >> 8) & 0xff) + buf[7] = byte(e.Label & 0xff) + return buf, nil +} + +func (e *ESILabelExtended) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + buf.WriteString(fmt.Sprintf("esi-label: %d", e.Label)) + if e.IsSingleActive { + buf.WriteString(", single-active") + } + return buf.String() +} + +func (e *ESILabelExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Label uint32 `json:"label"` + IsSingleActive bool `json:"is_single_active"` + }{ + Type: t, + Subtype: s, + Label: e.Label, + IsSingleActive: e.IsSingleActive, + }) +} + +func (e *ESILabelExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_ESI_LABEL +} + +func NewESILabelExtended(label uint32, isSingleActive bool) *ESILabelExtended { + return &ESILabelExtended{ + Label: label, + IsSingleActive: isSingleActive, + } +} + +type ESImportRouteTarget struct { + ESImport net.HardwareAddr +} + +func (e *ESImportRouteTarget) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_ES_IMPORT) + copy(buf[2:], e.ESImport) + return buf, nil +} + +func (e *ESImportRouteTarget) String() string { + return fmt.Sprintf("es-import rt: %s", e.ESImport.String()) +} + +func (e *ESImportRouteTarget) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.ESImport.String(), + }) +} + +func (e *ESImportRouteTarget) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_ES_IMPORT +} + +func NewESImportRouteTarget(mac string) *ESImportRouteTarget { + esImport, err := net.ParseMAC(mac) + if err != nil { + return nil + } + return &ESImportRouteTarget{ + ESImport: esImport, + } +} + +type MacMobilityExtended struct { + Sequence uint32 + IsSticky bool +} + +func (e *MacMobilityExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_MAC_MOBILITY) + if e.IsSticky { + buf[2] = byte(1) + } + binary.BigEndian.PutUint32(buf[4:], e.Sequence) + return buf, nil +} + +func (e *MacMobilityExtended) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + buf.WriteString(fmt.Sprintf("mac-mobility: %d", e.Sequence)) + if e.IsSticky { + buf.WriteString(", sticky") + } + return buf.String() +} + +func (e *MacMobilityExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Sequence uint32 `json:"sequence"` + IsSticky bool `json:"is_sticky"` + }{ + Type: t, + Subtype: s, + Sequence: e.Sequence, + IsSticky: e.IsSticky, + }) +} + +func (e *MacMobilityExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_MAC_MOBILITY +} + +func NewMacMobilityExtended(seq uint32, isSticky bool) *MacMobilityExtended { + return &MacMobilityExtended{ + Sequence: seq, + IsSticky: isSticky, + } +} + +type RouterMacExtended struct { + Mac net.HardwareAddr +} + +func (e *RouterMacExtended) Serialize() ([]byte, error) { + buf := make([]byte, 2, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_ROUTER_MAC) + buf = append(buf, e.Mac...) + return buf, nil +} + +func (e *RouterMacExtended) String() string { + return fmt.Sprintf("router's mac: %s", e.Mac.String()) +} + +func (e *RouterMacExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Mac string `json:"mac"` + }{ + Type: t, + Subtype: s, + Mac: e.Mac.String(), + }) +} + +func (e *RouterMacExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_ROUTER_MAC +} + +func NewRoutersMacExtended(mac string) *RouterMacExtended { + hw, err := net.ParseMAC(mac) + if err != nil { + return nil + } + return &RouterMacExtended{ + Mac: hw, + } +} + +func parseEvpnExtended(data []byte) (ExtendedCommunityInterface, error) { + if ExtendedCommunityAttrType(data[0]) != EC_TYPE_EVPN { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("ext comm type is not EC_TYPE_EVPN: %d", data[0])) + } + subType := ExtendedCommunityAttrSubType(data[1]) + switch subType { + case EC_SUBTYPE_ESI_LABEL: + var isSingleActive bool + if data[2] > 0 { + isSingleActive = true + } + label := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7]) + return &ESILabelExtended{ + IsSingleActive: isSingleActive, + Label: label, + }, nil + case EC_SUBTYPE_ES_IMPORT: + return &ESImportRouteTarget{ + ESImport: net.HardwareAddr(data[2:8]), + }, nil + case EC_SUBTYPE_MAC_MOBILITY: + var isSticky bool + if data[2] > 0 { + isSticky = true + } + seq := binary.BigEndian.Uint32(data[4:8]) + return &MacMobilityExtended{ + Sequence: seq, + IsSticky: isSticky, + }, nil + case EC_SUBTYPE_ROUTER_MAC: + return &RouterMacExtended{ + Mac: net.HardwareAddr(data[2:8]), + }, nil + } + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("unknown evpn subtype: %d", subType)) +} + +type TrafficRateExtended struct { + AS uint16 + Rate float32 +} + +func (e *TrafficRateExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_TRAFFIC_RATE) + binary.BigEndian.PutUint16(buf[2:4], e.AS) + binary.BigEndian.PutUint32(buf[4:8], math.Float32bits(e.Rate)) + return buf, nil +} + +func (e *TrafficRateExtended) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + if e.Rate == 0 { + buf.WriteString("discard") + } else { + buf.WriteString(fmt.Sprintf("rate: %f", e.Rate)) + } + if e.AS != 0 { + buf.WriteString(fmt.Sprintf("(as: %d)", e.AS)) + } + return buf.String() +} + +func (e *TrafficRateExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + As uint16 `json:"as"` + Rate float32 `json:"rate"` + }{t, s, e.AS, e.Rate}) +} + +func (e *TrafficRateExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_FLOWSPEC_TRAFFIC_RATE +} + +func NewTrafficRateExtended(as uint16, rate float32) *TrafficRateExtended { + return &TrafficRateExtended{ + AS: as, + Rate: rate, + } +} + +type TrafficActionExtended struct { + Terminal bool + Sample bool +} + +func (e *TrafficActionExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_TRAFFIC_ACTION) + if e.Terminal { + buf[7] = 0x01 + } + if e.Sample { + buf[7] = buf[7] | 0x2 + } + return buf, nil +} + +func (e *TrafficActionExtended) String() string { + ss := make([]string, 0, 2) + if e.Terminal { + ss = append(ss, "terminal") + } + if e.Sample { + ss = append(ss, "sample") + } + return fmt.Sprintf("action: %s", strings.Join(ss, "-")) +} + +func (e *TrafficActionExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Terminal bool `json:"terminal"` + Sample bool `json:"sample"` + }{t, s, e.Terminal, e.Sample}) +} + +func (e *TrafficActionExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_FLOWSPEC_TRAFFIC_ACTION +} + +func NewTrafficActionExtended(terminal bool, sample bool) *TrafficActionExtended { + return &TrafficActionExtended{ + Terminal: terminal, + Sample: sample, + } +} + +type RedirectTwoOctetAsSpecificExtended struct { + TwoOctetAsSpecificExtended +} + +func (e *RedirectTwoOctetAsSpecificExtended) Serialize() ([]byte, error) { + buf, err := e.TwoOctetAsSpecificExtended.Serialize() + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_REDIRECT) + return buf, err +} + +func (e *RedirectTwoOctetAsSpecificExtended) String() string { + return fmt.Sprintf("redirect: %s", e.TwoOctetAsSpecificExtended.String()) +} + +func (e *RedirectTwoOctetAsSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{t, s, e.TwoOctetAsSpecificExtended.String()}) +} + +func (e *RedirectTwoOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_FLOWSPEC_REDIRECT +} + +func NewRedirectTwoOctetAsSpecificExtended(as uint16, localAdmin uint32) *RedirectTwoOctetAsSpecificExtended { + return &RedirectTwoOctetAsSpecificExtended{*NewTwoOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, as, localAdmin, false)} +} + +type RedirectIPv4AddressSpecificExtended struct { + IPv4AddressSpecificExtended +} + +func (e *RedirectIPv4AddressSpecificExtended) Serialize() ([]byte, error) { + buf, err := e.IPv4AddressSpecificExtended.Serialize() + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_REDIRECT) + return buf, err +} + +func (e *RedirectIPv4AddressSpecificExtended) String() string { + return fmt.Sprintf("redirect: %s", e.IPv4AddressSpecificExtended.String()) +} + +func (e *RedirectIPv4AddressSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{t, s, e.IPv4AddressSpecificExtended.String()}) +} + +func (e *RedirectIPv4AddressSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2, EC_SUBTYPE_FLOWSPEC_REDIRECT +} + +func NewRedirectIPv4AddressSpecificExtended(ipv4 string, localAdmin uint16) *RedirectIPv4AddressSpecificExtended { + e := NewIPv4AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, ipv4, localAdmin, false) + if e == nil { + return nil + } + return &RedirectIPv4AddressSpecificExtended{*e} +} + +type RedirectIPv6AddressSpecificExtended struct { + IPv6AddressSpecificExtended +} + +func (e *RedirectIPv6AddressSpecificExtended) Serialize() ([]byte, error) { + buf, err := e.IPv6AddressSpecificExtended.Serialize() + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6) + return buf, err +} + +func (e *RedirectIPv6AddressSpecificExtended) String() string { + return fmt.Sprintf("redirect: %s", e.IPv6AddressSpecificExtended.String()) +} + +func (e *RedirectIPv6AddressSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{t, s, e.IPv6AddressSpecificExtended.String()}) +} + +func (e *RedirectIPv6AddressSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6 +} + +func NewRedirectIPv6AddressSpecificExtended(ipv6 string, localAdmin uint16) *RedirectIPv6AddressSpecificExtended { + e := NewIPv6AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, ipv6, localAdmin, false) + if e == nil { + return nil + } + return &RedirectIPv6AddressSpecificExtended{*e} +} + +type RedirectFourOctetAsSpecificExtended struct { + FourOctetAsSpecificExtended +} + +func (e *RedirectFourOctetAsSpecificExtended) Serialize() ([]byte, error) { + buf, err := e.FourOctetAsSpecificExtended.Serialize() + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_REDIRECT) + return buf, err +} + +func (e *RedirectFourOctetAsSpecificExtended) String() string { + return fmt.Sprintf("redirect: %s", e.FourOctetAsSpecificExtended.String()) +} + +func (e *RedirectFourOctetAsSpecificExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value string `json:"value"` + }{t, s, e.FourOctetAsSpecificExtended.String()}) +} + +func (e *RedirectFourOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3, EC_SUBTYPE_FLOWSPEC_REDIRECT +} + +func NewRedirectFourOctetAsSpecificExtended(as uint32, localAdmin uint16) *RedirectFourOctetAsSpecificExtended { + return &RedirectFourOctetAsSpecificExtended{*NewFourOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, as, localAdmin, false)} +} + +type TrafficRemarkExtended struct { + DSCP uint8 +} + +func (e *TrafficRemarkExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) + buf[1] = byte(EC_SUBTYPE_FLOWSPEC_TRAFFIC_REMARK) + buf[7] = byte(e.DSCP) + return buf, nil +} + +func (e *TrafficRemarkExtended) String() string { + return fmt.Sprintf("remark: %d", e.DSCP) +} + +func (e *TrafficRemarkExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value uint8 `json:"value"` + }{t, s, e.DSCP}) +} + +func (e *TrafficRemarkExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_FLOWSPEC_TRAFFIC_REMARK +} + +func NewTrafficRemarkExtended(dscp uint8) *TrafficRemarkExtended { + return &TrafficRemarkExtended{ + DSCP: dscp, + } +} + +func parseFlowSpecExtended(data []byte) (ExtendedCommunityInterface, error) { + typ := ExtendedCommunityAttrType(data[0]) + if typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL && typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2 && typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3 { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("ext comm type is not EC_TYPE_FLOWSPEC: %d", data[0])) + } + subType := ExtendedCommunityAttrSubType(data[1]) + switch subType { + case EC_SUBTYPE_FLOWSPEC_TRAFFIC_RATE: + asn := binary.BigEndian.Uint16(data[2:4]) + bits := binary.BigEndian.Uint32(data[4:8]) + rate := math.Float32frombits(bits) + return NewTrafficRateExtended(asn, rate), nil + case EC_SUBTYPE_FLOWSPEC_TRAFFIC_ACTION: + terminal := data[7]&0x1 == 1 + sample := (data[7]>>1)&0x1 == 1 + return NewTrafficActionExtended(terminal, sample), nil + case EC_SUBTYPE_FLOWSPEC_REDIRECT: + // RFC7674 + switch typ { + case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL: + as := binary.BigEndian.Uint16(data[2:4]) + localAdmin := binary.BigEndian.Uint32(data[4:8]) + return NewRedirectTwoOctetAsSpecificExtended(as, localAdmin), nil + case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2: + ipv4 := net.IP(data[2:6]).String() + localAdmin := binary.BigEndian.Uint16(data[6:8]) + return NewRedirectIPv4AddressSpecificExtended(ipv4, localAdmin), nil + case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3: + as := binary.BigEndian.Uint32(data[2:6]) + localAdmin := binary.BigEndian.Uint16(data[6:8]) + return NewRedirectFourOctetAsSpecificExtended(as, localAdmin), nil + } + case EC_SUBTYPE_FLOWSPEC_TRAFFIC_REMARK: + dscp := data[7] + return NewTrafficRemarkExtended(dscp), nil + case EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6: + ipv6 := net.IP(data[2:18]).String() + localAdmin := binary.BigEndian.Uint16(data[18:20]) + return NewRedirectIPv6AddressSpecificExtended(ipv6, localAdmin), nil + } + return &UnknownExtended{ + Type: ExtendedCommunityAttrType(data[0]), + Value: data[1:8], + }, nil +} + +func parseIP6FlowSpecExtended(data []byte) (ExtendedCommunityInterface, error) { + typ := ExtendedCommunityAttrType(data[0]) + if typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL && typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2 && typ != EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3 { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("ext comm type is not EC_TYPE_FLOWSPEC: %d", data[0])) + } + subType := ExtendedCommunityAttrSubType(data[1]) + switch subType { + case EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6: + // RFC7674 + switch typ { + case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL: + ipv6 := net.IP(data[2:18]).String() + localAdmin := binary.BigEndian.Uint16(data[18:20]) + return NewRedirectIPv6AddressSpecificExtended(ipv6, localAdmin), nil + } + } + return &UnknownExtended{ + Type: ExtendedCommunityAttrType(data[0]), + Value: data[1:20], + }, nil +} + +type UnknownExtended struct { + Type ExtendedCommunityAttrType + Value []byte +} + +func (e *UnknownExtended) Serialize() ([]byte, error) { + if len(e.Value) != 7 { + return nil, fmt.Errorf("invalid value length for unknown extended community: %d", len(e.Value)) + } + buf := make([]byte, 8) + buf[0] = uint8(e.Type) + copy(buf[1:], e.Value) + return buf, nil +} + +func (e *UnknownExtended) String() string { + var buf [8]byte + copy(buf[1:], e.Value) + return fmt.Sprintf("%d", binary.BigEndian.Uint64(buf[:])) +} + +func (e *UnknownExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + Value []byte `json:"value"` + }{ + Type: t, + Subtype: s, + Value: e.Value, + }) +} + +func (e *UnknownExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + var subType ExtendedCommunityAttrSubType + if len(e.Value) > 0 { + // Use the first byte of value as the sub type + subType = ExtendedCommunityAttrSubType(e.Value[0]) + } + return e.Type, subType +} + +func NewUnknownExtended(typ ExtendedCommunityAttrType, value []byte) *UnknownExtended { + v := make([]byte, 7) + copy(v, value) + return &UnknownExtended{ + Type: typ, + Value: v, + } +} + +type PathAttributeExtendedCommunities struct { + PathAttribute + Value []ExtendedCommunityInterface +} + +func ParseExtended(data []byte) (ExtendedCommunityInterface, error) { + if len(data) < 8 { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "not all extended community bytes are available") + } + attrType := ExtendedCommunityAttrType(data[0]) + subtype := ExtendedCommunityAttrSubType(data[1]) + transitive := false + switch attrType { + case EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC: + transitive = true + fallthrough + case EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC: + as := binary.BigEndian.Uint16(data[2:4]) + localAdmin := binary.BigEndian.Uint32(data[4:8]) + + if subtype == EC_SUBTYPE_LINK_BANDWIDTH { + return NewLinkBandwidthExtended(as, math.Float32frombits(localAdmin)), nil + } else { + return NewTwoOctetAsSpecificExtended(subtype, as, localAdmin, transitive), nil + } + case EC_TYPE_TRANSITIVE_IP4_SPECIFIC: + transitive = true + fallthrough + case EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC: + ipv4 := net.IP(data[2:6]).String() + localAdmin := binary.BigEndian.Uint16(data[6:8]) + return NewIPv4AddressSpecificExtended(subtype, ipv4, localAdmin, transitive), nil + case EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC: + transitive = true + fallthrough + case EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC: + as := binary.BigEndian.Uint32(data[2:6]) + localAdmin := binary.BigEndian.Uint16(data[6:8]) + return NewFourOctetAsSpecificExtended(subtype, as, localAdmin, transitive), nil + case EC_TYPE_TRANSITIVE_OPAQUE: + transitive = true + fallthrough + case EC_TYPE_NON_TRANSITIVE_OPAQUE: + return parseOpaqueExtended(data) + case EC_TYPE_EVPN: + return parseEvpnExtended(data) + case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2, EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3: + return parseFlowSpecExtended(data) + case EC_TYPE_MUP: + return parseMUPExtended(data) + default: + return &UnknownExtended{ + Type: ExtendedCommunityAttrType(data[0]), + Value: data[1:8], + }, nil + } +} + +func (p *PathAttributeExtendedCommunities) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length%8 != 0 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_ATTRIBUTE_LENGTH_ERROR) + return NewMessageError(eCode, eSubCode, nil, "extendedcommunities length isn't correct") + } + for len(value) >= 8 { + e, err := ParseExtended(value) + if err != nil { + return err + } + p.Value = append(p.Value, e) + value = value[8:] + } + return nil +} + +func (p *PathAttributeExtendedCommunities) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 0) + for _, p := range p.Value { + ebuf, err := p.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ebuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeExtendedCommunities) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + for idx, v := range p.Value { + buf.WriteString("[") + buf.WriteString(v.String()) + buf.WriteString("]") + if idx < len(p.Value)-1 { + buf.WriteString(", ") + } + } + return fmt.Sprintf("{Extcomms: %s}", buf.String()) +} + +func (p *PathAttributeExtendedCommunities) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []ExtendedCommunityInterface `json:"value"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeExtendedCommunities(value []ExtendedCommunityInterface) *PathAttributeExtendedCommunities { + l := len(value) * 8 + t := BGP_ATTR_TYPE_EXTENDED_COMMUNITIES + return &PathAttributeExtendedCommunities{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: value, + } +} + +type PathAttributeAs4Path struct { + PathAttribute + Value []*As4PathParam +} + +func (p *PathAttributeAs4Path) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length == 0 { + // ibgp or something + return nil + } + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + isAs4, err := validateAsPathValueBytes(value) + if err != nil { + return err + } + + if !isAs4 { + return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed") + } + + for len(value) > 0 { + tuple := &As4PathParam{} + tuple.DecodeFromBytes(value) + p.Value = append(p.Value, tuple) + if len(value) < tuple.Len() { + return NewMessageError(eCode, eSubCode, nil, "AS4 PATH param is malformed") + } + value = value[tuple.Len():] + } + return nil +} + +func (p *PathAttributeAs4Path) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 0) + for _, v := range p.Value { + vbuf, err := v.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, vbuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeAs4Path) String() string { + params := make([]string, 0, len(p.Value)) + for _, param := range p.Value { + params = append(params, param.String()) + } + return strings.Join(params, " ") +} + +func (p *PathAttributeAs4Path) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []*As4PathParam `json:"as_paths"` + }{ + Type: p.GetType(), + Value: p.Value, + }) +} + +func NewPathAttributeAs4Path(value []*As4PathParam) *PathAttributeAs4Path { + var l int + for _, v := range value { + l += v.Len() + } + t := BGP_ATTR_TYPE_AS4_PATH + return &PathAttributeAs4Path{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: value, + } +} + +type PathAttributeAs4Aggregator struct { + PathAttribute + Value PathAttributeAggregatorParam +} + +func (p *PathAttributeAs4Aggregator) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length != 8 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "AS4 Aggregator length is incorrect") + } + p.Value.AS = binary.BigEndian.Uint32(value[0:4]) + p.Value.Address = value[4:] + return nil +} + +func (p *PathAttributeAs4Aggregator) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 8) + binary.BigEndian.PutUint32(buf[0:], p.Value.AS) + copy(buf[4:], p.Value.Address.To4()) + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeAs4Aggregator) String() string { + return fmt.Sprintf("{As4Aggregator: {AS: %d, Address: %s}}", p.Value.AS, p.Value.Address) +} + +func (p *PathAttributeAs4Aggregator) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + AS uint32 `json:"as"` + Address string `json:"address"` + }{ + Type: p.GetType(), + AS: p.Value.AS, + Address: p.Value.Address.String(), + }) +} + +func NewPathAttributeAs4Aggregator(as uint32, address string) *PathAttributeAs4Aggregator { + t := BGP_ATTR_TYPE_AS4_AGGREGATOR + return &PathAttributeAs4Aggregator{ + PathAttribute: PathAttribute{ + Flags: PathAttrFlags[t], + Type: t, + Length: 8, + }, + Value: PathAttributeAggregatorParam{ + AS: as, + Address: net.ParseIP(address).To4(), + }, + } +} + +type TunnelEncapSubTLVInterface interface { + Len() int + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) + String() string + MarshalJSON() ([]byte, error) +} + +type TunnelEncapSubTLV struct { + Type EncapSubTLVType + Length uint16 +} + +func (t *TunnelEncapSubTLV) Len() int { + if t.Type >= 0x80 { + return 3 + int(t.Length) + } + return 2 + int(t.Length) +} + +func (t *TunnelEncapSubTLV) DecodeFromBytes(data []byte) (value []byte, err error) { + t.Type = EncapSubTLVType(data[0]) + if t.Type >= 0x80 { + t.Length = binary.BigEndian.Uint16(data[1:3]) + data = data[3:] + } else { + t.Length = uint16(data[1]) + data = data[2:] + } + if len(data) < int(t.Length) { + return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLV bytes available") + } + return data[:t.Length], nil +} + +func (t *TunnelEncapSubTLV) Serialize(value []byte) (buf []byte, err error) { + t.Length = uint16(len(value)) + if t.Type >= 0x80 { + buf = append(make([]byte, 3), value...) + binary.BigEndian.PutUint16(buf[1:3], t.Length) + } else { + buf = append(make([]byte, 2), value...) + buf[1] = uint8(t.Length) + } + buf[0] = uint8(t.Type) + return buf, nil +} + +type TunnelEncapSubTLVUnknown struct { + TunnelEncapSubTLV + Value []byte +} + +func (t *TunnelEncapSubTLVUnknown) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + t.Value = value + return nil +} + +func (t *TunnelEncapSubTLVUnknown) Serialize() ([]byte, error) { + return t.TunnelEncapSubTLV.Serialize(t.Value) +} + +func (t *TunnelEncapSubTLVUnknown) String() string { + return fmt.Sprintf("{Type: %d, Value: %x}", t.Type, t.Value) +} + +func (t *TunnelEncapSubTLVUnknown) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Value []byte `json:"value"` + }{ + Type: t.Type, + Value: t.Value, + }) +} + +func NewTunnelEncapSubTLVUnknown(typ EncapSubTLVType, value []byte) *TunnelEncapSubTLVUnknown { + return &TunnelEncapSubTLVUnknown{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: typ, + }, + Value: value, + } +} + +type TunnelEncapSubTLVEncapsulation struct { + TunnelEncapSubTLV + Key uint32 // this represent both SessionID for L2TPv3 case and GRE-key for GRE case (RFC5512 4.) + Cookie []byte +} + +func (t *TunnelEncapSubTLVEncapsulation) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + if t.Length < 4 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLVEncapsulation bytes available") + } + t.Key = binary.BigEndian.Uint32(value[0:4]) + t.Cookie = value[4:] + return nil +} + +func (t *TunnelEncapSubTLVEncapsulation) Serialize() ([]byte, error) { + buf := make([]byte, 4, 4+len(t.Cookie)) + binary.BigEndian.PutUint32(buf, t.Key) + buf = append(buf, t.Cookie...) + return t.TunnelEncapSubTLV.Serialize(buf) +} + +func (t *TunnelEncapSubTLVEncapsulation) String() string { + return fmt.Sprintf("{Key: %d, Cookie: %x}", t.Key, t.Cookie) +} + +func (t *TunnelEncapSubTLVEncapsulation) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Key uint32 `json:"key"` + Cookie []byte `json:"cookie"` + }{ + Type: t.Type, + Key: t.Key, + Cookie: t.Cookie, + }) +} + +func NewTunnelEncapSubTLVEncapsulation(key uint32, cookie []byte) *TunnelEncapSubTLVEncapsulation { + return &TunnelEncapSubTLVEncapsulation{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_ENCAPSULATION, + }, + Key: key, + Cookie: cookie, + } +} + +type TunnelEncapSubTLVProtocol struct { + TunnelEncapSubTLV + Protocol uint16 +} + +func (t *TunnelEncapSubTLVProtocol) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + if t.Length < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLVProtocol bytes available") + } + t.Protocol = binary.BigEndian.Uint16(value[0:2]) + return nil +} + +func (t *TunnelEncapSubTLVProtocol) Serialize() ([]byte, error) { + var buf [2]byte + binary.BigEndian.PutUint16(buf[:2], t.Protocol) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVProtocol) String() string { + return fmt.Sprintf("{Protocol: %d}", t.Protocol) +} + +func (t *TunnelEncapSubTLVProtocol) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Protocol uint16 `json:"protocol"` + }{ + Type: t.Type, + Protocol: t.Protocol, + }) +} + +func NewTunnelEncapSubTLVProtocol(protocol uint16) *TunnelEncapSubTLVProtocol { + return &TunnelEncapSubTLVProtocol{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_PROTOCOL, + }, + Protocol: protocol, + } +} + +type TunnelEncapSubTLVColor struct { + TunnelEncapSubTLV + Color uint32 +} + +func (t *TunnelEncapSubTLVColor) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + if t.Length != 8 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Invalid TunnelEncapSubTLVColor length") + } + t.Color = binary.BigEndian.Uint32(value[4:8]) + return nil +} + +func (t *TunnelEncapSubTLVColor) Serialize() ([]byte, error) { + var buf [8]byte + buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE) + buf[1] = byte(EC_SUBTYPE_COLOR) + binary.BigEndian.PutUint32(buf[4:8], t.Color) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVColor) String() string { + return fmt.Sprintf("{Color: %d}", t.Color) +} + +func (t *TunnelEncapSubTLVColor) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Color uint32 `json:"color"` + }{ + Type: t.Type, + Color: t.Color, + }) +} + +func NewTunnelEncapSubTLVColor(color uint32) *TunnelEncapSubTLVColor { + return &TunnelEncapSubTLVColor{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_COLOR, + }, + Color: color, + } +} + +type TunnelEncapSubTLVEgressEndpoint struct { + TunnelEncapSubTLV + Address net.IP +} + +// Tunnel Egress Endpoint Sub-TLV subfield positions +const ( + EGRESS_ENDPOINT_RESERVED_POS = 0 + EGRESS_ENDPOINT_FAMILY_POS = 4 + EGRESS_ENDPOINT_ADDRESS_POS = 6 +) + +func (t *TunnelEncapSubTLVEgressEndpoint) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + if t.Length < EGRESS_ENDPOINT_ADDRESS_POS { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLVEgressEndpoint bytes available") + } + addressFamily := binary.BigEndian.Uint16(value[EGRESS_ENDPOINT_FAMILY_POS : EGRESS_ENDPOINT_FAMILY_POS+2]) + + var addressLen uint16 + switch addressFamily { + case 0: + addressLen = 0 + case AFI_IP: + addressLen = net.IPv4len + case AFI_IP6: + addressLen = net.IPv6len + default: + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Unsupported address family in TunnelEncapSubTLVEgressEndpoint") + } + if t.Length != EGRESS_ENDPOINT_ADDRESS_POS+addressLen { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLVEgressEndpoint address bytes available") + } + t.Address = nil + if addressFamily != 0 { + t.Address = net.IP(value[EGRESS_ENDPOINT_ADDRESS_POS : EGRESS_ENDPOINT_ADDRESS_POS+addressLen]) + } + + return nil +} + +func (t *TunnelEncapSubTLVEgressEndpoint) Serialize() ([]byte, error) { + var length uint32 = EGRESS_ENDPOINT_ADDRESS_POS + var family uint16 + var ip net.IP + if t.Address == nil { + family = 0 + } else if t.Address.To4() != nil { + length += net.IPv4len + family = AFI_IP + ip = t.Address.To4() + } else { + length += net.IPv6len + family = AFI_IP6 + ip = t.Address.To16() + } + buf := make([]byte, length) + binary.BigEndian.PutUint32(buf, 0) + binary.BigEndian.PutUint16(buf[EGRESS_ENDPOINT_FAMILY_POS:], family) + if family != 0 { + copy(buf[EGRESS_ENDPOINT_ADDRESS_POS:], ip) + } + return t.TunnelEncapSubTLV.Serialize(buf) +} + +func (t *TunnelEncapSubTLVEgressEndpoint) String() string { + address := "" + if t.Address != nil { + address = t.Address.String() + } + return fmt.Sprintf("{EgressEndpoint: %s}", address) +} + +func (t *TunnelEncapSubTLVEgressEndpoint) MarshalJSON() ([]byte, error) { + address := "" + if t.Address != nil { + address = t.Address.String() + } + + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Address string `json:"address"` + }{ + Type: t.Type, + Address: address, + }) +} + +func NewTunnelEncapSubTLVEgressEndpoint(address string) *TunnelEncapSubTLVEgressEndpoint { + var ip net.IP = nil + if address != "" { + ip = net.ParseIP(address) + } + return &TunnelEncapSubTLVEgressEndpoint{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_EGRESS_ENDPOINT, + }, + Address: ip, + } +} + +type TunnelEncapSubTLVUDPDestPort struct { + TunnelEncapSubTLV + UDPDestPort uint16 +} + +func (t *TunnelEncapSubTLVUDPDestPort) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + if t.Length < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapSubTLVUDPDestPort bytes available") + } + t.UDPDestPort = binary.BigEndian.Uint16(value[0:2]) + return nil +} + +func (t *TunnelEncapSubTLVUDPDestPort) Serialize() ([]byte, error) { + buf := make([]byte, 2) + binary.BigEndian.PutUint16(buf, t.UDPDestPort) + return t.TunnelEncapSubTLV.Serialize(buf) +} + +func (t *TunnelEncapSubTLVUDPDestPort) String() string { + return fmt.Sprintf("{UDPDestPort: %d}", t.UDPDestPort) +} + +func (t *TunnelEncapSubTLVUDPDestPort) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + UDPDestPort uint16 `json:"port"` + }{ + Type: t.Type, + UDPDestPort: t.UDPDestPort, + }) +} + +func NewTunnelEncapSubTLVUDPDestPort(port uint16) *TunnelEncapSubTLVUDPDestPort { + return &TunnelEncapSubTLVUDPDestPort{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_UDP_DEST_PORT, + }, + UDPDestPort: port, + } +} + +type TunnelEncapTLV struct { + Type TunnelType + Length uint16 + Value []TunnelEncapSubTLVInterface +} + +func (t *TunnelEncapTLV) Len() int { + var l int + for _, v := range t.Value { + l += v.Len() + } + return 4 + l // Type(2) + Length(2) + Value(variable) +} + +func (t *TunnelEncapTLV) DecodeFromBytes(data []byte) error { + t.Type = TunnelType(binary.BigEndian.Uint16(data[0:2])) + t.Length = binary.BigEndian.Uint16(data[2:4]) + data = data[4:] + if len(data) < int(t.Length) { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all TunnelEncapTLV bytes available") + } + value := data[:t.Length] + for len(value) > 2 { + subType := EncapSubTLVType(value[0]) + var subTlv TunnelEncapSubTLVInterface + switch subType { + case ENCAP_SUBTLV_TYPE_ENCAPSULATION: + subTlv = &TunnelEncapSubTLVEncapsulation{} + case ENCAP_SUBTLV_TYPE_PROTOCOL: + subTlv = &TunnelEncapSubTLVProtocol{} + case ENCAP_SUBTLV_TYPE_COLOR: + subTlv = &TunnelEncapSubTLVColor{} + case ENCAP_SUBTLV_TYPE_UDP_DEST_PORT: + subTlv = &TunnelEncapSubTLVUDPDestPort{} + case ENCAP_SUBTLV_TYPE_EGRESS_ENDPOINT: + subTlv = &TunnelEncapSubTLVEgressEndpoint{} + case ENCAP_SUBTLV_TYPE_SRPREFERENCE: + subTlv = &TunnelEncapSubTLVSRPreference{} + case ENCAP_SUBTLV_TYPE_SRBINDING_SID: + subTlv = &TunnelEncapSubTLVSRBSID{} + case ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST: + subTlv = &TunnelEncapSubTLVSRSegmentList{} + case ENCAP_SUBTLV_TYPE_SRENLP: + subTlv = &TunnelEncapSubTLVSRENLP{} + case ENCAP_SUBTLV_TYPE_SRPRIORITY: + subTlv = &TunnelEncapSubTLVSRPriority{} + case ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME: + subTlv = &TunnelEncapSubTLVSRCandidatePathName{} + default: + subTlv = &TunnelEncapSubTLVUnknown{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: subType, + }, + } + } + err := subTlv.DecodeFromBytes(value) + if err != nil { + return err + } + t.Value = append(t.Value, subTlv) + value = value[subTlv.Len():] + } + return nil +} + +func (p *TunnelEncapTLV) Serialize() ([]byte, error) { + buf := make([]byte, 4) + for _, t := range p.Value { + tBuf, err := t.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tBuf...) + } + binary.BigEndian.PutUint16(buf, uint16(p.Type)) + binary.BigEndian.PutUint16(buf[2:], uint16(len(buf)-4)) + return buf, nil +} + +func (p *TunnelEncapTLV) String() string { + tlvList := make([]string, len(p.Value)) + for i, v := range p.Value { + tlvList[i] = v.String() + } + return fmt.Sprintf("{%s: %s}", p.Type, strings.Join(tlvList, ", ")) +} + +func (p *TunnelEncapTLV) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type TunnelType `json:"type"` + Value []TunnelEncapSubTLVInterface `json:"value"` + }{ + Type: p.Type, + Value: p.Value, + }) +} + +func NewTunnelEncapTLV(typ TunnelType, value []TunnelEncapSubTLVInterface) *TunnelEncapTLV { + return &TunnelEncapTLV{ + Type: typ, + Value: value, + } +} + +type PathAttributeTunnelEncap struct { + PathAttribute + Value []*TunnelEncapTLV +} + +func (p *PathAttributeTunnelEncap) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + for len(value) > 4 { + tlv := &TunnelEncapTLV{} + err = tlv.DecodeFromBytes(value) + if err != nil { + return err + } + p.Value = append(p.Value, tlv) + value = value[4+tlv.Length:] + } + return nil +} + +func (p *PathAttributeTunnelEncap) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 0) + for _, t := range p.Value { + bbuf, err := t.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, bbuf...) + } + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributeTunnelEncap) String() string { + tlvList := make([]string, len(p.Value)) + for i, v := range p.Value { + tlvList[i] = v.String() + } + return fmt.Sprintf("{TunnelEncap: %s}", strings.Join(tlvList, ", ")) +} + +func (p *PathAttributeTunnelEncap) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value []*TunnelEncapTLV `json:"value"` + }{ + Type: p.Type, + Value: p.Value, + }) +} + +func NewPathAttributeTunnelEncap(value []*TunnelEncapTLV) *PathAttributeTunnelEncap { + var l int + for _, v := range value { + l += v.Len() + } + t := BGP_ATTR_TYPE_TUNNEL_ENCAP + return &PathAttributeTunnelEncap{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + Value: value, + } +} + +type PmsiTunnelIDInterface interface { + Len() int + Serialize() ([]byte, error) + String() string +} + +type DefaultPmsiTunnelID struct { + Value []byte +} + +func (i *DefaultPmsiTunnelID) Len() int { + return len(i.Value) +} + +func (i *DefaultPmsiTunnelID) Serialize() ([]byte, error) { + return i.Value, nil +} + +func (i *DefaultPmsiTunnelID) String() string { + return string(i.Value) +} + +func NewDefaultPmsiTunnelID(value []byte) *DefaultPmsiTunnelID { + return &DefaultPmsiTunnelID{ + Value: value, + } +} + +type IngressReplTunnelID struct { + Value net.IP +} + +func (i *IngressReplTunnelID) Len() int { + return len(i.Value) +} + +func (i *IngressReplTunnelID) Serialize() ([]byte, error) { + if i.Value.To4() != nil { + return []byte(i.Value.To4()), nil + } + return []byte(i.Value), nil +} + +func (i *IngressReplTunnelID) String() string { + return i.Value.String() +} + +func NewIngressReplTunnelID(value string) *IngressReplTunnelID { + ip := net.ParseIP(value) + if ip == nil { + return nil + } + return &IngressReplTunnelID{ + Value: ip, + } +} + +type PathAttributePmsiTunnel struct { + PathAttribute + IsLeafInfoRequired bool + TunnelType PmsiTunnelType + Label uint32 + TunnelID PmsiTunnelIDInterface +} + +func (p *PathAttributePmsiTunnel) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + value, err := p.PathAttribute.DecodeFromBytes(data, options...) + if err != nil { + return err + } + if p.Length < 5 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "PMSI Tunnel length is incorrect") + } + + if (value[0] & 0x01) > 0 { + p.IsLeafInfoRequired = true + } + p.TunnelType = PmsiTunnelType(value[1]) + if p.Label, err = labelDecode(value[2:5]); err != nil { + return err + } + + switch p.TunnelType { + case PMSI_TUNNEL_TYPE_INGRESS_REPL: + p.TunnelID = &IngressReplTunnelID{net.IP(value[5:])} + default: + p.TunnelID = &DefaultPmsiTunnelID{value[5:]} + } + return nil +} + +func (p *PathAttributePmsiTunnel) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 2) + if p.IsLeafInfoRequired { + buf[0] = 0x01 + } + buf[1] = byte(p.TunnelType) + tbuf, err := labelSerialize(p.Label) + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + tbuf, err = p.TunnelID.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + return p.PathAttribute.Serialize(buf, options...) +} + +func (p *PathAttributePmsiTunnel) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + buf.WriteString(fmt.Sprintf("{Pmsi: type: %s,", p.TunnelType)) + if p.IsLeafInfoRequired { + buf.WriteString(" leaf-info-required,") + } + buf.WriteString(fmt.Sprintf(" label: %d, tunnel-id: %s}", p.Label, p.TunnelID)) + return buf.String() +} + +func (p *PathAttributePmsiTunnel) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + IsLeafInfoRequired bool `json:"is-leaf-info-required"` + TunnelType uint8 `json:"tunnel-type"` + Label uint32 `json:"label"` + TunnelID string `json:"tunnel-id"` + }{ + Type: p.Type, + IsLeafInfoRequired: p.IsLeafInfoRequired, + TunnelType: uint8(p.TunnelType), + Label: p.Label, + TunnelID: p.TunnelID.String(), + }) +} + +func NewPathAttributePmsiTunnel(typ PmsiTunnelType, isLeafInfoRequired bool, label uint32, id PmsiTunnelIDInterface) *PathAttributePmsiTunnel { + if id == nil { + return nil + } + // Flags(1) + TunnelType(1) + Label(3) + TunnelID(variable) + l := 5 + id.Len() + t := BGP_ATTR_TYPE_PMSI_TUNNEL + return &PathAttributePmsiTunnel{ + PathAttribute: PathAttribute{ + Flags: getPathAttrFlags(t, l), + Type: t, + Length: uint16(l), + }, + IsLeafInfoRequired: isLeafInfoRequired, + TunnelType: typ, + Label: label, + TunnelID: id, + } +} + +func ParsePmsiTunnel(args []string) (*PathAttributePmsiTunnel, error) { + // Format: + // "" ["leaf-info-required"] "