From adbc14ab2fe16f921c1a8a1ab2dfbb6d1123bd44 Mon Sep 17 00:00:00 2001 From: Nathan Johnson Date: Tue, 6 Dec 2022 22:21:09 -0600 Subject: [PATCH] add feature to advertise anycast addresses via BGP (#909) * add feature to advertise anycast addresses via BGP add gobgp dependency ensure that we ignore advertisements from bgp peers add option to pass gobgpd config file, which helped figure out how to actually configure gobgpd to block peers from publishing routes into our routing table. install gobgpd and gobgp during github action tests update Makefile github target for use with bgp tests adding bgp documentation updating fabio.properties to show off bgp options * update docs --- .github/workflows/build.yml | 2 +- .gitignore | 4 +- Makefile | 4 + bgp/bgp.go | 413 + bgp/bgp_test.go | 186 + bgp/logger.go | 77 + bgp/test_data/bgp.toml | 15 + config/config.go | 27 + config/default.go | 17 + config/load.go | 72 + config/load_test.go | 18 + docs/content/feature/_index.md | 1 + docs/content/feature/bgp.md | 60 + docs/content/ref/bgp.anycastaddresses.md | 14 + docs/content/ref/bgp.asn.md | 9 + docs/content/ref/bgp.certfile.md | 11 + docs/content/ref/bgp.enabled.md | 9 + docs/content/ref/bgp.enablegrpc.md | 13 + docs/content/ref/bgp.gobgpdcfgfile.md | 17 + docs/content/ref/bgp.grpclistenaddress.md | 12 + docs/content/ref/bgp.grpctls.md | 11 + docs/content/ref/bgp.keyfile.md | 11 + docs/content/ref/bgp.listenaddresses.md | 11 + docs/content/ref/bgp.listenport.md | 11 + docs/content/ref/bgp.nexthop.md | 11 + docs/content/ref/bgp.peers.md | 22 + docs/content/ref/bgp.routerid.md | 13 + fabio.iml | 1 + fabio.properties | 91 + go.mod | 28 +- go.sum | 640 +- main.go | 24 +- vendor/github.com/armon/go-metrics/inmem.go | 44 +- .../armon/go-metrics/inmem_endpoint.go | 33 +- vendor/github.com/armon/go-metrics/metrics.go | 4 +- vendor/github.com/armon/go-metrics/start.go | 7 +- .../github.com/cespare/xxhash/v2/.travis.yml | 8 - vendor/github.com/cespare/xxhash/v2/README.md | 6 +- vendor/github.com/cespare/xxhash/v2/xxhash.go | 1 - .../cespare/xxhash/v2/xxhash_amd64.s | 62 +- .../cespare/xxhash/v2/xxhash_unsafe.go | 53 +- vendor/github.com/dgryski/go-farm/.gitignore | 24 + vendor/github.com/dgryski/go-farm/.travis.yml | 39 + vendor/github.com/dgryski/go-farm/LICENSE | 21 + vendor/github.com/dgryski/go-farm/Makefile | 187 + vendor/github.com/dgryski/go-farm/README.md | 46 + vendor/github.com/dgryski/go-farm/VERSION | 1 + vendor/github.com/dgryski/go-farm/basics.go | 32 + .../github.com/dgryski/go-farm/farmhashcc.go | 194 + .../github.com/dgryski/go-farm/farmhashmk.go | 102 + .../github.com/dgryski/go-farm/farmhashna.go | 161 + .../github.com/dgryski/go-farm/farmhashuo.go | 122 + .../github.com/dgryski/go-farm/farmhashxo.go | 104 + vendor/github.com/dgryski/go-farm/fp_amd64.s | 951 + .../github.com/dgryski/go-farm/fp_generic.go | 13 + vendor/github.com/dgryski/go-farm/fp_stub.go | 9 + vendor/github.com/eapache/channels/.gitignore | 22 + .../github.com/eapache/channels/.travis.yml | 11 + .../github.com/eapache/channels/CHANGELOG.md | 17 + vendor/github.com/eapache/channels/LICENSE | 20 + vendor/github.com/eapache/channels/README.md | 27 + .../eapache/channels/batching_channel.go | 87 + .../github.com/eapache/channels/black_hole.go | 54 + .../github.com/eapache/channels/channels.go | 277 + .../eapache/channels/infinite_channel.go | 72 + .../eapache/channels/native_channel.go | 92 + .../eapache/channels/overflowing_channel.go | 113 + .../eapache/channels/resizable_channel.go | 109 + .../eapache/channels/ring_channel.go | 114 + .../eapache/channels/shared_buffer.go | 167 + vendor/github.com/fatih/color/README.md | 32 +- vendor/github.com/fatih/color/color.go | 25 +- vendor/github.com/fatih/color/doc.go | 2 + vendor/github.com/fatih/color/go.mod | 4 +- vendor/github.com/fatih/color/go.sum | 17 +- .../fsnotify/fsnotify/.editorconfig | 12 + .../fsnotify/fsnotify/.gitattributes | 1 + .../github.com/fsnotify/fsnotify/.gitignore | 6 + vendor/github.com/fsnotify/fsnotify/.mailmap | 2 + vendor/github.com/fsnotify/fsnotify/AUTHORS | 62 + .../github.com/fsnotify/fsnotify/CHANGELOG.md | 339 + .../fsnotify/fsnotify/CONTRIBUTING.md | 77 + vendor/github.com/fsnotify/fsnotify/LICENSE | 28 + vendor/github.com/fsnotify/fsnotify/README.md | 130 + vendor/github.com/fsnotify/fsnotify/fen.go | 38 + .../github.com/fsnotify/fsnotify/fsnotify.go | 69 + vendor/github.com/fsnotify/fsnotify/go.mod | 7 + vendor/github.com/fsnotify/fsnotify/go.sum | 2 + .../github.com/fsnotify/fsnotify/inotify.go | 338 + .../fsnotify/fsnotify/inotify_poller.go | 188 + vendor/github.com/fsnotify/fsnotify/kqueue.go | 522 + .../fsnotify/fsnotify/open_mode_bsd.go | 12 + .../fsnotify/fsnotify/open_mode_darwin.go | 13 + .../github.com/fsnotify/fsnotify/windows.go | 562 + .../golang/protobuf/jsonpb/decode.go | 524 + .../golang/protobuf/jsonpb/encode.go | 559 + .../github.com/golang/protobuf/jsonpb/json.go | 69 + .../golang/protobuf/proto/registry.go | 10 +- .../github.com/golang/protobuf/ptypes/any.go | 14 + .../github.com/golang/protobuf/ptypes/doc.go | 4 + .../golang/protobuf/ptypes/duration.go | 4 + .../golang/protobuf/ptypes/timestamp.go | 9 + .../github.com/golang/snappy/decode_arm64.s | 45 +- .../github.com/golang/snappy/encode_arm64.s | 81 +- vendor/github.com/google/uuid/.travis.yml | 9 + vendor/github.com/google/uuid/CONTRIBUTING.md | 10 + vendor/github.com/google/uuid/CONTRIBUTORS | 9 + vendor/github.com/google/uuid/LICENSE | 27 + vendor/github.com/google/uuid/README.md | 19 + vendor/github.com/google/uuid/dce.go | 80 + vendor/github.com/google/uuid/doc.go | 12 + vendor/github.com/google/uuid/go.mod | 1 + vendor/github.com/google/uuid/hash.go | 53 + vendor/github.com/google/uuid/marshal.go | 38 + vendor/github.com/google/uuid/node.go | 90 + vendor/github.com/google/uuid/node_js.go | 12 + vendor/github.com/google/uuid/node_net.go | 33 + vendor/github.com/google/uuid/null.go | 118 + vendor/github.com/google/uuid/sql.go | 59 + vendor/github.com/google/uuid/time.go | 123 + vendor/github.com/google/uuid/util.go | 43 + vendor/github.com/google/uuid/uuid.go | 294 + vendor/github.com/google/uuid/version1.go | 44 + vendor/github.com/google/uuid/version4.go | 76 + vendor/github.com/hashicorp/consul/api/acl.go | 431 +- .../github.com/hashicorp/consul/api/agent.go | 455 +- vendor/github.com/hashicorp/consul/api/api.go | 187 +- .../hashicorp/consul/api/catalog.go | 69 +- .../hashicorp/consul/api/config_entry.go | 269 +- .../consul/api/config_entry_discoverychain.go | 171 +- .../consul/api/config_entry_exports.go | 72 + .../consul/api/config_entry_gateways.go | 95 +- .../consul/api/config_entry_intentions.go | 66 + .../hashicorp/consul/api/config_entry_mesh.go | 56 + .../hashicorp/consul/api/connect_ca.go | 31 +- .../hashicorp/consul/api/connect_intention.go | 186 +- .../hashicorp/consul/api/coordinate.go | 35 +- .../github.com/hashicorp/consul/api/debug.go | 41 +- .../hashicorp/consul/api/discovery_chain.go | 11 +- .../github.com/hashicorp/consul/api/event.go | 15 +- vendor/github.com/hashicorp/consul/api/go.mod | 4 +- vendor/github.com/hashicorp/consul/api/go.sum | 47 +- .../github.com/hashicorp/consul/api/health.go | 30 +- vendor/github.com/hashicorp/consul/api/kv.go | 36 +- .../github.com/hashicorp/consul/api/lock.go | 6 +- .../hashicorp/consul/api/namespace.go | 45 +- .../hashicorp/consul/api/operator_area.go | 28 +- .../consul/api/operator_autopilot.go | 185 +- .../hashicorp/consul/api/operator_keyring.go | 31 +- .../hashicorp/consul/api/operator_license.go | 30 +- .../hashicorp/consul/api/operator_raft.go | 23 +- .../hashicorp/consul/api/partition.go | 164 + .../hashicorp/consul/api/prepared_query.go | 14 +- .../hashicorp/consul/api/session.go | 2 +- .../hashicorp/consul/api/snapshot.go | 11 +- .../github.com/hashicorp/consul/api/status.go | 36 +- vendor/github.com/hashicorp/consul/api/txn.go | 3 +- .../hashicorp/go-cleanhttp/cleanhttp.go | 1 + .../github.com/hashicorp/go-cleanhttp/go.mod | 2 + .../hashicorp/go-hclog/interceptlogger.go | 105 +- .../hashicorp/go-hclog/intlogger.go | 207 +- .../github.com/hashicorp/go-hclog/logger.go | 30 +- .../github.com/hashicorp/go-hclog/stdlog.go | 2 +- .../hashicorp/go-immutable-radix/CHANGELOG.md | 2 + .../hashicorp/go-immutable-radix/iter.go | 59 +- .../go-immutable-radix/reverse_iter.go | 166 +- .../hashicorp/go-multierror/.travis.yml | 12 - .../hashicorp/go-multierror/README.md | 29 +- .../hashicorp/go-multierror/append.go | 2 + .../github.com/hashicorp/go-multierror/go.mod | 2 +- .../hashicorp/go-multierror/multierror.go | 15 +- .../hashicorp/hcl/hcl/printer/nodes.go | 789 + .../hashicorp/hcl/hcl/printer/printer.go | 66 + .../github.com/k-sone/critbitgo/.travis.yml | 6 + vendor/github.com/k-sone/critbitgo/CHANGES.md | 22 + vendor/github.com/k-sone/critbitgo/LICENSE | 22 + vendor/github.com/k-sone/critbitgo/README.md | 44 + vendor/github.com/k-sone/critbitgo/critbit.go | 393 + vendor/github.com/k-sone/critbitgo/map.go | 57 + vendor/github.com/k-sone/critbitgo/net.go | 323 + .../magiconair/properties/.travis.yml | 1 + .../magiconair/properties/properties.go | 2 +- .../github.com/mattn/go-colorable/.travis.yml | 15 - .../github.com/mattn/go-colorable/README.md | 2 +- .../mattn/go-colorable/colorable_appengine.go | 1 + .../mattn/go-colorable/colorable_others.go | 4 +- .../mattn/go-colorable/colorable_windows.go | 14 +- vendor/github.com/mattn/go-colorable/go.mod | 4 +- vendor/github.com/mattn/go-colorable/go.sum | 10 +- .../mattn/go-colorable/noncolorable.go | 12 +- vendor/github.com/mattn/go-isatty/.travis.yml | 14 - vendor/github.com/mattn/go-isatty/go.mod | 2 +- .../github.com/mattn/go-isatty/isatty_bsd.go | 1 + .../mattn/go-isatty/isatty_others.go | 3 +- .../mattn/go-isatty/isatty_plan9.go | 1 + .../mattn/go-isatty/isatty_solaris.go | 9 +- .../mattn/go-isatty/isatty_tcgets.go | 3 +- .../mattn/go-isatty/isatty_windows.go | 6 +- .../github.com/mattn/go-isatty/renovate.json | 8 - .../mitchellh/mapstructure/.travis.yml | 9 - .../mitchellh/mapstructure/CHANGELOG.md | 22 + .../mitchellh/mapstructure/decode_hooks.go | 72 +- .../mitchellh/mapstructure/mapstructure.go | 144 +- vendor/github.com/osrg/gobgp/v3/LICENSE | 201 + .../osrg/gobgp/v3/api/attribute.pb.go | 10273 ++++++++++ .../osrg/gobgp/v3/api/attribute.proto | 892 + .../osrg/gobgp/v3/api/capability.pb.go | 1252 ++ .../osrg/gobgp/v3/api/capability.proto | 105 + .../github.com/osrg/gobgp/v3/api/gobgp.pb.go | 15721 ++++++++++++++++ .../github.com/osrg/gobgp/v3/api/gobgp.proto | 1115 ++ .../osrg/gobgp/v3/api/gobgp_grpc.pb.go | 2436 +++ .../v3/internal/pkg/config/bgp_configs.go | 6423 +++++++ .../gobgp/v3/internal/pkg/config/default.go | 537 + .../v3/internal/pkg/config/default_linux.go | 73 + .../internal/pkg/config/default_nonlinux.go | 26 + .../gobgp/v3/internal/pkg/config/serve.go | 131 + .../osrg/gobgp/v3/internal/pkg/config/util.go | 763 + .../osrg/gobgp/v3/internal/pkg/table/adj.go | 253 + .../v3/internal/pkg/table/destination.go | 934 + .../gobgp/v3/internal/pkg/table/message.go | 519 + .../osrg/gobgp/v3/internal/pkg/table/path.go | 1283 ++ .../gobgp/v3/internal/pkg/table/policy.go | 4166 ++++ .../osrg/gobgp/v3/internal/pkg/table/roa.go | 299 + .../osrg/gobgp/v3/internal/pkg/table/table.go | 507 + .../v3/internal/pkg/table/table_manager.go | 365 + .../osrg/gobgp/v3/internal/pkg/table/vrf.go | 55 + .../gobgp/v3/internal/pkg/version/version.go | 51 + .../gobgp/v3/internal/pkg/zebra/afi_string.go | 27 + .../v3/internal/pkg/zebra/apitype_string.go | 272 + .../v3/internal/pkg/zebra/linktype_string.go | 72 + .../v3/internal/pkg/zebra/lsptype_string.go | 28 + .../internal/pkg/zebra/nexthopflag_string.go | 61 + .../internal/pkg/zebra/nexthoptype_string.go | 37 + .../v3/internal/pkg/zebra/ptmenable_string.go | 25 + .../v3/internal/pkg/zebra/ptmstatus_string.go | 25 + .../v3/internal/pkg/zebra/routetype_string.go | 75 + .../v3/internal/pkg/zebra/safi_string.go | 36 + .../osrg/gobgp/v3/internal/pkg/zebra/zapi.go | 3578 ++++ .../gobgp/v3/internal/pkg/zebra/zapi_bsd.go | 59 + .../v3/internal/pkg/zebra/zapi_darwin.go | 59 + .../gobgp/v3/internal/pkg/zebra/zapi_linux.go | 83 + .../v3/internal/pkg/zebra/zapi_windows.go | 38 + .../osrg/gobgp/v3/pkg/apiutil/attribute.go | 2406 +++ .../osrg/gobgp/v3/pkg/apiutil/capability.go | 256 + .../osrg/gobgp/v3/pkg/apiutil/util.go | 138 + .../osrg/gobgp/v3/pkg/config/config.go | 415 + .../osrg/gobgp/v3/pkg/log/logger.go | 87 + .../osrg/gobgp/v3/pkg/packet/bgp/bgp.go | 13633 ++++++++++++++ .../v3/pkg/packet/bgp/bgpattrtype_string.go | 75 + .../osrg/gobgp/v3/pkg/packet/bgp/constant.go | 328 + .../gobgp/v3/pkg/packet/bgp/esitype_string.go | 28 + .../v3/pkg/packet/bgp/fsmstate_string.go | 28 + .../osrg/gobgp/v3/pkg/packet/bgp/helper.go | 126 + .../osrg/gobgp/v3/pkg/packet/bgp/mup.go | 651 + .../gobgp/v3/pkg/packet/bgp/prefix_sid.go | 694 + .../osrg/gobgp/v3/pkg/packet/bgp/sr_policy.go | 927 + .../gobgp/v3/pkg/packet/bgp/srbehavior.go | 47 + .../v3/pkg/packet/bgp/srbehavior_string.go | 84 + .../osrg/gobgp/v3/pkg/packet/bgp/validate.go | 356 + .../osrg/gobgp/v3/pkg/packet/bmp/bmp.go | 1116 ++ .../osrg/gobgp/v3/pkg/packet/mrt/mrt.go | 1010 + .../osrg/gobgp/v3/pkg/packet/rtr/rtr.go | 392 + .../osrg/gobgp/v3/pkg/server/bmp.go | 400 + .../osrg/gobgp/v3/pkg/server/fsm.go | 1988 ++ .../osrg/gobgp/v3/pkg/server/grpc_server.go | 1840 ++ .../osrg/gobgp/v3/pkg/server/mrt.go | 413 + .../osrg/gobgp/v3/pkg/server/peer.go | 578 + .../osrg/gobgp/v3/pkg/server/rpki.go | 451 + .../osrg/gobgp/v3/pkg/server/server.go | 4538 +++++ .../osrg/gobgp/v3/pkg/server/sockopt.go | 64 + .../osrg/gobgp/v3/pkg/server/sockopt_bsd.go | 61 + .../gobgp/v3/pkg/server/sockopt_darwin.go | 45 + .../osrg/gobgp/v3/pkg/server/sockopt_linux.go | 168 + .../gobgp/v3/pkg/server/sockopt_openbsd.go | 411 + .../osrg/gobgp/v3/pkg/server/sockopt_stub.go | 35 + .../osrg/gobgp/v3/pkg/server/util.go | 108 + .../osrg/gobgp/v3/pkg/server/zclient.go | 585 + .../pelletier/go-toml/.dockerignore | 2 + .../github.com/pelletier/go-toml/.gitignore | 5 + .../pelletier/go-toml/CONTRIBUTING.md | 132 + .../github.com/pelletier/go-toml/Dockerfile | 11 + vendor/github.com/pelletier/go-toml/LICENSE | 247 + vendor/github.com/pelletier/go-toml/Makefile | 29 + .../go-toml/PULL_REQUEST_TEMPLATE.md | 5 + vendor/github.com/pelletier/go-toml/README.md | 176 + .../pelletier/go-toml/azure-pipelines.yml | 188 + .../github.com/pelletier/go-toml/benchmark.sh | 35 + vendor/github.com/pelletier/go-toml/doc.go | 23 + .../pelletier/go-toml/example-crlf.toml | 30 + .../github.com/pelletier/go-toml/example.toml | 30 + vendor/github.com/pelletier/go-toml/fuzz.go | 31 + vendor/github.com/pelletier/go-toml/fuzz.sh | 15 + vendor/github.com/pelletier/go-toml/go.mod | 3 + .../pelletier/go-toml/keysparsing.go | 112 + vendor/github.com/pelletier/go-toml/lexer.go | 1031 + .../github.com/pelletier/go-toml/localtime.go | 287 + .../github.com/pelletier/go-toml/marshal.go | 1308 ++ .../go-toml/marshal_OrderPreserve_test.toml | 39 + .../pelletier/go-toml/marshal_test.toml | 39 + vendor/github.com/pelletier/go-toml/parser.go | 508 + .../github.com/pelletier/go-toml/position.go | 29 + vendor/github.com/pelletier/go-toml/token.go | 136 + vendor/github.com/pelletier/go-toml/toml.go | 533 + .../github.com/pelletier/go-toml/tomlpub.go | 71 + .../pelletier/go-toml/tomltree_create.go | 155 + .../pelletier/go-toml/tomltree_write.go | 552 + .../pelletier/go-toml/tomltree_writepub.go | 6 + vendor/github.com/sirupsen/logrus/.gitignore | 4 + .../github.com/sirupsen/logrus/.golangci.yml | 40 + vendor/github.com/sirupsen/logrus/.travis.yml | 15 + .../github.com/sirupsen/logrus/CHANGELOG.md | 259 + vendor/github.com/sirupsen/logrus/LICENSE | 21 + vendor/github.com/sirupsen/logrus/README.md | 513 + vendor/github.com/sirupsen/logrus/alt_exit.go | 76 + .../github.com/sirupsen/logrus/appveyor.yml | 14 + .../github.com/sirupsen/logrus/buffer_pool.go | 52 + vendor/github.com/sirupsen/logrus/doc.go | 26 + vendor/github.com/sirupsen/logrus/entry.go | 431 + vendor/github.com/sirupsen/logrus/exported.go | 270 + .../github.com/sirupsen/logrus/formatter.go | 78 + vendor/github.com/sirupsen/logrus/go.mod | 10 + vendor/github.com/sirupsen/logrus/go.sum | 8 + vendor/github.com/sirupsen/logrus/hooks.go | 34 + .../sirupsen/logrus/json_formatter.go | 128 + vendor/github.com/sirupsen/logrus/logger.go | 404 + vendor/github.com/sirupsen/logrus/logrus.go | 186 + .../logrus/terminal_check_appengine.go | 11 + .../sirupsen/logrus/terminal_check_bsd.go | 13 + .../sirupsen/logrus/terminal_check_js.go | 7 + .../logrus/terminal_check_no_terminal.go | 11 + .../logrus/terminal_check_notappengine.go | 17 + .../sirupsen/logrus/terminal_check_solaris.go | 11 + .../sirupsen/logrus/terminal_check_unix.go | 13 + .../sirupsen/logrus/terminal_check_windows.go | 27 + .../sirupsen/logrus/text_formatter.go | 339 + vendor/github.com/sirupsen/logrus/writer.go | 70 + vendor/github.com/spf13/afero/.gitignore | 2 + vendor/github.com/spf13/afero/.travis.yml | 26 + vendor/github.com/spf13/afero/LICENSE.txt | 174 + vendor/github.com/spf13/afero/README.md | 430 + vendor/github.com/spf13/afero/afero.go | 111 + vendor/github.com/spf13/afero/appveyor.yml | 15 + vendor/github.com/spf13/afero/basepath.go | 211 + .../github.com/spf13/afero/cacheOnReadFs.go | 311 + vendor/github.com/spf13/afero/const_bsds.go | 22 + .../github.com/spf13/afero/const_win_unix.go | 26 + .../github.com/spf13/afero/copyOnWriteFs.go | 326 + vendor/github.com/spf13/afero/go.mod | 9 + vendor/github.com/spf13/afero/go.sum | 29 + vendor/github.com/spf13/afero/httpFs.go | 114 + vendor/github.com/spf13/afero/iofs.go | 288 + vendor/github.com/spf13/afero/ioutil.go | 240 + vendor/github.com/spf13/afero/lstater.go | 27 + vendor/github.com/spf13/afero/match.go | 110 + vendor/github.com/spf13/afero/mem/dir.go | 37 + vendor/github.com/spf13/afero/mem/dirmap.go | 43 + vendor/github.com/spf13/afero/mem/file.go | 338 + vendor/github.com/spf13/afero/memmap.go | 404 + vendor/github.com/spf13/afero/os.go | 113 + vendor/github.com/spf13/afero/path.go | 106 + vendor/github.com/spf13/afero/readonlyfs.go | 96 + vendor/github.com/spf13/afero/regexpfs.go | 224 + vendor/github.com/spf13/afero/symlink.go | 55 + vendor/github.com/spf13/afero/unionFile.go | 317 + vendor/github.com/spf13/afero/util.go | 330 + vendor/github.com/spf13/cast/.gitignore | 25 + vendor/github.com/spf13/cast/LICENSE | 21 + vendor/github.com/spf13/cast/Makefile | 40 + vendor/github.com/spf13/cast/README.md | 75 + vendor/github.com/spf13/cast/cast.go | 176 + vendor/github.com/spf13/cast/caste.go | 1337 ++ vendor/github.com/spf13/cast/go.mod | 7 + vendor/github.com/spf13/cast/go.sum | 6 + .../spf13/cast/timeformattype_string.go | 27 + .../spf13/jwalterweatherman/.gitignore | 24 + .../spf13/jwalterweatherman/LICENSE | 21 + .../spf13/jwalterweatherman/README.md | 148 + .../jwalterweatherman/default_notepad.go | 111 + .../github.com/spf13/jwalterweatherman/go.mod | 7 + .../spf13/jwalterweatherman/log_counter.go | 46 + .../spf13/jwalterweatherman/notepad.go | 225 + vendor/github.com/spf13/pflag/.gitignore | 2 + vendor/github.com/spf13/pflag/.travis.yml | 22 + vendor/github.com/spf13/pflag/LICENSE | 28 + vendor/github.com/spf13/pflag/README.md | 296 + vendor/github.com/spf13/pflag/bool.go | 94 + vendor/github.com/spf13/pflag/bool_slice.go | 185 + vendor/github.com/spf13/pflag/bytes.go | 209 + vendor/github.com/spf13/pflag/count.go | 96 + vendor/github.com/spf13/pflag/duration.go | 86 + .../github.com/spf13/pflag/duration_slice.go | 166 + vendor/github.com/spf13/pflag/flag.go | 1239 ++ vendor/github.com/spf13/pflag/float32.go | 88 + .../github.com/spf13/pflag/float32_slice.go | 174 + vendor/github.com/spf13/pflag/float64.go | 84 + .../github.com/spf13/pflag/float64_slice.go | 166 + vendor/github.com/spf13/pflag/go.mod | 3 + vendor/github.com/spf13/pflag/go.sum | 0 vendor/github.com/spf13/pflag/golangflag.go | 105 + vendor/github.com/spf13/pflag/int.go | 84 + vendor/github.com/spf13/pflag/int16.go | 88 + vendor/github.com/spf13/pflag/int32.go | 88 + vendor/github.com/spf13/pflag/int32_slice.go | 174 + vendor/github.com/spf13/pflag/int64.go | 84 + vendor/github.com/spf13/pflag/int64_slice.go | 166 + vendor/github.com/spf13/pflag/int8.go | 88 + vendor/github.com/spf13/pflag/int_slice.go | 158 + vendor/github.com/spf13/pflag/ip.go | 94 + vendor/github.com/spf13/pflag/ip_slice.go | 186 + vendor/github.com/spf13/pflag/ipmask.go | 122 + vendor/github.com/spf13/pflag/ipnet.go | 98 + vendor/github.com/spf13/pflag/string.go | 80 + vendor/github.com/spf13/pflag/string_array.go | 129 + vendor/github.com/spf13/pflag/string_slice.go | 163 + .../github.com/spf13/pflag/string_to_int.go | 149 + .../github.com/spf13/pflag/string_to_int64.go | 149 + .../spf13/pflag/string_to_string.go | 160 + vendor/github.com/spf13/pflag/uint.go | 88 + vendor/github.com/spf13/pflag/uint16.go | 88 + vendor/github.com/spf13/pflag/uint32.go | 88 + vendor/github.com/spf13/pflag/uint64.go | 88 + vendor/github.com/spf13/pflag/uint8.go | 88 + vendor/github.com/spf13/pflag/uint_slice.go | 168 + vendor/github.com/spf13/viper/.editorconfig | 15 + vendor/github.com/spf13/viper/.gitignore | 5 + vendor/github.com/spf13/viper/.golangci.yml | 93 + vendor/github.com/spf13/viper/LICENSE | 21 + vendor/github.com/spf13/viper/Makefile | 76 + vendor/github.com/spf13/viper/README.md | 874 + .../github.com/spf13/viper/TROUBLESHOOTING.md | 23 + vendor/github.com/spf13/viper/flags.go | 57 + vendor/github.com/spf13/viper/fs.go | 65 + vendor/github.com/spf13/viper/go.mod | 69 + vendor/github.com/spf13/viper/go.sum | 819 + .../spf13/viper/internal/encoding/decoder.go | 61 + .../spf13/viper/internal/encoding/encoder.go | 60 + .../spf13/viper/internal/encoding/error.go | 7 + .../viper/internal/encoding/hcl/codec.go | 40 + .../viper/internal/encoding/json/codec.go | 17 + .../viper/internal/encoding/toml/codec.go | 45 + .../viper/internal/encoding/yaml/codec.go | 14 + vendor/github.com/spf13/viper/logger.go | 77 + vendor/github.com/spf13/viper/util.go | 204 + vendor/github.com/spf13/viper/viper.go | 2141 +++ vendor/github.com/spf13/viper/viper_go1_15.go | 57 + vendor/github.com/spf13/viper/viper_go1_16.go | 32 + vendor/github.com/spf13/viper/watch.go | 12 + vendor/github.com/spf13/viper/watch_wasm.go | 30 + vendor/github.com/subosito/gotenv/.env | 1 + .../github.com/subosito/gotenv/.env.invalid | 1 + vendor/github.com/subosito/gotenv/.gitignore | 3 + vendor/github.com/subosito/gotenv/.travis.yml | 10 + .../github.com/subosito/gotenv/CHANGELOG.md | 47 + vendor/github.com/subosito/gotenv/LICENSE | 21 + vendor/github.com/subosito/gotenv/README.md | 131 + .../github.com/subosito/gotenv/appveyor.yml | 9 + vendor/github.com/subosito/gotenv/gotenv.go | 265 + .../github.com/vishvananda/netlink/.gitignore | 1 + .../vishvananda/netlink/.travis.yml | 20 + .../vishvananda/netlink/CHANGELOG.md | 5 + vendor/github.com/vishvananda/netlink/LICENSE | 192 + .../github.com/vishvananda/netlink/Makefile | 30 + .../github.com/vishvananda/netlink/README.md | 92 + vendor/github.com/vishvananda/netlink/addr.go | 57 + .../vishvananda/netlink/addr_linux.go | 414 + .../vishvananda/netlink/bpf_linux.go | 53 + .../vishvananda/netlink/bridge_linux.go | 112 + .../github.com/vishvananda/netlink/class.go | 239 + .../vishvananda/netlink/class_linux.go | 397 + .../vishvananda/netlink/conntrack_linux.go | 454 + .../netlink/conntrack_unspecified.go | 53 + .../vishvananda/netlink/devlink_linux.go | 393 + .../github.com/vishvananda/netlink/filter.go | 325 + .../vishvananda/netlink/filter_linux.go | 815 + vendor/github.com/vishvananda/netlink/fou.go | 21 + .../vishvananda/netlink/fou_linux.go | 211 + .../vishvananda/netlink/fou_unspecified.go | 15 + .../vishvananda/netlink/genetlink_linux.go | 171 + .../netlink/genetlink_unspecified.go | 25 + vendor/github.com/vishvananda/netlink/go.mod | 8 + vendor/github.com/vishvananda/netlink/go.sum | 6 + .../vishvananda/netlink/gtp_linux.go | 239 + .../vishvananda/netlink/handle_linux.go | 160 + .../vishvananda/netlink/handle_unspecified.go | 274 + .../vishvananda/netlink/inet_diag.go | 31 + .../vishvananda/netlink/ioctl_linux.go | 90 + .../vishvananda/netlink/ipset_linux.go | 365 + vendor/github.com/vishvananda/netlink/link.go | 1275 ++ .../vishvananda/netlink/link_linux.go | 3305 ++++ .../vishvananda/netlink/link_tuntap_linux.go | 14 + .../github.com/vishvananda/netlink/neigh.go | 32 + .../vishvananda/netlink/neigh_linux.go | 434 + .../github.com/vishvananda/netlink/netlink.go | 40 + .../vishvananda/netlink/netlink_linux.go | 11 + .../netlink/netlink_unspecified.go | 241 + .../vishvananda/netlink/netns_linux.go | 141 + .../vishvananda/netlink/netns_unspecified.go | 19 + .../vishvananda/netlink/nl/addr_linux.go | 71 + .../vishvananda/netlink/nl/bridge_linux.go | 74 + .../vishvananda/netlink/nl/conntrack_linux.go | 218 + .../vishvananda/netlink/nl/devlink_linux.go | 63 + .../vishvananda/netlink/nl/genetlink_linux.go | 89 + .../vishvananda/netlink/nl/ipset_linux.go | 222 + .../vishvananda/netlink/nl/link_linux.go | 711 + .../vishvananda/netlink/nl/mpls_linux.go | 36 + .../vishvananda/netlink/nl/nl_linux.go | 791 + .../vishvananda/netlink/nl/nl_unspecified.go | 11 + .../netlink/nl/parse_attr_linux.go | 79 + .../vishvananda/netlink/nl/rdma_link_linux.go | 35 + .../vishvananda/netlink/nl/route_linux.go | 107 + .../vishvananda/netlink/nl/seg6_linux.go | 154 + .../vishvananda/netlink/nl/seg6local_linux.go | 76 + .../vishvananda/netlink/nl/syscall.go | 76 + .../vishvananda/netlink/nl/tc_linux.go | 983 + .../vishvananda/netlink/nl/xfrm_linux.go | 306 + .../netlink/nl/xfrm_monitor_linux.go | 32 + .../netlink/nl/xfrm_policy_linux.go | 119 + .../netlink/nl/xfrm_state_linux.go | 334 + .../github.com/vishvananda/netlink/order.go | 32 + .../vishvananda/netlink/protinfo.go | 62 + .../vishvananda/netlink/protinfo_linux.go | 74 + .../github.com/vishvananda/netlink/qdisc.go | 366 + .../vishvananda/netlink/qdisc_linux.go | 713 + .../vishvananda/netlink/rdma_link_linux.go | 280 + .../github.com/vishvananda/netlink/route.go | 205 + .../vishvananda/netlink/route_linux.go | 1390 ++ .../vishvananda/netlink/route_unspecified.go | 21 + vendor/github.com/vishvananda/netlink/rule.go | 56 + .../vishvananda/netlink/rule_linux.go | 296 + .../github.com/vishvananda/netlink/socket.go | 27 + .../vishvananda/netlink/socket_linux.go | 261 + vendor/github.com/vishvananda/netlink/tcp.go | 84 + .../vishvananda/netlink/tcp_linux.go | 353 + vendor/github.com/vishvananda/netlink/xfrm.go | 75 + .../vishvananda/netlink/xfrm_monitor_linux.go | 101 + .../vishvananda/netlink/xfrm_policy.go | 97 + .../vishvananda/netlink/xfrm_policy_linux.go | 265 + .../vishvananda/netlink/xfrm_state.go | 131 + .../vishvananda/netlink/xfrm_state_linux.go | 477 + vendor/github.com/vishvananda/netns/LICENSE | 192 + vendor/github.com/vishvananda/netns/README.md | 50 + vendor/github.com/vishvananda/netns/go.mod | 5 + vendor/github.com/vishvananda/netns/go.sum | 2 + vendor/github.com/vishvananda/netns/netns.go | 81 + .../vishvananda/netns/netns_linux.go | 260 + .../vishvananda/netns/netns_unspecified.go | 43 + vendor/golang.org/x/crypto/ed25519/ed25519.go | 1 + .../x/crypto/ed25519/ed25519_go113.go | 1 + vendor/golang.org/x/net/context/go17.go | 1 + vendor/golang.org/x/net/context/go19.go | 1 + vendor/golang.org/x/net/context/pre_go17.go | 1 + vendor/golang.org/x/net/context/pre_go19.go | 1 + .../golang.org/x/net/http/httpguts/httplex.go | 10 +- vendor/golang.org/x/net/http2/Dockerfile | 2 +- vendor/golang.org/x/net/http2/README | 20 - vendor/golang.org/x/net/http2/ascii.go | 53 + .../x/net/http2/client_conn_pool.go | 120 +- vendor/golang.org/x/net/http2/errors.go | 12 + vendor/golang.org/x/net/http2/frame.go | 62 +- vendor/golang.org/x/net/http2/go111.go | 1 + vendor/golang.org/x/net/http2/go115.go | 27 + vendor/golang.org/x/net/http2/go118.go | 17 + vendor/golang.org/x/net/http2/headermap.go | 7 +- .../golang.org/x/net/http2/hpack/huffman.go | 38 +- vendor/golang.org/x/net/http2/not_go111.go | 1 + vendor/golang.org/x/net/http2/not_go115.go | 31 + vendor/golang.org/x/net/http2/not_go118.go | 17 + vendor/golang.org/x/net/http2/pipe.go | 11 + vendor/golang.org/x/net/http2/server.go | 190 +- vendor/golang.org/x/net/http2/transport.go | 1656 +- vendor/golang.org/x/net/http2/write.go | 7 +- vendor/golang.org/x/net/http2/writesched.go | 4 +- .../x/net/http2/writesched_random.go | 6 +- vendor/golang.org/x/net/idna/go118.go | 14 + vendor/golang.org/x/net/idna/idna10.0.0.go | 118 +- vendor/golang.org/x/net/idna/idna9.0.0.go | 98 +- vendor/golang.org/x/net/idna/pre_go118.go | 12 + vendor/golang.org/x/net/idna/punycode.go | 36 +- vendor/golang.org/x/net/idna/tables10.0.0.go | 1 + vendor/golang.org/x/net/idna/tables11.0.0.go | 1 + .../idna/{tables12.00.go => tables12.0.0.go} | 3 +- vendor/golang.org/x/net/idna/tables13.0.0.go | 4840 +++++ vendor/golang.org/x/net/idna/tables9.0.0.go | 1 + .../x/text/secure/bidirule/bidirule10.0.0.go | 1 + .../x/text/secure/bidirule/bidirule9.0.0.go | 1 + vendor/golang.org/x/text/unicode/bidi/bidi.go | 221 +- vendor/golang.org/x/text/unicode/bidi/core.go | 63 +- .../x/text/unicode/bidi/tables10.0.0.go | 1 + .../x/text/unicode/bidi/tables11.0.0.go | 1 + .../x/text/unicode/bidi/tables12.0.0.go | 3 +- .../x/text/unicode/bidi/tables13.0.0.go | 1956 ++ .../x/text/unicode/bidi/tables9.0.0.go | 1 + .../x/text/unicode/norm/tables10.0.0.go | 1 + .../x/text/unicode/norm/tables11.0.0.go | 1 + .../x/text/unicode/norm/tables12.0.0.go | 3 +- .../x/text/unicode/norm/tables13.0.0.go | 7761 ++++++++ .../x/text/unicode/norm/tables9.0.0.go | 1 + .../googleapis/rpc/status/status.pb.go | 19 +- vendor/google.golang.org/grpc/.travis.yml | 42 - vendor/google.golang.org/grpc/CONTRIBUTING.md | 7 +- vendor/google.golang.org/grpc/MAINTAINERS.md | 5 +- vendor/google.golang.org/grpc/Makefile | 32 +- vendor/google.golang.org/grpc/NOTICE.txt | 13 + vendor/google.golang.org/grpc/README.md | 2 +- vendor/google.golang.org/grpc/SECURITY.md | 3 + .../grpc/attributes/attributes.go | 80 +- .../grpc/balancer/balancer.go | 133 +- .../grpc/balancer/base/balancer.go | 45 +- .../grpc/balancer/conn_state_evaluator.go | 70 + .../grpc/balancer/grpclb/state/state.go | 2 +- .../grpc/balancer/roundrobin/roundrobin.go | 20 +- .../grpc/balancer_conn_wrappers.go | 320 +- .../grpc_binarylog_v1/binarylog.pb.go | 1249 +- .../grpc/channelz/channelz.go | 36 + vendor/google.golang.org/grpc/clientconn.go | 969 +- .../grpc/connectivity/connectivity.go | 35 +- .../grpc/credentials/credentials.go | 68 +- .../grpc/credentials/go12.go | 30 - .../grpc/credentials/insecure/insecure.go | 98 + .../google.golang.org/grpc/credentials/tls.go | 3 + vendor/google.golang.org/grpc/dialoptions.go | 168 +- .../grpc/encoding/encoding.go | 2 +- .../grpc/encoding/proto/proto.go | 70 +- vendor/google.golang.org/grpc/go.mod | 30 +- vendor/google.golang.org/grpc/go.sum | 108 +- .../grpc/grpclog/loggerv2.go | 94 +- vendor/google.golang.org/grpc/install_gae.sh | 6 - vendor/google.golang.org/grpc/interceptor.go | 45 +- .../balancer/gracefulswitch/gracefulswitch.go | 384 + .../grpc/internal/binarylog/binarylog.go | 107 +- .../grpc/internal/binarylog/env_config.go | 8 +- .../grpc/internal/binarylog/method_logger.go | 29 +- .../grpc/internal/binarylog/sink.go | 41 +- .../grpc/internal/channelz/funcs.go | 240 +- .../grpc/internal/channelz/id.go | 75 + .../grpc/internal/channelz/logging.go | 91 +- .../grpc/internal/channelz/types.go | 23 +- .../grpc/internal/channelz/types_linux.go | 2 - .../grpc/internal/channelz/types_nonlinux.go | 5 +- .../grpc/internal/channelz/util_linux.go | 2 - .../grpc/internal/channelz/util_nonlinux.go | 3 +- .../grpc/internal/credentials/credentials.go | 49 + .../grpc/internal/credentials/spiffe.go | 18 +- .../internal/credentials/spiffe_appengine.go | 31 - .../grpc/internal/credentials/syscallconn.go | 2 - .../grpc/internal/credentials/util.go | 4 +- .../grpc/internal/envconfig/envconfig.go | 3 - .../grpc/internal/envconfig/observability.go | 36 + .../grpc/internal/envconfig/xds.go | 101 + .../grpc/internal/grpclog/grpclog.go | 8 +- .../grpc/internal/grpcrand/grpcrand.go | 36 +- .../grpcutil.go} | 16 +- .../grpc/internal/grpcutil/method.go | 5 + .../dns/go113.go => grpcutil/regex.go} | 22 +- .../grpc/internal/grpcutil/target.go | 55 - .../grpc/internal/internal.go | 96 +- .../grpc/internal/metadata/metadata.go | 120 + .../grpc/internal/pretty/pretty.go | 82 + .../grpc/internal/resolver/config_selector.go | 167 + .../internal/resolver/dns/dns_resolver.go | 52 +- .../grpc/internal/resolver/unix/unix.go | 74 + .../internal/serviceconfig/serviceconfig.go | 76 +- .../grpc/internal/status/status.go | 14 +- .../grpc/internal/syscall/syscall_linux.go | 22 +- .../grpc/internal/syscall/syscall_nonlinux.go | 23 +- .../grpc/internal/transport/controlbuf.go | 70 +- .../grpc/internal/transport/flowcontrol.go | 4 +- .../grpc/internal/transport/handler_server.go | 25 +- .../grpc/internal/transport/http2_client.go | 520 +- .../grpc/internal/transport/http2_server.go | 449 +- .../grpc/internal/transport/http_util.go | 284 +- .../transport/networktype/networktype.go | 46 + .../grpc/{ => internal/transport}/proxy.go | 54 +- .../grpc/internal/transport/transport.go | 41 +- .../grpc/internal/xds_handshake_cluster.go | 40 + .../grpc/metadata/metadata.go | 143 +- .../google.golang.org/grpc/picker_wrapper.go | 12 +- vendor/google.golang.org/grpc/pickfirst.go | 135 +- vendor/google.golang.org/grpc/regenerate.sh | 81 +- vendor/google.golang.org/grpc/resolver/map.go | 138 + .../grpc/resolver/resolver.go | 64 +- .../grpc/resolver_conn_wrapper.go | 94 +- vendor/google.golang.org/grpc/rpc_util.go | 100 +- vendor/google.golang.org/grpc/server.go | 552 +- .../google.golang.org/grpc/service_config.go | 86 +- vendor/google.golang.org/grpc/stats/stats.go | 11 +- .../google.golang.org/grpc/status/status.go | 32 +- vendor/google.golang.org/grpc/stream.go | 585 +- vendor/google.golang.org/grpc/tap/tap.go | 16 +- vendor/google.golang.org/grpc/version.go | 2 +- vendor/google.golang.org/grpc/vet.sh | 93 +- vendor/google.golang.org/protobuf/AUTHORS | 3 - .../google.golang.org/protobuf/CONTRIBUTORS | 3 - .../protobuf/encoding/protojson/decode.go | 665 + .../protobuf/encoding/protojson/doc.go | 11 + .../protobuf/encoding/protojson/encode.go | 343 + .../encoding/protojson/well_known_types.go | 889 + .../protobuf/encoding/prototext/decode.go | 147 +- .../protobuf/encoding/prototext/encode.go | 121 +- .../protobuf/encoding/protowire/wire.go | 23 +- .../protobuf/internal/descfmt/stringer.go | 68 +- .../protobuf/internal/detrand/rand.go | 8 + .../internal/encoding/defval/default.go | 78 +- .../protobuf/internal/encoding/json/decode.go | 340 + .../internal/encoding/json/decode_number.go | 254 + .../internal/encoding/json/decode_string.go | 91 + .../internal/encoding/json/decode_token.go | 192 + .../protobuf/internal/encoding/json/encode.go | 276 + .../encoding/messageset/messageset.go | 40 +- .../protobuf/internal/encoding/tag/tag.go | 98 +- .../protobuf/internal/encoding/text/decode.go | 32 +- .../internal/encoding/text/decode_number.go | 6 +- .../protobuf/internal/encoding/text/doc.go | 4 +- .../protobuf/internal/encoding/text/encode.go | 13 +- .../protobuf/internal/errors/is_go112.go | 1 + .../protobuf/internal/errors/is_go113.go | 1 + .../protobuf/internal/fieldsort/fieldsort.go | 40 - .../protobuf/internal/filedesc/build.go | 22 +- .../protobuf/internal/filedesc/desc.go | 437 +- .../protobuf/internal/filedesc/desc_init.go | 36 +- .../protobuf/internal/filedesc/desc_lazy.go | 84 +- .../protobuf/internal/filedesc/desc_list.go | 257 +- .../internal/filedesc/desc_list_gen.go | 11 + .../protobuf/internal/filedesc/placeholder.go | 136 +- .../protobuf/internal/filetype/build.go | 87 +- .../internal/flags/proto_legacy_disable.go | 1 + .../internal/flags/proto_legacy_enable.go | 1 + .../protobuf/internal/impl/api_export.go | 44 +- .../protobuf/internal/impl/checkinit.go | 12 +- .../protobuf/internal/impl/codec_extension.go | 36 +- .../protobuf/internal/impl/codec_field.go | 104 +- .../protobuf/internal/impl/codec_gen.go | 974 +- .../protobuf/internal/impl/codec_map.go | 39 +- .../protobuf/internal/impl/codec_map_go111.go | 1 + .../protobuf/internal/impl/codec_map_go112.go | 1 + .../protobuf/internal/impl/codec_message.go | 98 +- .../internal/impl/codec_messageset.go | 21 +- .../protobuf/internal/impl/codec_reflect.go | 9 +- .../protobuf/internal/impl/codec_tables.go | 290 +- .../protobuf/internal/impl/codec_unsafe.go | 1 + .../protobuf/internal/impl/convert.go | 257 +- .../protobuf/internal/impl/convert_list.go | 42 +- .../protobuf/internal/impl/convert_map.go | 32 +- .../protobuf/internal/impl/decode.go | 45 +- .../protobuf/internal/impl/encode.go | 10 +- .../protobuf/internal/impl/enum.go | 10 +- .../protobuf/internal/impl/extension.go | 26 +- .../protobuf/internal/impl/legacy_enum.go | 57 +- .../protobuf/internal/impl/legacy_export.go | 20 +- .../internal/impl/legacy_extension.go | 99 +- .../protobuf/internal/impl/legacy_message.go | 233 +- .../protobuf/internal/impl/merge.go | 38 +- .../protobuf/internal/impl/message.go | 106 +- .../protobuf/internal/impl/message_reflect.go | 191 +- .../internal/impl/message_reflect_field.go | 191 +- .../protobuf/internal/impl/pointer_reflect.go | 2 + .../protobuf/internal/impl/pointer_unsafe.go | 2 + .../protobuf/internal/impl/validate.go | 50 +- .../protobuf/internal/impl/weak.go | 16 +- .../protobuf/internal/mapsort/mapsort.go | 43 - .../protobuf/internal/order/order.go | 89 + .../protobuf/internal/order/range.go | 115 + .../protobuf/internal/strs/strings_pure.go | 1 + .../protobuf/internal/strs/strings_unsafe.go | 7 +- .../protobuf/internal/version/version.go | 56 +- .../protobuf/proto/decode.go | 38 +- .../protobuf/proto/decode_gen.go | 128 +- .../google.golang.org/protobuf/proto/doc.go | 21 +- .../protobuf/proto/encode.go | 60 +- .../google.golang.org/protobuf/proto/equal.go | 53 +- .../protobuf/proto/messageset.go | 7 +- .../google.golang.org/protobuf/proto/proto.go | 9 + .../protobuf/proto/proto_methods.go | 1 + .../protobuf/proto/proto_reflect.go | 1 + .../protobuf/reflect/protodesc/desc.go | 276 + .../protobuf/reflect/protodesc/desc_init.go | 248 + .../reflect/protodesc/desc_resolve.go | 286 + .../reflect/protodesc/desc_validate.go | 374 + .../protobuf/reflect/protodesc/proto.go | 252 + .../protobuf/reflect/protoreflect/methods.go | 1 + .../protobuf/reflect/protoreflect/proto.go | 32 +- .../protobuf/reflect/protoreflect/source.go | 85 +- .../reflect/protoreflect/source_gen.go | 461 + .../protobuf/reflect/protoreflect/type.go | 35 + .../reflect/protoreflect/value_pure.go | 1 + .../reflect/protoreflect/value_union.go | 27 + .../reflect/protoreflect/value_unsafe.go | 1 + .../reflect/protoregistry/registry.go | 202 +- .../protobuf/runtime/protoiface/methods.go | 1 + .../protobuf/runtime/protoimpl/version.go | 8 +- .../types/descriptorpb/descriptor.pb.go | 3957 ++++ .../protobuf/types/known/anypb/any.pb.go | 22 +- .../types/known/durationpb/duration.pb.go | 20 +- .../protobuf/types/known/emptypb/empty.pb.go | 168 + .../types/known/timestamppb/timestamp.pb.go | 29 +- vendor/gopkg.in/ini.v1/.gitignore | 6 + vendor/gopkg.in/ini.v1/.golangci.yml | 21 + vendor/gopkg.in/ini.v1/LICENSE | 191 + vendor/gopkg.in/ini.v1/Makefile | 15 + vendor/gopkg.in/ini.v1/README.md | 43 + vendor/gopkg.in/ini.v1/codecov.yml | 9 + vendor/gopkg.in/ini.v1/data_source.go | 76 + vendor/gopkg.in/ini.v1/deprecated.go | 25 + vendor/gopkg.in/ini.v1/error.go | 34 + vendor/gopkg.in/ini.v1/file.go | 524 + vendor/gopkg.in/ini.v1/helper.go | 24 + vendor/gopkg.in/ini.v1/ini.go | 176 + vendor/gopkg.in/ini.v1/key.go | 828 + vendor/gopkg.in/ini.v1/parser.go | 513 + vendor/gopkg.in/ini.v1/section.go | 256 + vendor/gopkg.in/ini.v1/struct.go | 747 + vendor/gopkg.in/yaml.v2/.travis.yml | 17 + vendor/gopkg.in/yaml.v2/LICENSE | 201 + vendor/gopkg.in/yaml.v2/LICENSE.libyaml | 31 + vendor/gopkg.in/yaml.v2/NOTICE | 13 + vendor/gopkg.in/yaml.v2/README.md | 133 + vendor/gopkg.in/yaml.v2/apic.go | 744 + vendor/gopkg.in/yaml.v2/decode.go | 815 + vendor/gopkg.in/yaml.v2/emitterc.go | 1685 ++ vendor/gopkg.in/yaml.v2/encode.go | 390 + vendor/gopkg.in/yaml.v2/go.mod | 5 + vendor/gopkg.in/yaml.v2/parserc.go | 1095 ++ vendor/gopkg.in/yaml.v2/readerc.go | 412 + vendor/gopkg.in/yaml.v2/resolve.go | 258 + vendor/gopkg.in/yaml.v2/scannerc.go | 2711 +++ vendor/gopkg.in/yaml.v2/sorter.go | 113 + vendor/gopkg.in/yaml.v2/writerc.go | 26 + vendor/gopkg.in/yaml.v2/yaml.go | 478 + vendor/gopkg.in/yaml.v2/yamlh.go | 739 + vendor/gopkg.in/yaml.v2/yamlprivateh.go | 173 + vendor/modules.txt | 135 +- 831 files changed, 199239 insertions(+), 7974 deletions(-) create mode 100644 bgp/bgp.go create mode 100644 bgp/bgp_test.go create mode 100644 bgp/logger.go create mode 100644 bgp/test_data/bgp.toml create mode 100644 docs/content/feature/bgp.md create mode 100644 docs/content/ref/bgp.anycastaddresses.md create mode 100644 docs/content/ref/bgp.asn.md create mode 100644 docs/content/ref/bgp.certfile.md create mode 100644 docs/content/ref/bgp.enabled.md create mode 100644 docs/content/ref/bgp.enablegrpc.md create mode 100644 docs/content/ref/bgp.gobgpdcfgfile.md create mode 100644 docs/content/ref/bgp.grpclistenaddress.md create mode 100644 docs/content/ref/bgp.grpctls.md create mode 100644 docs/content/ref/bgp.keyfile.md create mode 100644 docs/content/ref/bgp.listenaddresses.md create mode 100644 docs/content/ref/bgp.listenport.md create mode 100644 docs/content/ref/bgp.nexthop.md create mode 100644 docs/content/ref/bgp.peers.md create mode 100644 docs/content/ref/bgp.routerid.md delete mode 100644 vendor/github.com/cespare/xxhash/v2/.travis.yml create mode 100644 vendor/github.com/dgryski/go-farm/.gitignore create mode 100644 vendor/github.com/dgryski/go-farm/.travis.yml create mode 100644 vendor/github.com/dgryski/go-farm/LICENSE create mode 100644 vendor/github.com/dgryski/go-farm/Makefile create mode 100644 vendor/github.com/dgryski/go-farm/README.md create mode 100644 vendor/github.com/dgryski/go-farm/VERSION create mode 100644 vendor/github.com/dgryski/go-farm/basics.go create mode 100644 vendor/github.com/dgryski/go-farm/farmhashcc.go create mode 100644 vendor/github.com/dgryski/go-farm/farmhashmk.go create mode 100644 vendor/github.com/dgryski/go-farm/farmhashna.go create mode 100644 vendor/github.com/dgryski/go-farm/farmhashuo.go create mode 100644 vendor/github.com/dgryski/go-farm/farmhashxo.go create mode 100644 vendor/github.com/dgryski/go-farm/fp_amd64.s create mode 100644 vendor/github.com/dgryski/go-farm/fp_generic.go create mode 100644 vendor/github.com/dgryski/go-farm/fp_stub.go create mode 100644 vendor/github.com/eapache/channels/.gitignore create mode 100644 vendor/github.com/eapache/channels/.travis.yml create mode 100644 vendor/github.com/eapache/channels/CHANGELOG.md create mode 100644 vendor/github.com/eapache/channels/LICENSE create mode 100644 vendor/github.com/eapache/channels/README.md create mode 100644 vendor/github.com/eapache/channels/batching_channel.go create mode 100644 vendor/github.com/eapache/channels/black_hole.go create mode 100644 vendor/github.com/eapache/channels/channels.go create mode 100644 vendor/github.com/eapache/channels/infinite_channel.go create mode 100644 vendor/github.com/eapache/channels/native_channel.go create mode 100644 vendor/github.com/eapache/channels/overflowing_channel.go create mode 100644 vendor/github.com/eapache/channels/resizable_channel.go create mode 100644 vendor/github.com/eapache/channels/ring_channel.go create mode 100644 vendor/github.com/eapache/channels/shared_buffer.go create mode 100644 vendor/github.com/fsnotify/fsnotify/.editorconfig create mode 100644 vendor/github.com/fsnotify/fsnotify/.gitattributes create mode 100644 vendor/github.com/fsnotify/fsnotify/.gitignore create mode 100644 vendor/github.com/fsnotify/fsnotify/.mailmap create mode 100644 vendor/github.com/fsnotify/fsnotify/AUTHORS create mode 100644 vendor/github.com/fsnotify/fsnotify/CHANGELOG.md create mode 100644 vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md create mode 100644 vendor/github.com/fsnotify/fsnotify/LICENSE create mode 100644 vendor/github.com/fsnotify/fsnotify/README.md create mode 100644 vendor/github.com/fsnotify/fsnotify/fen.go create mode 100644 vendor/github.com/fsnotify/fsnotify/fsnotify.go create mode 100644 vendor/github.com/fsnotify/fsnotify/go.mod create mode 100644 vendor/github.com/fsnotify/fsnotify/go.sum create mode 100644 vendor/github.com/fsnotify/fsnotify/inotify.go create mode 100644 vendor/github.com/fsnotify/fsnotify/inotify_poller.go create mode 100644 vendor/github.com/fsnotify/fsnotify/kqueue.go create mode 100644 vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go create mode 100644 vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go create mode 100644 vendor/github.com/fsnotify/fsnotify/windows.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/decode.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/encode.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/json.go create mode 100644 vendor/github.com/google/uuid/.travis.yml create mode 100644 vendor/github.com/google/uuid/CONTRIBUTING.md create mode 100644 vendor/github.com/google/uuid/CONTRIBUTORS create mode 100644 vendor/github.com/google/uuid/LICENSE create mode 100644 vendor/github.com/google/uuid/README.md create mode 100644 vendor/github.com/google/uuid/dce.go create mode 100644 vendor/github.com/google/uuid/doc.go create mode 100644 vendor/github.com/google/uuid/go.mod create mode 100644 vendor/github.com/google/uuid/hash.go create mode 100644 vendor/github.com/google/uuid/marshal.go create mode 100644 vendor/github.com/google/uuid/node.go create mode 100644 vendor/github.com/google/uuid/node_js.go create mode 100644 vendor/github.com/google/uuid/node_net.go create mode 100644 vendor/github.com/google/uuid/null.go create mode 100644 vendor/github.com/google/uuid/sql.go create mode 100644 vendor/github.com/google/uuid/time.go create mode 100644 vendor/github.com/google/uuid/util.go create mode 100644 vendor/github.com/google/uuid/uuid.go create mode 100644 vendor/github.com/google/uuid/version1.go create mode 100644 vendor/github.com/google/uuid/version4.go create mode 100644 vendor/github.com/hashicorp/consul/api/config_entry_exports.go create mode 100644 vendor/github.com/hashicorp/consul/api/config_entry_intentions.go create mode 100644 vendor/github.com/hashicorp/consul/api/config_entry_mesh.go create mode 100644 vendor/github.com/hashicorp/consul/api/partition.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/.travis.yml create mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/nodes.go create mode 100644 vendor/github.com/hashicorp/hcl/hcl/printer/printer.go create mode 100644 vendor/github.com/k-sone/critbitgo/.travis.yml create mode 100644 vendor/github.com/k-sone/critbitgo/CHANGES.md create mode 100644 vendor/github.com/k-sone/critbitgo/LICENSE create mode 100644 vendor/github.com/k-sone/critbitgo/README.md create mode 100644 vendor/github.com/k-sone/critbitgo/critbit.go create mode 100644 vendor/github.com/k-sone/critbitgo/map.go create mode 100644 vendor/github.com/k-sone/critbitgo/net.go delete mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml delete mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml delete mode 100644 vendor/github.com/mattn/go-isatty/renovate.json delete mode 100644 vendor/github.com/mitchellh/mapstructure/.travis.yml create mode 100644 vendor/github.com/osrg/gobgp/v3/LICENSE create mode 100644 vendor/github.com/osrg/gobgp/v3/api/attribute.pb.go create mode 100644 vendor/github.com/osrg/gobgp/v3/api/attribute.proto create mode 100644 vendor/github.com/osrg/gobgp/v3/api/capability.pb.go create mode 100644 vendor/github.com/osrg/gobgp/v3/api/capability.proto create mode 100644 vendor/github.com/osrg/gobgp/v3/api/gobgp.pb.go create mode 100644 vendor/github.com/osrg/gobgp/v3/api/gobgp.proto create mode 100644 vendor/github.com/osrg/gobgp/v3/api/gobgp_grpc.pb.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/bgp_configs.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_linux.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/default_nonlinux.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/serve.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/config/util.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/adj.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/destination.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/message.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/path.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/policy.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/roa.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/table_manager.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/table/vrf.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/version/version.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/afi_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/apitype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/linktype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/lsptype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthopflag_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/nexthoptype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmenable_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/ptmstatus_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/routetype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/safi_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_bsd.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_darwin.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_linux.go create mode 100644 vendor/github.com/osrg/gobgp/v3/internal/pkg/zebra/zapi_windows.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/apiutil/attribute.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/apiutil/capability.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/apiutil/util.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/config/config.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/log/logger.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgp.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/bgpattrtype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/constant.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/esitype_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/fsmstate_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/helper.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/mup.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/prefix_sid.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/sr_policy.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/srbehavior.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/srbehavior_string.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bgp/validate.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/bmp/bmp.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/mrt/mrt.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/packet/rtr/rtr.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/bmp.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/fsm.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/grpc_server.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/mrt.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/peer.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/rpki.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/server.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt_bsd.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt_darwin.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt_linux.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt_openbsd.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/sockopt_stub.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/util.go create mode 100644 vendor/github.com/osrg/gobgp/v3/pkg/server/zclient.go create mode 100644 vendor/github.com/pelletier/go-toml/.dockerignore create mode 100644 vendor/github.com/pelletier/go-toml/.gitignore create mode 100644 vendor/github.com/pelletier/go-toml/CONTRIBUTING.md create mode 100644 vendor/github.com/pelletier/go-toml/Dockerfile create mode 100644 vendor/github.com/pelletier/go-toml/LICENSE create mode 100644 vendor/github.com/pelletier/go-toml/Makefile create mode 100644 vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md create mode 100644 vendor/github.com/pelletier/go-toml/README.md create mode 100644 vendor/github.com/pelletier/go-toml/azure-pipelines.yml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.sh create mode 100644 vendor/github.com/pelletier/go-toml/doc.go create mode 100644 vendor/github.com/pelletier/go-toml/example-crlf.toml create mode 100644 vendor/github.com/pelletier/go-toml/example.toml create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.go create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.sh create mode 100644 vendor/github.com/pelletier/go-toml/go.mod create mode 100644 vendor/github.com/pelletier/go-toml/keysparsing.go create mode 100644 vendor/github.com/pelletier/go-toml/lexer.go create mode 100644 vendor/github.com/pelletier/go-toml/localtime.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml create mode 100644 vendor/github.com/pelletier/go-toml/marshal_test.toml create mode 100644 vendor/github.com/pelletier/go-toml/parser.go create mode 100644 vendor/github.com/pelletier/go-toml/position.go create mode 100644 vendor/github.com/pelletier/go-toml/token.go create mode 100644 vendor/github.com/pelletier/go-toml/toml.go create mode 100644 vendor/github.com/pelletier/go-toml/tomlpub.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_create.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_write.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_writepub.go create mode 100644 vendor/github.com/sirupsen/logrus/.gitignore create mode 100644 vendor/github.com/sirupsen/logrus/.golangci.yml create mode 100644 vendor/github.com/sirupsen/logrus/.travis.yml create mode 100644 vendor/github.com/sirupsen/logrus/CHANGELOG.md create mode 100644 vendor/github.com/sirupsen/logrus/LICENSE create mode 100644 vendor/github.com/sirupsen/logrus/README.md create mode 100644 vendor/github.com/sirupsen/logrus/alt_exit.go create mode 100644 vendor/github.com/sirupsen/logrus/appveyor.yml create mode 100644 vendor/github.com/sirupsen/logrus/buffer_pool.go create mode 100644 vendor/github.com/sirupsen/logrus/doc.go create mode 100644 vendor/github.com/sirupsen/logrus/entry.go create mode 100644 vendor/github.com/sirupsen/logrus/exported.go create mode 100644 vendor/github.com/sirupsen/logrus/formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/go.mod create mode 100644 vendor/github.com/sirupsen/logrus/go.sum create mode 100644 vendor/github.com/sirupsen/logrus/hooks.go create mode 100644 vendor/github.com/sirupsen/logrus/json_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/logger.go create mode 100644 vendor/github.com/sirupsen/logrus/logrus.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_appengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_bsd.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_js.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_solaris.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_unix.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_windows.go create mode 100644 vendor/github.com/sirupsen/logrus/text_formatter.go create mode 100644 vendor/github.com/sirupsen/logrus/writer.go create mode 100644 vendor/github.com/spf13/afero/.gitignore create mode 100644 vendor/github.com/spf13/afero/.travis.yml create mode 100644 vendor/github.com/spf13/afero/LICENSE.txt create mode 100644 vendor/github.com/spf13/afero/README.md create mode 100644 vendor/github.com/spf13/afero/afero.go create mode 100644 vendor/github.com/spf13/afero/appveyor.yml create mode 100644 vendor/github.com/spf13/afero/basepath.go create mode 100644 vendor/github.com/spf13/afero/cacheOnReadFs.go create mode 100644 vendor/github.com/spf13/afero/const_bsds.go create mode 100644 vendor/github.com/spf13/afero/const_win_unix.go create mode 100644 vendor/github.com/spf13/afero/copyOnWriteFs.go create mode 100644 vendor/github.com/spf13/afero/go.mod create mode 100644 vendor/github.com/spf13/afero/go.sum create mode 100644 vendor/github.com/spf13/afero/httpFs.go create mode 100644 vendor/github.com/spf13/afero/iofs.go create mode 100644 vendor/github.com/spf13/afero/ioutil.go create mode 100644 vendor/github.com/spf13/afero/lstater.go create mode 100644 vendor/github.com/spf13/afero/match.go create mode 100644 vendor/github.com/spf13/afero/mem/dir.go create mode 100644 vendor/github.com/spf13/afero/mem/dirmap.go create mode 100644 vendor/github.com/spf13/afero/mem/file.go create mode 100644 vendor/github.com/spf13/afero/memmap.go create mode 100644 vendor/github.com/spf13/afero/os.go create mode 100644 vendor/github.com/spf13/afero/path.go create mode 100644 vendor/github.com/spf13/afero/readonlyfs.go create mode 100644 vendor/github.com/spf13/afero/regexpfs.go create mode 100644 vendor/github.com/spf13/afero/symlink.go create mode 100644 vendor/github.com/spf13/afero/unionFile.go create mode 100644 vendor/github.com/spf13/afero/util.go create mode 100644 vendor/github.com/spf13/cast/.gitignore create mode 100644 vendor/github.com/spf13/cast/LICENSE create mode 100644 vendor/github.com/spf13/cast/Makefile create mode 100644 vendor/github.com/spf13/cast/README.md create mode 100644 vendor/github.com/spf13/cast/cast.go create mode 100644 vendor/github.com/spf13/cast/caste.go create mode 100644 vendor/github.com/spf13/cast/go.mod create mode 100644 vendor/github.com/spf13/cast/go.sum create mode 100644 vendor/github.com/spf13/cast/timeformattype_string.go create mode 100644 vendor/github.com/spf13/jwalterweatherman/.gitignore create mode 100644 vendor/github.com/spf13/jwalterweatherman/LICENSE create mode 100644 vendor/github.com/spf13/jwalterweatherman/README.md create mode 100644 vendor/github.com/spf13/jwalterweatherman/default_notepad.go create mode 100644 vendor/github.com/spf13/jwalterweatherman/go.mod create mode 100644 vendor/github.com/spf13/jwalterweatherman/log_counter.go create mode 100644 vendor/github.com/spf13/jwalterweatherman/notepad.go create mode 100644 vendor/github.com/spf13/pflag/.gitignore create mode 100644 vendor/github.com/spf13/pflag/.travis.yml create mode 100644 vendor/github.com/spf13/pflag/LICENSE create mode 100644 vendor/github.com/spf13/pflag/README.md create mode 100644 vendor/github.com/spf13/pflag/bool.go create mode 100644 vendor/github.com/spf13/pflag/bool_slice.go create mode 100644 vendor/github.com/spf13/pflag/bytes.go create mode 100644 vendor/github.com/spf13/pflag/count.go create mode 100644 vendor/github.com/spf13/pflag/duration.go create mode 100644 vendor/github.com/spf13/pflag/duration_slice.go create mode 100644 vendor/github.com/spf13/pflag/flag.go create mode 100644 vendor/github.com/spf13/pflag/float32.go create mode 100644 vendor/github.com/spf13/pflag/float32_slice.go create mode 100644 vendor/github.com/spf13/pflag/float64.go create mode 100644 vendor/github.com/spf13/pflag/float64_slice.go create mode 100644 vendor/github.com/spf13/pflag/go.mod create mode 100644 vendor/github.com/spf13/pflag/go.sum create mode 100644 vendor/github.com/spf13/pflag/golangflag.go create mode 100644 vendor/github.com/spf13/pflag/int.go create mode 100644 vendor/github.com/spf13/pflag/int16.go create mode 100644 vendor/github.com/spf13/pflag/int32.go create mode 100644 vendor/github.com/spf13/pflag/int32_slice.go create mode 100644 vendor/github.com/spf13/pflag/int64.go create mode 100644 vendor/github.com/spf13/pflag/int64_slice.go create mode 100644 vendor/github.com/spf13/pflag/int8.go create mode 100644 vendor/github.com/spf13/pflag/int_slice.go create mode 100644 vendor/github.com/spf13/pflag/ip.go create mode 100644 vendor/github.com/spf13/pflag/ip_slice.go create mode 100644 vendor/github.com/spf13/pflag/ipmask.go create mode 100644 vendor/github.com/spf13/pflag/ipnet.go create mode 100644 vendor/github.com/spf13/pflag/string.go create mode 100644 vendor/github.com/spf13/pflag/string_array.go create mode 100644 vendor/github.com/spf13/pflag/string_slice.go create mode 100644 vendor/github.com/spf13/pflag/string_to_int.go create mode 100644 vendor/github.com/spf13/pflag/string_to_int64.go create mode 100644 vendor/github.com/spf13/pflag/string_to_string.go create mode 100644 vendor/github.com/spf13/pflag/uint.go create mode 100644 vendor/github.com/spf13/pflag/uint16.go create mode 100644 vendor/github.com/spf13/pflag/uint32.go create mode 100644 vendor/github.com/spf13/pflag/uint64.go create mode 100644 vendor/github.com/spf13/pflag/uint8.go create mode 100644 vendor/github.com/spf13/pflag/uint_slice.go create mode 100644 vendor/github.com/spf13/viper/.editorconfig create mode 100644 vendor/github.com/spf13/viper/.gitignore create mode 100644 vendor/github.com/spf13/viper/.golangci.yml create mode 100644 vendor/github.com/spf13/viper/LICENSE create mode 100644 vendor/github.com/spf13/viper/Makefile create mode 100644 vendor/github.com/spf13/viper/README.md create mode 100644 vendor/github.com/spf13/viper/TROUBLESHOOTING.md create mode 100644 vendor/github.com/spf13/viper/flags.go create mode 100644 vendor/github.com/spf13/viper/fs.go create mode 100644 vendor/github.com/spf13/viper/go.mod create mode 100644 vendor/github.com/spf13/viper/go.sum create mode 100644 vendor/github.com/spf13/viper/internal/encoding/decoder.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/encoder.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/error.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/json/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/toml/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go create mode 100644 vendor/github.com/spf13/viper/logger.go create mode 100644 vendor/github.com/spf13/viper/util.go create mode 100644 vendor/github.com/spf13/viper/viper.go create mode 100644 vendor/github.com/spf13/viper/viper_go1_15.go create mode 100644 vendor/github.com/spf13/viper/viper_go1_16.go create mode 100644 vendor/github.com/spf13/viper/watch.go create mode 100644 vendor/github.com/spf13/viper/watch_wasm.go create mode 100644 vendor/github.com/subosito/gotenv/.env create mode 100644 vendor/github.com/subosito/gotenv/.env.invalid create mode 100644 vendor/github.com/subosito/gotenv/.gitignore create mode 100644 vendor/github.com/subosito/gotenv/.travis.yml create mode 100644 vendor/github.com/subosito/gotenv/CHANGELOG.md create mode 100644 vendor/github.com/subosito/gotenv/LICENSE create mode 100644 vendor/github.com/subosito/gotenv/README.md create mode 100644 vendor/github.com/subosito/gotenv/appveyor.yml create mode 100644 vendor/github.com/subosito/gotenv/gotenv.go create mode 100644 vendor/github.com/vishvananda/netlink/.gitignore create mode 100644 vendor/github.com/vishvananda/netlink/.travis.yml create mode 100644 vendor/github.com/vishvananda/netlink/CHANGELOG.md create mode 100644 vendor/github.com/vishvananda/netlink/LICENSE create mode 100644 vendor/github.com/vishvananda/netlink/Makefile create mode 100644 vendor/github.com/vishvananda/netlink/README.md create mode 100644 vendor/github.com/vishvananda/netlink/addr.go create mode 100644 vendor/github.com/vishvananda/netlink/addr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/bpf_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/bridge_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/class.go create mode 100644 vendor/github.com/vishvananda/netlink/class_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/conntrack_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/conntrack_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/devlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/filter.go create mode 100644 vendor/github.com/vishvananda/netlink/filter_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/fou.go create mode 100644 vendor/github.com/vishvananda/netlink/fou_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/fou_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/genetlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/genetlink_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/go.mod create mode 100644 vendor/github.com/vishvananda/netlink/go.sum create mode 100644 vendor/github.com/vishvananda/netlink/gtp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/handle_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/handle_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/inet_diag.go create mode 100644 vendor/github.com/vishvananda/netlink/ioctl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/link.go create mode 100644 vendor/github.com/vishvananda/netlink/link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/link_tuntap_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/neigh.go create mode 100644 vendor/github.com/vishvananda/netlink/neigh_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netlink_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/netns_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/netns_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/addr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/bridge_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/devlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/mpls_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/route_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/syscall.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/tc_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/order.go create mode 100644 vendor/github.com/vishvananda/netlink/protinfo.go create mode 100644 vendor/github.com/vishvananda/netlink/protinfo_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/qdisc.go create mode 100644 vendor/github.com/vishvananda/netlink/qdisc_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/rdma_link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/route.go create mode 100644 vendor/github.com/vishvananda/netlink/route_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/route_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/rule.go create mode 100644 vendor/github.com/vishvananda/netlink/rule_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/socket.go create mode 100644 vendor/github.com/vishvananda/netlink/socket_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_policy.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_state.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netns/LICENSE create mode 100644 vendor/github.com/vishvananda/netns/README.md create mode 100644 vendor/github.com/vishvananda/netns/go.mod create mode 100644 vendor/github.com/vishvananda/netns/go.sum create mode 100644 vendor/github.com/vishvananda/netns/netns.go create mode 100644 vendor/github.com/vishvananda/netns/netns_linux.go create mode 100644 vendor/github.com/vishvananda/netns/netns_unspecified.go delete mode 100644 vendor/golang.org/x/net/http2/README create mode 100644 vendor/golang.org/x/net/http2/ascii.go create mode 100644 vendor/golang.org/x/net/http2/go115.go create mode 100644 vendor/golang.org/x/net/http2/go118.go create mode 100644 vendor/golang.org/x/net/http2/not_go115.go create mode 100644 vendor/golang.org/x/net/http2/not_go118.go create mode 100644 vendor/golang.org/x/net/idna/go118.go create mode 100644 vendor/golang.org/x/net/idna/pre_go118.go rename vendor/golang.org/x/net/idna/{tables12.00.go => tables12.0.0.go} (99%) create mode 100644 vendor/golang.org/x/net/idna/tables13.0.0.go create mode 100644 vendor/golang.org/x/text/unicode/bidi/tables13.0.0.go create mode 100644 vendor/golang.org/x/text/unicode/norm/tables13.0.0.go delete mode 100644 vendor/google.golang.org/grpc/.travis.yml create mode 100644 vendor/google.golang.org/grpc/NOTICE.txt create mode 100644 vendor/google.golang.org/grpc/SECURITY.md create mode 100644 vendor/google.golang.org/grpc/balancer/conn_state_evaluator.go create mode 100644 vendor/google.golang.org/grpc/channelz/channelz.go delete mode 100644 vendor/google.golang.org/grpc/credentials/go12.go create mode 100644 vendor/google.golang.org/grpc/credentials/insecure/insecure.go delete mode 100644 vendor/google.golang.org/grpc/install_gae.sh create mode 100644 vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go create mode 100644 vendor/google.golang.org/grpc/internal/channelz/id.go create mode 100644 vendor/google.golang.org/grpc/internal/credentials/credentials.go delete mode 100644 vendor/google.golang.org/grpc/internal/credentials/spiffe_appengine.go create mode 100644 vendor/google.golang.org/grpc/internal/envconfig/observability.go create mode 100644 vendor/google.golang.org/grpc/internal/envconfig/xds.go rename vendor/google.golang.org/grpc/internal/{credentials/syscallconn_appengine.go => grpcutil/grpcutil.go} (72%) rename vendor/google.golang.org/grpc/internal/{resolver/dns/go113.go => grpcutil/regex.go} (63%) delete mode 100644 vendor/google.golang.org/grpc/internal/grpcutil/target.go create mode 100644 vendor/google.golang.org/grpc/internal/metadata/metadata.go create mode 100644 vendor/google.golang.org/grpc/internal/pretty/pretty.go create mode 100644 vendor/google.golang.org/grpc/internal/resolver/config_selector.go create mode 100644 vendor/google.golang.org/grpc/internal/resolver/unix/unix.go create mode 100644 vendor/google.golang.org/grpc/internal/transport/networktype/networktype.go rename vendor/google.golang.org/grpc/{ => internal/transport}/proxy.go (71%) create mode 100644 vendor/google.golang.org/grpc/internal/xds_handshake_cluster.go create mode 100644 vendor/google.golang.org/grpc/resolver/map.go delete mode 100644 vendor/google.golang.org/protobuf/AUTHORS delete mode 100644 vendor/google.golang.org/protobuf/CONTRIBUTORS create mode 100644 vendor/google.golang.org/protobuf/encoding/protojson/decode.go create mode 100644 vendor/google.golang.org/protobuf/encoding/protojson/doc.go create mode 100644 vendor/google.golang.org/protobuf/encoding/protojson/encode.go create mode 100644 vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/json/decode.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/json/decode_number.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/json/decode_string.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/json/decode_token.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/json/encode.go delete mode 100644 vendor/google.golang.org/protobuf/internal/fieldsort/fieldsort.go delete mode 100644 vendor/google.golang.org/protobuf/internal/mapsort/mapsort.go create mode 100644 vendor/google.golang.org/protobuf/internal/order/order.go create mode 100644 vendor/google.golang.org/protobuf/internal/order/range.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protodesc/proto.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go create mode 100644 vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go create mode 100644 vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go create mode 100644 vendor/gopkg.in/ini.v1/.gitignore create mode 100644 vendor/gopkg.in/ini.v1/.golangci.yml create mode 100644 vendor/gopkg.in/ini.v1/LICENSE create mode 100644 vendor/gopkg.in/ini.v1/Makefile create mode 100644 vendor/gopkg.in/ini.v1/README.md create mode 100644 vendor/gopkg.in/ini.v1/codecov.yml create mode 100644 vendor/gopkg.in/ini.v1/data_source.go create mode 100644 vendor/gopkg.in/ini.v1/deprecated.go create mode 100644 vendor/gopkg.in/ini.v1/error.go create mode 100644 vendor/gopkg.in/ini.v1/file.go create mode 100644 vendor/gopkg.in/ini.v1/helper.go create mode 100644 vendor/gopkg.in/ini.v1/ini.go create mode 100644 vendor/gopkg.in/ini.v1/key.go create mode 100644 vendor/gopkg.in/ini.v1/parser.go create mode 100644 vendor/gopkg.in/ini.v1/section.go create mode 100644 vendor/gopkg.in/ini.v1/struct.go create mode 100644 vendor/gopkg.in/yaml.v2/.travis.yml create mode 100644 vendor/gopkg.in/yaml.v2/LICENSE create mode 100644 vendor/gopkg.in/yaml.v2/LICENSE.libyaml create mode 100644 vendor/gopkg.in/yaml.v2/NOTICE create mode 100644 vendor/gopkg.in/yaml.v2/README.md create mode 100644 vendor/gopkg.in/yaml.v2/apic.go create mode 100644 vendor/gopkg.in/yaml.v2/decode.go create mode 100644 vendor/gopkg.in/yaml.v2/emitterc.go create mode 100644 vendor/gopkg.in/yaml.v2/encode.go create mode 100644 vendor/gopkg.in/yaml.v2/go.mod create mode 100644 vendor/gopkg.in/yaml.v2/parserc.go create mode 100644 vendor/gopkg.in/yaml.v2/readerc.go create mode 100644 vendor/gopkg.in/yaml.v2/resolve.go create mode 100644 vendor/gopkg.in/yaml.v2/scannerc.go create mode 100644 vendor/gopkg.in/yaml.v2/sorter.go create mode 100644 vendor/gopkg.in/yaml.v2/writerc.go create mode 100644 vendor/gopkg.in/yaml.v2/yaml.go create mode 100644 vendor/gopkg.in/yaml.v2/yamlh.go create mode 100644 vendor/gopkg.in/yaml.v2/yamlprivateh.go 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"] "