diff --git a/glide.lock b/glide.lock index 2e004575..ffbffe67 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: aa4807befbaa3fa5d489feed6ecaca17a92edb6761f7a3aebfbb053f1c636754 -updated: 2017-07-12T21:49:20.87386587-05:00 +hash: ec07230b29cc1473d02179ae0a62534d03e5b4b7683e4227174a9296e7661081 +updated: 2017-07-14T02:08:26.222807645+05:30 imports: - name: github.com/armon/go-radix version: 4239b77079c7b5d1243b7b4736304ce8ddb6f0f2 @@ -125,7 +125,7 @@ imports: - name: github.com/opencontainers/go-digest version: 279bed98673dd5bef374d3b6e4b09e2af76183bf - name: github.com/osrg/gobgp - version: 9f9a71eab2bc9f2fed0d7c32a05f74d4c42b12ae + version: 3d01f04c8cb10ad91fb53e432d82ad9c4d8efff2 subpackages: - api - config @@ -147,7 +147,9 @@ imports: - name: github.com/satori/go.uuid version: 5bf94b69c6b68ee1b541973bb8e1144db23a194b - name: github.com/sirupsen/logrus - version: 1fe8319fcaef78ef9220c9b05178df0f871dbc5d + version: 51dc0fc64317a2861273909081f9c315786533eb +- name: github.com/Sirupsen/logrus + version: 51dc0fc64317a2861273909081f9c315786533eb - name: github.com/spf13/afero version: 9be650865eab0c12963d8753212f4f9c66cdcf12 subpackages: diff --git a/glide.yaml b/glide.yaml index fdf513ae..a17b863a 100644 --- a/glide.yaml +++ b/glide.yaml @@ -15,7 +15,7 @@ import: - package: github.com/mqliang/libipvs version: master - package: github.com/osrg/gobgp - version: ^1.17.0 + version: ~1.20 subpackages: - api - config diff --git a/vendor/github.com/Sirupsen/logrus/.gitignore b/vendor/github.com/Sirupsen/logrus/.gitignore new file mode 100644 index 00000000..66be63a0 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/.gitignore @@ -0,0 +1 @@ +logrus diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml new file mode 100644 index 00000000..ceace13b --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/.travis.yml @@ -0,0 +1,12 @@ +language: go +go: + - 1.6.x + - 1.7.x + - 1.8.x + - tip +env: + - GOMAXPROCS=4 GORACE=halt_on_error=1 +install: + - go get github.com/stretchr/testify/assert +script: + - go test -race -v . diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md new file mode 100644 index 00000000..c443aed0 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md @@ -0,0 +1,109 @@ +# 1.0.2 + +* bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method + +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + +# 1.0.0 + +* Officially changed name to lower-case +* bug: colors on Windows 10 (#541) +* bug: fix race in accessing level (#512) + +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + +# 0.10.0 + +* feature: Add a test hook (#180) +* feature: `ParseLevel` is now case-insensitive (#326) +* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) +* performance: avoid re-allocations on `WithFields` (#335) + +# 0.9.0 + +* logrus/text_formatter: don't emit empty msg +* logrus/hooks/airbrake: move out of main repository +* logrus/hooks/sentry: move out of main repository +* logrus/hooks/papertrail: move out of main repository +* logrus/hooks/bugsnag: move out of main repository +* logrus/core: run tests with `-race` +* logrus/core: detect TTY based on `stderr` +* logrus/core: support `WithError` on logger +* logrus/core: Solaris support + +# 0.8.7 + +* logrus/core: fix possible race (#216) +* logrus/doc: small typo fixes and doc improvements + + +# 0.8.6 + +* hooks/raven: allow passing an initialized client + +# 0.8.5 + +* logrus/core: revert #208 + +# 0.8.4 + +* formatter/text: fix data race (#218) + +# 0.8.3 + +* logrus/core: fix entry log level (#208) +* logrus/core: improve performance of text formatter by 40% +* logrus/core: expose `LevelHooks` type +* logrus/core: add support for DragonflyBSD and NetBSD +* formatter/text: print structs more verbosely + +# 0.8.2 + +* logrus: fix more Fatal family functions + +# 0.8.1 + +* logrus: fix not exiting on `Fatalf` and `Fatalln` + +# 0.8.0 + +* logrus: defaults to stderr instead of stdout +* hooks/sentry: add special field for `*http.Request` +* formatter/text: ignore Windows for colors + +# 0.7.3 + +* formatter/\*: allow configuration of timestamp layout + +# 0.7.2 + +* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/Sirupsen/logrus/LICENSE new file mode 100644 index 00000000..f090cb42 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Simon Eskildsen + +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/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md new file mode 100644 index 00000000..82aeb4ee --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/README.md @@ -0,0 +1,504 @@ +# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) + +Logrus is a structured logger for Go (golang), completely API compatible with +the standard library logger. [Godoc][godoc]. + +**Seeing weird case-sensitive problems?** It's in the past been possible to +import Logrus as both upper- and lower-case. Due to the Go package environment, +this caused issues in the community and we needed a standard. Some environments +experienced problems with the upper-case variant, so the lower-case was decided. +Everything using `logrus` will need to use the lower-case: +`github.com/sirupsen/logrus`. Any package that isn't, should be changed. + +To fix Glide, see [these +comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). +For an in-depth explanation of the casing issue, see [this +comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). + +**Are you interested in assisting in maintaining Logrus?** Currently I have a +lot of obligations, and I am unable to provide Logrus with the maintainership it +needs. If you'd like to help, please reach out to me at `simon at author's +username dot com`. + +Nicely color-coded in development (when a TTY is attached, otherwise just +plain text): + +![Colored](http://i.imgur.com/PY7qMwd.png) + +With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash +or Splunk: + +```json +{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the +ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} + +{"level":"warning","msg":"The group's number increased tremendously!", +"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"A giant walrus appears!", +"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", +"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} + +{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, +"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} +``` + +With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not +attached, the output is compatible with the +[logfmt](http://godoc.org/github.com/kr/logfmt) format: + +```text +time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 +time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 +time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true +time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 +time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 +time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true +exit status 1 +``` + +#### Case-sensitivity + +The organization's name was changed to lower-case--and this will not be changed +back. If you are getting import conflicts due to case sensitivity, please use +the lower-case import: `github.com/sirupsen/logrus`. + +#### Example + +The simplest way to use Logrus is simply the package-level exported logger: + +```go +package main + +import ( + log "github.com/sirupsen/logrus" +) + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") +} +``` + +Note that it's completely api-compatible with the stdlib logger, so you can +replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` +and you'll now have the flexibility of Logrus. You can customize it all you +want: + +```go +package main + +import ( + "os" + log "github.com/sirupsen/logrus" +) + +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) +} + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(log.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(log.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") + + // A common pattern is to re-use fields between logging statements by re-using + // the logrus.Entry returned from WithFields() + contextLogger := log.WithFields(log.Fields{ + "common": "this is a common field", + "other": "I also should be logged always", + }) + + contextLogger.Info("I'll be logged with common and other field") + contextLogger.Info("Me too") +} +``` + +For more advanced usage such as logging to multiple locations from the same +application, you can also create an instance of the `logrus` Logger: + +```go +package main + +import ( + "os" + "github.com/sirupsen/logrus" +) + +// Create a new instance of the logger. You can have any number of instances. +var log = logrus.New() + +func main() { + // The API for setting attributes is a little different than the package level + // exported logger. See Godoc. + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") +} +``` + +#### Fields + +Logrus encourages careful, structured logging through logging fields instead of +long, unparseable error messages. For example, instead of: `log.Fatalf("Failed +to send event %s to topic %s with key %d")`, you should log the much more +discoverable: + +```go +log.WithFields(log.Fields{ + "event": event, + "topic": topic, + "key": key, +}).Fatal("Failed to send event") +``` + +We've found this API forces you to think about logging in a way that produces +much more useful logging messages. We've been in countless situations where just +a single added field to a log statement that was already there would've saved us +hours. The `WithFields` call is optional. + +In general, with Logrus using any of the `printf`-family functions should be +seen as a hint you should add a field, however, you can still use the +`printf`-family functions with Logrus. + +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + +#### Hooks + +You can add hooks for logging levels. For example to send errors to an exception +tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to +multiple places simultaneously, e.g. syslog. + +Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in +`init`: + +```go +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + "log/syslog" +) + +func init() { + + // Use the Airbrake hook to report errors that have Error severity or above to + // an exception tracker. You can create custom hooks, see the Hooks section. + log.AddHook(airbrake.NewHook(123, "xyz", "production")) + + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + if err != nil { + log.Error("Unable to connect to local syslog daemon") + } else { + log.AddHook(hook) + } +} +``` +Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). + +| Hook | Description | +| ----- | ----------- | +| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. | +| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. | +| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) | +| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) | +| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. | +| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic | +| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) | +| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch| +| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/) +| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd | +| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) | +| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) | +| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. | +| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger | +| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb | +| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) | +| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | +| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka | +| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem | +| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) | +| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) | +| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) | +| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) | +| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) | +| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail | +| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) | +| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb | +| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) | +| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit | +| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. | +| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) | +| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) | +| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | +| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) | +| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar | +| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)| +| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. | +| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | +| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) | +| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)| +| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. | +| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. | +| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) | +| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) | +| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash | +| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) | + +#### Level logging + +Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. + +```go +log.Debug("Useful debugging information.") +log.Info("Something noteworthy happened!") +log.Warn("You should probably take a look at this.") +log.Error("Something failed but I'm not quitting.") +// Calls os.Exit(1) after logging +log.Fatal("Bye.") +// Calls panic() after logging +log.Panic("I'm bailing.") +``` + +You can set the logging level on a `Logger`, then it will only log entries with +that severity or anything above it: + +```go +// Will log anything that is info or above (warn, error, fatal, panic). Default. +log.SetLevel(log.InfoLevel) +``` + +It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose +environment if your application has that. + +#### Entries + +Besides the fields added with `WithField` or `WithFields` some fields are +automatically added to all logging events: + +1. `time`. The timestamp when the entry was created. +2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after + the `AddFields` call. E.g. `Failed to send event.` +3. `level`. The logging level. E.g. `info`. + +#### Environments + +Logrus has no notion of environment. + +If you wish for hooks and formatters to only be used in specific environments, +you should handle that yourself. For example, if your application has a global +variable `Environment`, which is a string representation of the environment you +could do: + +```go +import ( + log "github.com/sirupsen/logrus" +) + +init() { + // do something here to set environment depending on an environment variable + // or command-line flag + if Environment == "production" { + log.SetFormatter(&log.JSONFormatter{}) + } else { + // The TextFormatter is default, you don't actually have to do this. + log.SetFormatter(&log.TextFormatter{}) + } +} +``` + +This configuration is how `logrus` was intended to be used, but JSON in +production is mostly only useful if you do log aggregation with tools like +Splunk or Logstash. + +#### Formatters + +The built-in logging formatters are: + +* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise + without colors. + * *Note:* to force colored output when there is no TTY, set the `ForceColors` + field to `true`. To force no colored output even if there is a TTY set the + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). +* `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). + +Third party logging formatters: + +* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. +* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. +* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. + +You can define your formatter by implementing the `Formatter` interface, +requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a +`Fields` type (`map[string]interface{}`) with all your fields as well as the +default ones (see Entries section above): + +```go +type MyJSONFormatter struct { +} + +log.SetFormatter(new(MyJSONFormatter)) + +func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { + // Note this doesn't include Time, Level and Message which are available on + // the Entry. Consult `godoc` on information about those fields or read the + // source of the official loggers. + serialized, err := json.Marshal(entry.Data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} +``` + +#### Logger as an `io.Writer` + +Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. + +```go +w := logger.Writer() +defer w.Close() + +srv := http.Server{ + // create a stdlib log.Logger that writes to + // logrus.Logger. + ErrorLog: log.New(w, "", 0), +} +``` + +Each line written to that writer will be printed the usual way, using formatters +and hooks. The level for those entries is `info`. + +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + +#### Rotation + +Log rotation is not provided with Logrus. Log rotation should be done by an +external program (like `logrotate(8)`) that can compress and delete old log +entries. It should not be a feature of the application-level logger. + +#### Tools + +| Tool | Description | +| ---- | ----------- | +|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| +|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | + +#### Testing + +Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: + +* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook +* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): + +```go +import( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSomething(t*testing.T){ + logger, hook := test.NewNullLogger() + logger.Error("Helloerror") + + assert.Equal(t, 1, len(hook.Entries)) + assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal(t, "Helloerror", hook.LastEntry().Message) + + hook.Reset() + assert.Nil(t, hook.LastEntry()) +} +``` + +#### Fatal handlers + +Logrus can register one or more functions that will be called when any `fatal` +level message is logged. The registered handlers will be executed before +logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need +to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. + +``` +... +handler := func() { + // gracefully shutdown something... +} +logrus.RegisterExitHandler(handler) +... +``` + +#### Thread safety + +By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs. +If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. + +Situation when locking is not needed includes: + +* You have no hooks registered, or hooks calling is already thread-safe. + +* Writing to logger.Out is already thread-safe, for example: + + 1) logger.Out is protected by locks. + + 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing) + + (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit.go b/vendor/github.com/Sirupsen/logrus/alt_exit.go new file mode 100644 index 00000000..8af90637 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/alt_exit.go @@ -0,0 +1,64 @@ +package logrus + +// The following code was sourced and modified from the +// https://github.com/tebeka/atexit package governed by the following license: +// +// Copyright (c) 2012 Miki Tebeka . +// +// 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. + +import ( + "fmt" + "os" +) + +var handlers = []func(){} + +func runHandler(handler func()) { + defer func() { + if err := recover(); err != nil { + fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) + } + }() + + handler() +} + +func runHandlers() { + for _, handler := range handlers { + runHandler(handler) + } +} + +// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) +func Exit(code int) { + runHandlers() + os.Exit(code) +} + +// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke +// all handlers. The handlers will also be invoked when any Fatal log entry is +// made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func RegisterExitHandler(handler func()) { + handlers = append(handlers, handler) +} diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit_test.go b/vendor/github.com/Sirupsen/logrus/alt_exit_test.go new file mode 100644 index 00000000..d1829634 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/alt_exit_test.go @@ -0,0 +1,74 @@ +package logrus + +import ( + "io/ioutil" + "os/exec" + "testing" + "time" +) + +func TestRegister(t *testing.T) { + current := len(handlers) + RegisterExitHandler(func() {}) + if len(handlers) != current+1 { + t.Fatalf("can't add handler") + } +} + +func TestHandler(t *testing.T) { + gofile := "/tmp/testprog.go" + if err := ioutil.WriteFile(gofile, testprog, 0666); err != nil { + t.Fatalf("can't create go file") + } + + outfile := "/tmp/testprog.out" + arg := time.Now().UTC().String() + err := exec.Command("go", "run", gofile, outfile, arg).Run() + if err == nil { + t.Fatalf("completed normally, should have failed") + } + + data, err := ioutil.ReadFile(outfile) + if err != nil { + t.Fatalf("can't read output file %s", outfile) + } + + if string(data) != arg { + t.Fatalf("bad data") + } +} + +var testprog = []byte(` +// Test program for atexit, gets output file and data as arguments and writes +// data to output file in atexit handler. +package main + +import ( + "github.com/sirupsen/logrus" + "flag" + "fmt" + "io/ioutil" +) + +var outfile = "" +var data = "" + +func handler() { + ioutil.WriteFile(outfile, []byte(data), 0666) +} + +func badHandler() { + n := 0 + fmt.Println(1/n) +} + +func main() { + flag.Parse() + outfile = flag.Arg(0) + data = flag.Arg(1) + + logrus.RegisterExitHandler(handler) + logrus.RegisterExitHandler(badHandler) + logrus.Fatal("Bye bye") +} +`) diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/Sirupsen/logrus/doc.go new file mode 100644 index 00000000..da67aba0 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/doc.go @@ -0,0 +1,26 @@ +/* +Package logrus is a structured logger for Go, completely API compatible with the standard library logger. + + +The simplest way to use Logrus is simply the package-level exported logger: + + package main + + import ( + log "github.com/sirupsen/logrus" + ) + + func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "number": 1, + "size": 10, + }).Info("A walrus appears") + } + +Output: + time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 + +For a full guide visit https://github.com/sirupsen/logrus +*/ +package logrus diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go new file mode 100644 index 00000000..320e5d5b --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/entry.go @@ -0,0 +1,275 @@ +package logrus + +import ( + "bytes" + "fmt" + "os" + "sync" + "time" +) + +var bufferPool *sync.Pool + +func init() { + bufferPool = &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + } +} + +// Defines the key when adding errors using WithError. +var ErrorKey = "error" + +// An entry is the final or intermediate Logrus logging entry. It contains all +// the fields passed with WithField{,s}. It's finally logged when Debug, Info, +// Warn, Error, Fatal or Panic is called on it. These objects can be reused and +// passed around as much as you wish to avoid field duplication. +type Entry struct { + Logger *Logger + + // Contains all the fields set by the user. + Data Fields + + // Time at which the log entry was created + Time time.Time + + // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic + Level Level + + // Message passed to Debug, Info, Warn, Error, Fatal or Panic + Message string + + // When formatter is called in entry.log(), an Buffer may be set to entry + Buffer *bytes.Buffer +} + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: logger, + // Default is three fields, give a little extra room + Data: make(Fields, 5), + } +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return "", err + } + str := string(serialized) + return str, nil +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return entry.WithField(ErrorKey, err) +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return entry.WithFields(Fields{key: value}) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + data := make(Fields, len(entry.Data)+len(fields)) + for k, v := range entry.Data { + data[k] = v + } + for k, v := range fields { + data[k] = v + } + return &Entry{Logger: entry.Logger, Data: data} +} + +// This function is not declared with a pointer value because otherwise +// race conditions will occur when using multiple goroutines +func (entry Entry) log(level Level, msg string) { + var buffer *bytes.Buffer + entry.Time = time.Now() + entry.Level = level + entry.Message = msg + + if err := entry.Logger.Hooks.Fire(level, &entry); err != nil { + entry.Logger.mu.Lock() + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + entry.Logger.mu.Unlock() + } + buffer = bufferPool.Get().(*bytes.Buffer) + buffer.Reset() + defer bufferPool.Put(buffer) + entry.Buffer = buffer + serialized, err := entry.Logger.Formatter.Format(&entry) + entry.Buffer = nil + if err != nil { + entry.Logger.mu.Lock() + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + entry.Logger.mu.Unlock() + } else { + entry.Logger.mu.Lock() + _, err = entry.Logger.Out.Write(serialized) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + } + entry.Logger.mu.Unlock() + } + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(&entry) + } +} + +func (entry *Entry) Debug(args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.log(DebugLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Print(args ...interface{}) { + entry.Info(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.log(InfoLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Warn(args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.log(WarnLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Warning(args ...interface{}) { + entry.Warn(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.log(ErrorLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Fatal(args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.log(FatalLevel, fmt.Sprint(args...)) + } + Exit(1) +} + +func (entry *Entry) Panic(args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.log(PanicLevel, fmt.Sprint(args...)) + } + panic(fmt.Sprint(args...)) +} + +// Entry Printf family functions + +func (entry *Entry) Debugf(format string, args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.Debug(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.Info(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + entry.Infof(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.Warn(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + entry.Warnf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.Error(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.Fatal(fmt.Sprintf(format, args...)) + } + Exit(1) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.Panic(fmt.Sprintf(format, args...)) + } +} + +// Entry Println family functions + +func (entry *Entry) Debugln(args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.Debug(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Infoln(args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.Info(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Println(args ...interface{}) { + entry.Infoln(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.Warn(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Warningln(args ...interface{}) { + entry.Warnln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.Error(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Fatalln(args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.Fatal(entry.sprintlnn(args...)) + } + Exit(1) +} + +func (entry *Entry) Panicln(args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.Panic(entry.sprintlnn(args...)) + } +} + +// Sprintlnn => Sprint no newline. This is to get the behavior of how +// fmt.Sprintln where spaces are always added between operands, regardless of +// their type. Instead of vendoring the Sprintln implementation to spare a +// string allocation, we do the simplest thing. +func (entry *Entry) sprintlnn(args ...interface{}) string { + msg := fmt.Sprintln(args...) + return msg[:len(msg)-1] +} diff --git a/vendor/github.com/Sirupsen/logrus/entry_test.go b/vendor/github.com/Sirupsen/logrus/entry_test.go new file mode 100644 index 00000000..99c3b41d --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/entry_test.go @@ -0,0 +1,77 @@ +package logrus + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEntryWithError(t *testing.T) { + + assert := assert.New(t) + + defer func() { + ErrorKey = "error" + }() + + err := fmt.Errorf("kaboom at layer %d", 4711) + + assert.Equal(err, WithError(err).Data["error"]) + + logger := New() + logger.Out = &bytes.Buffer{} + entry := NewEntry(logger) + + assert.Equal(err, entry.WithError(err).Data["error"]) + + ErrorKey = "err" + + assert.Equal(err, entry.WithError(err).Data["err"]) + +} + +func TestEntryPanicln(t *testing.T) { + errBoom := fmt.Errorf("boom time") + + defer func() { + p := recover() + assert.NotNil(t, p) + + switch pVal := p.(type) { + case *Entry: + assert.Equal(t, "kaboom", pVal.Message) + assert.Equal(t, errBoom, pVal.Data["err"]) + default: + t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal) + } + }() + + logger := New() + logger.Out = &bytes.Buffer{} + entry := NewEntry(logger) + entry.WithField("err", errBoom).Panicln("kaboom") +} + +func TestEntryPanicf(t *testing.T) { + errBoom := fmt.Errorf("boom again") + + defer func() { + p := recover() + assert.NotNil(t, p) + + switch pVal := p.(type) { + case *Entry: + assert.Equal(t, "kaboom true", pVal.Message) + assert.Equal(t, errBoom, pVal.Data["err"]) + default: + t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal) + } + }() + + logger := New() + logger.Out = &bytes.Buffer{} + entry := NewEntry(logger) + entry.WithField("err", errBoom).Panicf("kaboom %v", true) +} diff --git a/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go new file mode 100644 index 00000000..3e112b4e --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/examples/basic/basic.go @@ -0,0 +1,59 @@ +package main + +import ( + "github.com/sirupsen/logrus" + // "os" +) + +var log = logrus.New() + +func init() { + log.Formatter = new(logrus.JSONFormatter) + log.Formatter = new(logrus.TextFormatter) // default + + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.Level = logrus.DebugLevel +} + +func main() { + defer func() { + err := recover() + if err != nil { + log.WithFields(logrus.Fields{ + "omg": true, + "err": err, + "number": 100, + }).Fatal("The ice breaks!") + } + }() + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "number": 8, + }).Debug("Started observing beach") + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(logrus.Fields{ + "temperature": -4, + }).Debug("Temperature changes") + + log.WithFields(logrus.Fields{ + "animal": "orca", + "size": 9009, + }).Panic("It's over 9000!") +} diff --git a/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go new file mode 100644 index 00000000..c8470c38 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/examples/hook/hook.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" +) + +var log = logrus.New() + +func init() { + log.Formatter = new(logrus.TextFormatter) // default + log.Hooks.Add(airbrake.NewHook(123, "xyz", "development")) +} + +func main() { + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") +} diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go new file mode 100644 index 00000000..013183ed --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/exported.go @@ -0,0 +1,193 @@ +package logrus + +import ( + "io" +) + +var ( + // std is the name of the standard logger in stdlib `log` + std = New() +) + +func StandardLogger() *Logger { + return std +} + +// SetOutput sets the standard logger output. +func SetOutput(out io.Writer) { + std.mu.Lock() + defer std.mu.Unlock() + std.Out = out +} + +// SetFormatter sets the standard logger formatter. +func SetFormatter(formatter Formatter) { + std.mu.Lock() + defer std.mu.Unlock() + std.Formatter = formatter +} + +// SetLevel sets the standard logger level. +func SetLevel(level Level) { + std.mu.Lock() + defer std.mu.Unlock() + std.SetLevel(level) +} + +// GetLevel returns the standard logger level. +func GetLevel() Level { + std.mu.Lock() + defer std.mu.Unlock() + return std.level() +} + +// AddHook adds a hook to the standard logger hooks. +func AddHook(hook Hook) { + std.mu.Lock() + defer std.mu.Unlock() + std.Hooks.Add(hook) +} + +// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. +func WithError(err error) *Entry { + return std.WithField(ErrorKey, err) +} + +// WithField creates an entry from the standard logger and adds a field to +// it. If you want multiple fields, use `WithFields`. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithField(key string, value interface{}) *Entry { + return std.WithField(key, value) +} + +// WithFields creates an entry from the standard logger and adds multiple +// fields to it. This is simply a helper for `WithField`, invoking it +// once for each field. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithFields(fields Fields) *Entry { + return std.WithFields(fields) +} + +// Debug logs a message at level Debug on the standard logger. +func Debug(args ...interface{}) { + std.Debug(args...) +} + +// Print logs a message at level Info on the standard logger. +func Print(args ...interface{}) { + std.Print(args...) +} + +// Info logs a message at level Info on the standard logger. +func Info(args ...interface{}) { + std.Info(args...) +} + +// Warn logs a message at level Warn on the standard logger. +func Warn(args ...interface{}) { + std.Warn(args...) +} + +// Warning logs a message at level Warn on the standard logger. +func Warning(args ...interface{}) { + std.Warning(args...) +} + +// Error logs a message at level Error on the standard logger. +func Error(args ...interface{}) { + std.Error(args...) +} + +// Panic logs a message at level Panic on the standard logger. +func Panic(args ...interface{}) { + std.Panic(args...) +} + +// Fatal logs a message at level Fatal on the standard logger. +func Fatal(args ...interface{}) { + std.Fatal(args...) +} + +// Debugf logs a message at level Debug on the standard logger. +func Debugf(format string, args ...interface{}) { + std.Debugf(format, args...) +} + +// Printf logs a message at level Info on the standard logger. +func Printf(format string, args ...interface{}) { + std.Printf(format, args...) +} + +// Infof logs a message at level Info on the standard logger. +func Infof(format string, args ...interface{}) { + std.Infof(format, args...) +} + +// Warnf logs a message at level Warn on the standard logger. +func Warnf(format string, args ...interface{}) { + std.Warnf(format, args...) +} + +// Warningf logs a message at level Warn on the standard logger. +func Warningf(format string, args ...interface{}) { + std.Warningf(format, args...) +} + +// Errorf logs a message at level Error on the standard logger. +func Errorf(format string, args ...interface{}) { + std.Errorf(format, args...) +} + +// Panicf logs a message at level Panic on the standard logger. +func Panicf(format string, args ...interface{}) { + std.Panicf(format, args...) +} + +// Fatalf logs a message at level Fatal on the standard logger. +func Fatalf(format string, args ...interface{}) { + std.Fatalf(format, args...) +} + +// Debugln logs a message at level Debug on the standard logger. +func Debugln(args ...interface{}) { + std.Debugln(args...) +} + +// Println logs a message at level Info on the standard logger. +func Println(args ...interface{}) { + std.Println(args...) +} + +// Infoln logs a message at level Info on the standard logger. +func Infoln(args ...interface{}) { + std.Infoln(args...) +} + +// Warnln logs a message at level Warn on the standard logger. +func Warnln(args ...interface{}) { + std.Warnln(args...) +} + +// Warningln logs a message at level Warn on the standard logger. +func Warningln(args ...interface{}) { + std.Warningln(args...) +} + +// Errorln logs a message at level Error on the standard logger. +func Errorln(args ...interface{}) { + std.Errorln(args...) +} + +// Panicln logs a message at level Panic on the standard logger. +func Panicln(args ...interface{}) { + std.Panicln(args...) +} + +// Fatalln logs a message at level Fatal on the standard logger. +func Fatalln(args ...interface{}) { + std.Fatalln(args...) +} diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go new file mode 100644 index 00000000..b5fbe934 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/formatter.go @@ -0,0 +1,45 @@ +package logrus + +import "time" + +const DefaultTimestampFormat = time.RFC3339 + +// The Formatter interface is used to implement a custom Formatter. It takes an +// `Entry`. It exposes all the fields, including the default ones: +// +// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. +// * `entry.Data["time"]`. The timestamp. +// * `entry.Data["level"]. The level the entry was logged at. +// +// Any additional fields added with `WithField` or `WithFields` are also in +// `entry.Data`. Format is expected to return an array of bytes which are then +// logged to `logger.Out`. +type Formatter interface { + Format(*Entry) ([]byte, error) +} + +// This is to not silently overwrite `time`, `msg` and `level` fields when +// dumping it. If this code wasn't there doing: +// +// logrus.WithField("level", 1).Info("hello") +// +// Would just silently drop the user provided level. Instead with this code +// it'll logged as: +// +// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} +// +// It's not exported because it's still using Data in an opinionated way. It's to +// avoid code duplication between the two default formatters. +func prefixFieldClashes(data Fields) { + if t, ok := data["time"]; ok { + data["fields.time"] = t + } + + if m, ok := data["msg"]; ok { + data["fields.msg"] = m + } + + if l, ok := data["level"]; ok { + data["fields.level"] = l + } +} diff --git a/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go b/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go new file mode 100644 index 00000000..d9481589 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go @@ -0,0 +1,101 @@ +package logrus + +import ( + "fmt" + "testing" + "time" +) + +// smallFields is a small size data set for benchmarking +var smallFields = Fields{ + "foo": "bar", + "baz": "qux", + "one": "two", + "three": "four", +} + +// largeFields is a large size data set for benchmarking +var largeFields = Fields{ + "foo": "bar", + "baz": "qux", + "one": "two", + "three": "four", + "five": "six", + "seven": "eight", + "nine": "ten", + "eleven": "twelve", + "thirteen": "fourteen", + "fifteen": "sixteen", + "seventeen": "eighteen", + "nineteen": "twenty", + "a": "b", + "c": "d", + "e": "f", + "g": "h", + "i": "j", + "k": "l", + "m": "n", + "o": "p", + "q": "r", + "s": "t", + "u": "v", + "w": "x", + "y": "z", + "this": "will", + "make": "thirty", + "entries": "yeah", +} + +var errorFields = Fields{ + "foo": fmt.Errorf("bar"), + "baz": fmt.Errorf("qux"), +} + +func BenchmarkErrorTextFormatter(b *testing.B) { + doBenchmark(b, &TextFormatter{DisableColors: true}, errorFields) +} + +func BenchmarkSmallTextFormatter(b *testing.B) { + doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields) +} + +func BenchmarkLargeTextFormatter(b *testing.B) { + doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields) +} + +func BenchmarkSmallColoredTextFormatter(b *testing.B) { + doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields) +} + +func BenchmarkLargeColoredTextFormatter(b *testing.B) { + doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields) +} + +func BenchmarkSmallJSONFormatter(b *testing.B) { + doBenchmark(b, &JSONFormatter{}, smallFields) +} + +func BenchmarkLargeJSONFormatter(b *testing.B) { + doBenchmark(b, &JSONFormatter{}, largeFields) +} + +func doBenchmark(b *testing.B, formatter Formatter, fields Fields) { + logger := New() + + entry := &Entry{ + Time: time.Time{}, + Level: InfoLevel, + Message: "message", + Data: fields, + Logger: logger, + } + var d []byte + var err error + for i := 0; i < b.N; i++ { + d, err = formatter.Format(entry) + if err != nil { + b.Fatal(err) + } + b.SetBytes(int64(len(d))) + } +} diff --git a/vendor/github.com/Sirupsen/logrus/hook_test.go b/vendor/github.com/Sirupsen/logrus/hook_test.go new file mode 100644 index 00000000..13f34cb6 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hook_test.go @@ -0,0 +1,122 @@ +package logrus + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type TestHook struct { + Fired bool +} + +func (hook *TestHook) Fire(entry *Entry) error { + hook.Fired = true + return nil +} + +func (hook *TestHook) Levels() []Level { + return []Level{ + DebugLevel, + InfoLevel, + WarnLevel, + ErrorLevel, + FatalLevel, + PanicLevel, + } +} + +func TestHookFires(t *testing.T) { + hook := new(TestHook) + + LogAndAssertJSON(t, func(log *Logger) { + log.Hooks.Add(hook) + assert.Equal(t, hook.Fired, false) + + log.Print("test") + }, func(fields Fields) { + assert.Equal(t, hook.Fired, true) + }) +} + +type ModifyHook struct { +} + +func (hook *ModifyHook) Fire(entry *Entry) error { + entry.Data["wow"] = "whale" + return nil +} + +func (hook *ModifyHook) Levels() []Level { + return []Level{ + DebugLevel, + InfoLevel, + WarnLevel, + ErrorLevel, + FatalLevel, + PanicLevel, + } +} + +func TestHookCanModifyEntry(t *testing.T) { + hook := new(ModifyHook) + + LogAndAssertJSON(t, func(log *Logger) { + log.Hooks.Add(hook) + log.WithField("wow", "elephant").Print("test") + }, func(fields Fields) { + assert.Equal(t, fields["wow"], "whale") + }) +} + +func TestCanFireMultipleHooks(t *testing.T) { + hook1 := new(ModifyHook) + hook2 := new(TestHook) + + LogAndAssertJSON(t, func(log *Logger) { + log.Hooks.Add(hook1) + log.Hooks.Add(hook2) + + log.WithField("wow", "elephant").Print("test") + }, func(fields Fields) { + assert.Equal(t, fields["wow"], "whale") + assert.Equal(t, hook2.Fired, true) + }) +} + +type ErrorHook struct { + Fired bool +} + +func (hook *ErrorHook) Fire(entry *Entry) error { + hook.Fired = true + return nil +} + +func (hook *ErrorHook) Levels() []Level { + return []Level{ + ErrorLevel, + } +} + +func TestErrorHookShouldntFireOnInfo(t *testing.T) { + hook := new(ErrorHook) + + LogAndAssertJSON(t, func(log *Logger) { + log.Hooks.Add(hook) + log.Info("test") + }, func(fields Fields) { + assert.Equal(t, hook.Fired, false) + }) +} + +func TestErrorHookShouldFireOnError(t *testing.T) { + hook := new(ErrorHook) + + LogAndAssertJSON(t, func(log *Logger) { + log.Hooks.Add(hook) + log.Error("test") + }, func(fields Fields) { + assert.Equal(t, hook.Fired, true) + }) +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/Sirupsen/logrus/hooks.go new file mode 100644 index 00000000..3f151cdc --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks.go @@ -0,0 +1,34 @@ +package logrus + +// A hook to be fired when logging on the logging levels returned from +// `Levels()` on your implementation of the interface. Note that this is not +// fired in a goroutine or a channel with workers, you should handle such +// functionality yourself if your call is non-blocking and you don't wish for +// the logging calls for levels returned from `Levels()` to block. +type Hook interface { + Levels() []Level + Fire(*Entry) error +} + +// Internal type for storing the hooks on a logger instance. +type LevelHooks map[Level][]Hook + +// Add a hook to an instance of logger. This is called with +// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. +func (hooks LevelHooks) Add(hook Hook) { + for _, level := range hook.Levels() { + hooks[level] = append(hooks[level], hook) + } +} + +// Fire all the hooks for the passed level. Used by `entry.log` to fire +// appropriate hooks for a log entry. +func (hooks LevelHooks) Fire(level Level, entry *Entry) error { + for _, hook := range hooks[level] { + if err := hook.Fire(entry); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md new file mode 100644 index 00000000..92b391c1 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/README.md @@ -0,0 +1,39 @@ +# Syslog Hooks for Logrus :walrus: + +## Usage + +```go +import ( + "log/syslog" + "github.com/sirupsen/logrus" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" +) + +func main() { + log := logrus.New() + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + + if err == nil { + log.Hooks.Add(hook) + } +} +``` + +If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following. + +```go +import ( + "log/syslog" + "github.com/sirupsen/logrus" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" +) + +func main() { + log := logrus.New() + hook, err := logrus_syslog.NewSyslogHook("", "", syslog.LOG_INFO, "") + + if err == nil { + log.Hooks.Add(hook) + } +} +``` diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go new file mode 100644 index 00000000..204f0016 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog.go @@ -0,0 +1,54 @@ +// +build !windows,!nacl,!plan9 + +package logrus_syslog + +import ( + "fmt" + "github.com/sirupsen/logrus" + "log/syslog" + "os" +) + +// SyslogHook to send logs via syslog. +type SyslogHook struct { + Writer *syslog.Writer + SyslogNetwork string + SyslogRaddr string +} + +// Creates a hook to be added to an instance of logger. This is called with +// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")` +// `if err == nil { log.Hooks.Add(hook) }` +func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) { + w, err := syslog.Dial(network, raddr, priority, tag) + return &SyslogHook{w, network, raddr}, err +} + +func (hook *SyslogHook) Fire(entry *logrus.Entry) error { + line, err := entry.String() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) + return err + } + + switch entry.Level { + case logrus.PanicLevel: + return hook.Writer.Crit(line) + case logrus.FatalLevel: + return hook.Writer.Crit(line) + case logrus.ErrorLevel: + return hook.Writer.Err(line) + case logrus.WarnLevel: + return hook.Writer.Warning(line) + case logrus.InfoLevel: + return hook.Writer.Info(line) + case logrus.DebugLevel: + return hook.Writer.Debug(line) + default: + return nil + } +} + +func (hook *SyslogHook) Levels() []logrus.Level { + return logrus.AllLevels +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go new file mode 100644 index 00000000..8d7fbe45 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go @@ -0,0 +1,26 @@ +package logrus_syslog + +import ( + "github.com/sirupsen/logrus" + "log/syslog" + "testing" +) + +func TestLocalhostAddAndPrint(t *testing.T) { + log := logrus.New() + hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + + if err != nil { + t.Errorf("Unable to connect to local syslog.") + } + + log.Hooks.Add(hook) + + for _, level := range hook.Levels() { + if len(log.Hooks[level]) != 1 { + t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level])) + } + } + + log.Info("Congratulations!") +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go new file mode 100644 index 00000000..62c4845d --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go @@ -0,0 +1,95 @@ +// The Test package is used for testing logrus. It is here for backwards +// compatibility from when logrus' organization was upper-case. Please use +// lower-case logrus and the `null` package instead of this one. +package test + +import ( + "io/ioutil" + "sync" + + "github.com/sirupsen/logrus" +) + +// Hook is a hook designed for dealing with logs in test scenarios. +type Hook struct { + // Entries is an array of all entries that have been received by this hook. + // For safe access, use the AllEntries() method, rather than reading this + // value directly. + Entries []*logrus.Entry + mu sync.RWMutex +} + +// NewGlobal installs a test hook for the global logger. +func NewGlobal() *Hook { + + hook := new(Hook) + logrus.AddHook(hook) + + return hook + +} + +// NewLocal installs a test hook for a given local logger. +func NewLocal(logger *logrus.Logger) *Hook { + + hook := new(Hook) + logger.Hooks.Add(hook) + + return hook + +} + +// NewNullLogger creates a discarding logger and installs the test hook. +func NewNullLogger() (*logrus.Logger, *Hook) { + + logger := logrus.New() + logger.Out = ioutil.Discard + + return logger, NewLocal(logger) + +} + +func (t *Hook) Fire(e *logrus.Entry) error { + t.mu.Lock() + defer t.mu.Unlock() + t.Entries = append(t.Entries, e) + return nil +} + +func (t *Hook) Levels() []logrus.Level { + return logrus.AllLevels +} + +// LastEntry returns the last entry that was logged or nil. +func (t *Hook) LastEntry() *logrus.Entry { + t.mu.RLock() + defer t.mu.RUnlock() + i := len(t.Entries) - 1 + if i < 0 { + return nil + } + // Make a copy, for safety + e := *t.Entries[i] + return &e +} + +// AllEntries returns all entries that were logged. +func (t *Hook) AllEntries() []*logrus.Entry { + t.mu.RLock() + defer t.mu.RUnlock() + // Make a copy so the returned value won't race with future log requests + entries := make([]*logrus.Entry, len(t.Entries)) + for i, entry := range t.Entries { + // Make a copy, for safety + e := *entry + entries[i] = &e + } + return entries +} + +// Reset removes all Entries from this test hook. +func (t *Hook) Reset() { + t.mu.Lock() + defer t.mu.Unlock() + t.Entries = make([]*logrus.Entry, 0) +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go new file mode 100644 index 00000000..3f55cfe3 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go @@ -0,0 +1,39 @@ +package test + +import ( + "testing" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestAllHooks(t *testing.T) { + + assert := assert.New(t) + + logger, hook := NewNullLogger() + assert.Nil(hook.LastEntry()) + assert.Equal(0, len(hook.Entries)) + + logger.Error("Hello error") + assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal("Hello error", hook.LastEntry().Message) + assert.Equal(1, len(hook.Entries)) + + logger.Warn("Hello warning") + assert.Equal(logrus.WarnLevel, hook.LastEntry().Level) + assert.Equal("Hello warning", hook.LastEntry().Message) + assert.Equal(2, len(hook.Entries)) + + hook.Reset() + assert.Nil(hook.LastEntry()) + assert.Equal(0, len(hook.Entries)) + + hook = NewGlobal() + + logrus.Error("Hello error") + assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal("Hello error", hook.LastEntry().Message) + assert.Equal(1, len(hook.Entries)) + +} diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go new file mode 100644 index 00000000..e787ea17 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/json_formatter.go @@ -0,0 +1,74 @@ +package logrus + +import ( + "encoding/json" + "fmt" +) + +type fieldKey string +type FieldMap map[fieldKey]string + +const ( + FieldKeyMsg = "msg" + FieldKeyLevel = "level" + FieldKeyTime = "time" +) + +func (f FieldMap) resolve(key fieldKey) string { + if k, ok := f[key]; ok { + return k + } + + return string(key) +} + +type JSONFormatter struct { + // TimestampFormat sets the format used for marshaling timestamps. + TimestampFormat string + + // DisableTimestamp allows disabling automatic timestamps in output + DisableTimestamp bool + + // FieldMap allows users to customize the names of keys for various fields. + // As an example: + // formatter := &JSONFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message", + // }, + // } + FieldMap FieldMap +} + +func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields, len(entry.Data)+3) + for k, v := range entry.Data { + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/sirupsen/logrus/issues/137 + data[k] = v.Error() + default: + data[k] = v + } + } + prefixFieldClashes(data) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = DefaultTimestampFormat + } + + if !f.DisableTimestamp { + data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) + } + data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message + data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() + + serialized, err := json.Marshal(data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter_test.go b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go new file mode 100644 index 00000000..51093a79 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go @@ -0,0 +1,199 @@ +package logrus + +import ( + "encoding/json" + "errors" + "strings" + "testing" +) + +func TestErrorNotLost(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("error", errors.New("wild walrus"))) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + if entry["error"] != "wild walrus" { + t.Fatal("Error field not set") + } +} + +func TestErrorNotLostOnFieldNotNamedError(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("omg", errors.New("wild walrus"))) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + if entry["omg"] != "wild walrus" { + t.Fatal("Error field not set") + } +} + +func TestFieldClashWithTime(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("time", "right now!")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + if entry["fields.time"] != "right now!" { + t.Fatal("fields.time not set to original time field") + } + + if entry["time"] != "0001-01-01T00:00:00Z" { + t.Fatal("time field not set to current time, was: ", entry["time"]) + } +} + +func TestFieldClashWithMsg(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("msg", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + if entry["fields.msg"] != "something" { + t.Fatal("fields.msg not set to original msg field") + } +} + +func TestFieldClashWithLevel(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + entry := make(map[string]interface{}) + err = json.Unmarshal(b, &entry) + if err != nil { + t.Fatal("Unable to unmarshal formatted entry: ", err) + } + + if entry["fields.level"] != "something" { + t.Fatal("fields.level not set to original level field") + } +} + +func TestJSONEntryEndsWithNewline(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + + if b[len(b)-1] != '\n' { + t.Fatal("Expected JSON log entry to end with a newline") + } +} + +func TestJSONMessageKey(t *testing.T) { + formatter := &JSONFormatter{ + FieldMap: FieldMap{ + FieldKeyMsg: "message", + }, + } + + b, err := formatter.Format(&Entry{Message: "oh hai"}) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + s := string(b) + if !(strings.Contains(s, "message") && strings.Contains(s, "oh hai")) { + t.Fatal("Expected JSON to format message key") + } +} + +func TestJSONLevelKey(t *testing.T) { + formatter := &JSONFormatter{ + FieldMap: FieldMap{ + FieldKeyLevel: "somelevel", + }, + } + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + s := string(b) + if !strings.Contains(s, "somelevel") { + t.Fatal("Expected JSON to format level key") + } +} + +func TestJSONTimeKey(t *testing.T) { + formatter := &JSONFormatter{ + FieldMap: FieldMap{ + FieldKeyTime: "timeywimey", + }, + } + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + s := string(b) + if !strings.Contains(s, "timeywimey") { + t.Fatal("Expected JSON to format time key") + } +} + +func TestJSONDisableTimestamp(t *testing.T) { + formatter := &JSONFormatter{ + DisableTimestamp: true, + } + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + s := string(b) + if strings.Contains(s, FieldKeyTime) { + t.Error("Did not prevent timestamp", s) + } +} + +func TestJSONEnableTimestamp(t *testing.T) { + formatter := &JSONFormatter{} + + b, err := formatter.Format(WithField("level", "something")) + if err != nil { + t.Fatal("Unable to format entry: ", err) + } + s := string(b) + if !strings.Contains(s, FieldKeyTime) { + t.Error("Timestamp not present", s) + } +} diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go new file mode 100644 index 00000000..b44966f9 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logger.go @@ -0,0 +1,317 @@ +package logrus + +import ( + "io" + "os" + "sync" + "sync/atomic" +) + +type Logger struct { + // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a + // file, or leave it default which is `os.Stderr`. You can also set this to + // something more adventorous, such as logging to Kafka. + Out io.Writer + // Hooks for the logger instance. These allow firing events based on logging + // levels and log entries. For example, to send errors to an error tracking + // service, log to StatsD or dump the core on fatal errors. + Hooks LevelHooks + // All log entries pass through the formatter before logged to Out. The + // included formatters are `TextFormatter` and `JSONFormatter` for which + // TextFormatter is the default. In development (when a TTY is attached) it + // logs with colors, but to a file it wouldn't. You can easily implement your + // own that implements the `Formatter` interface, see the `README` or included + // formatters for examples. + Formatter Formatter + // The logging level the logger should log at. This is typically (and defaults + // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be + // logged. `logrus.Debug` is useful in + Level Level + // Used to sync writing to the log. Locking is enabled by Default + mu MutexWrap + // Reusable empty entry + entryPool sync.Pool +} + +type MutexWrap struct { + lock sync.Mutex + disabled bool +} + +func (mw *MutexWrap) Lock() { + if !mw.disabled { + mw.lock.Lock() + } +} + +func (mw *MutexWrap) Unlock() { + if !mw.disabled { + mw.lock.Unlock() + } +} + +func (mw *MutexWrap) Disable() { + mw.disabled = true +} + +// Creates a new logger. Configuration should be set by changing `Formatter`, +// `Out` and `Hooks` directly on the default logger instance. You can also just +// instantiate your own: +// +// var log = &Logger{ +// Out: os.Stderr, +// Formatter: new(JSONFormatter), +// Hooks: make(LevelHooks), +// Level: logrus.DebugLevel, +// } +// +// It's recommended to make this a global instance called `log`. +func New() *Logger { + return &Logger{ + Out: os.Stderr, + Formatter: new(TextFormatter), + Hooks: make(LevelHooks), + Level: InfoLevel, + } +} + +func (logger *Logger) newEntry() *Entry { + entry, ok := logger.entryPool.Get().(*Entry) + if ok { + return entry + } + return NewEntry(logger) +} + +func (logger *Logger) releaseEntry(entry *Entry) { + logger.entryPool.Put(entry) +} + +// Adds a field to the log entry, note that it doesn't log until you call +// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry. +// If you want multiple fields, use `WithFields`. +func (logger *Logger) WithField(key string, value interface{}) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithField(key, value) +} + +// Adds a struct of fields to the log entry. All it does is call `WithField` for +// each `Field`. +func (logger *Logger) WithFields(fields Fields) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithFields(fields) +} + +// Add an error as single field to the log entry. All it does is call +// `WithError` for the given `error`. +func (logger *Logger) WithError(err error) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithError(err) +} + +func (logger *Logger) Debugf(format string, args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debugf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Infof(format string, args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Infof(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Printf(format string, args ...interface{}) { + entry := logger.newEntry() + entry.Printf(format, args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnf(format string, args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warningf(format string, args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Errorf(format string, args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Errorf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatalf(format string, args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatalf(format, args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panicf(format string, args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panicf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Debug(args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debug(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Info(args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Info(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Print(args ...interface{}) { + entry := logger.newEntry() + entry.Info(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warn(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warn(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warning(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warn(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Error(args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Error(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatal(args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatal(args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panic(args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panic(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Debugln(args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debugln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Infoln(args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Infoln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Println(args ...interface{}) { + entry := logger.newEntry() + entry.Println(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnln(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warningln(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Errorln(args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Errorln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatalln(args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatalln(args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panicln(args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panicln(args...) + logger.releaseEntry(entry) + } +} + +//When file is opened with appending mode, it's safe to +//write concurrently to a file (within 4k message on Linux). +//In these cases user can choose to disable the lock. +func (logger *Logger) SetNoLock() { + logger.mu.Disable() +} + +func (logger *Logger) level() Level { + return Level(atomic.LoadUint32((*uint32)(&logger.Level))) +} + +func (logger *Logger) SetLevel(level Level) { + atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) +} diff --git a/vendor/github.com/Sirupsen/logrus/logger_bench_test.go b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go new file mode 100644 index 00000000..dd23a353 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go @@ -0,0 +1,61 @@ +package logrus + +import ( + "os" + "testing" +) + +// smallFields is a small size data set for benchmarking +var loggerFields = Fields{ + "foo": "bar", + "baz": "qux", + "one": "two", + "three": "four", +} + +func BenchmarkDummyLogger(b *testing.B) { + nullf, err := os.OpenFile("/dev/null", os.O_WRONLY, 0666) + if err != nil { + b.Fatalf("%v", err) + } + defer nullf.Close() + doLoggerBenchmark(b, nullf, &TextFormatter{DisableColors: true}, smallFields) +} + +func BenchmarkDummyLoggerNoLock(b *testing.B) { + nullf, err := os.OpenFile("/dev/null", os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + b.Fatalf("%v", err) + } + defer nullf.Close() + doLoggerBenchmarkNoLock(b, nullf, &TextFormatter{DisableColors: true}, smallFields) +} + +func doLoggerBenchmark(b *testing.B, out *os.File, formatter Formatter, fields Fields) { + logger := Logger{ + Out: out, + Level: InfoLevel, + Formatter: formatter, + } + entry := logger.WithFields(fields) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + entry.Info("aaa") + } + }) +} + +func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fields Fields) { + logger := Logger{ + Out: out, + Level: InfoLevel, + Formatter: formatter, + } + logger.SetNoLock() + entry := logger.WithFields(fields) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + entry.Info("aaa") + } + }) +} diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go new file mode 100644 index 00000000..dd389997 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logrus.go @@ -0,0 +1,143 @@ +package logrus + +import ( + "fmt" + "log" + "strings" +) + +// Fields type, used to pass to `WithFields`. +type Fields map[string]interface{} + +// Level type +type Level uint32 + +// Convert the Level to a string. E.g. PanicLevel becomes "panic". +func (level Level) String() string { + switch level { + case DebugLevel: + return "debug" + case InfoLevel: + return "info" + case WarnLevel: + return "warning" + case ErrorLevel: + return "error" + case FatalLevel: + return "fatal" + case PanicLevel: + return "panic" + } + + return "unknown" +} + +// ParseLevel takes a string level and returns the Logrus log level constant. +func ParseLevel(lvl string) (Level, error) { + switch strings.ToLower(lvl) { + case "panic": + return PanicLevel, nil + case "fatal": + return FatalLevel, nil + case "error": + return ErrorLevel, nil + case "warn", "warning": + return WarnLevel, nil + case "info": + return InfoLevel, nil + case "debug": + return DebugLevel, nil + } + + var l Level + return l, fmt.Errorf("not a valid logrus Level: %q", lvl) +} + +// A constant exposing all logging levels +var AllLevels = []Level{ + PanicLevel, + FatalLevel, + ErrorLevel, + WarnLevel, + InfoLevel, + DebugLevel, +} + +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel +) + +// Won't compile if StdLogger can't be realized by a log.Logger +var ( + _ StdLogger = &log.Logger{} + _ StdLogger = &Entry{} + _ StdLogger = &Logger{} +) + +// StdLogger is what your logrus-enabled library should take, that way +// it'll accept a stdlib logger and a logrus logger. There's no standard +// interface, this is the closest we get, unfortunately. +type StdLogger interface { + Print(...interface{}) + Printf(string, ...interface{}) + Println(...interface{}) + + Fatal(...interface{}) + Fatalf(string, ...interface{}) + Fatalln(...interface{}) + + Panic(...interface{}) + Panicf(string, ...interface{}) + Panicln(...interface{}) +} + +// The FieldLogger interface generalizes the Entry and Logger types +type FieldLogger interface { + WithField(key string, value interface{}) *Entry + WithFields(fields Fields) *Entry + WithError(err error) *Entry + + Debugf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Printf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Warningf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + + Debug(args ...interface{}) + Info(args ...interface{}) + Print(args ...interface{}) + Warn(args ...interface{}) + Warning(args ...interface{}) + Error(args ...interface{}) + Fatal(args ...interface{}) + Panic(args ...interface{}) + + Debugln(args ...interface{}) + Infoln(args ...interface{}) + Println(args ...interface{}) + Warnln(args ...interface{}) + Warningln(args ...interface{}) + Errorln(args ...interface{}) + Fatalln(args ...interface{}) + Panicln(args ...interface{}) +} diff --git a/vendor/github.com/Sirupsen/logrus/logrus_test.go b/vendor/github.com/Sirupsen/logrus/logrus_test.go new file mode 100644 index 00000000..78cbc282 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logrus_test.go @@ -0,0 +1,386 @@ +package logrus + +import ( + "bytes" + "encoding/json" + "strconv" + "strings" + "sync" + "testing" + + "github.com/stretchr/testify/assert" +) + +func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) { + var buffer bytes.Buffer + var fields Fields + + logger := New() + logger.Out = &buffer + logger.Formatter = new(JSONFormatter) + + log(logger) + + err := json.Unmarshal(buffer.Bytes(), &fields) + assert.Nil(t, err) + + assertions(fields) +} + +func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) { + var buffer bytes.Buffer + + logger := New() + logger.Out = &buffer + logger.Formatter = &TextFormatter{ + DisableColors: true, + } + + log(logger) + + fields := make(map[string]string) + for _, kv := range strings.Split(buffer.String(), " ") { + if !strings.Contains(kv, "=") { + continue + } + kvArr := strings.Split(kv, "=") + key := strings.TrimSpace(kvArr[0]) + val := kvArr[1] + if kvArr[1][0] == '"' { + var err error + val, err = strconv.Unquote(val) + assert.NoError(t, err) + } + fields[key] = val + } + assertions(fields) +} + +func TestPrint(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Print("test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test") + assert.Equal(t, fields["level"], "info") + }) +} + +func TestInfo(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Info("test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test") + assert.Equal(t, fields["level"], "info") + }) +} + +func TestWarn(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Warn("test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test") + assert.Equal(t, fields["level"], "warning") + }) +} + +func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Infoln("test", "test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test test") + }) +} + +func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Infoln("test", 10) + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test 10") + }) +} + +func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Infoln(10, 10) + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "10 10") + }) +} + +func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Infoln(10, 10) + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "10 10") + }) +} + +func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Info("test", 10) + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test10") + }) +} + +func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.Info("test", "test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "testtest") + }) +} + +func TestWithFieldsShouldAllowAssignments(t *testing.T) { + var buffer bytes.Buffer + var fields Fields + + logger := New() + logger.Out = &buffer + logger.Formatter = new(JSONFormatter) + + localLog := logger.WithFields(Fields{ + "key1": "value1", + }) + + localLog.WithField("key2", "value2").Info("test") + err := json.Unmarshal(buffer.Bytes(), &fields) + assert.Nil(t, err) + + assert.Equal(t, "value2", fields["key2"]) + assert.Equal(t, "value1", fields["key1"]) + + buffer = bytes.Buffer{} + fields = Fields{} + localLog.Info("test") + err = json.Unmarshal(buffer.Bytes(), &fields) + assert.Nil(t, err) + + _, ok := fields["key2"] + assert.Equal(t, false, ok) + assert.Equal(t, "value1", fields["key1"]) +} + +func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.WithField("msg", "hello").Info("test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test") + }) +} + +func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.WithField("msg", "hello").Info("test") + }, func(fields Fields) { + assert.Equal(t, fields["msg"], "test") + assert.Equal(t, fields["fields.msg"], "hello") + }) +} + +func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.WithField("time", "hello").Info("test") + }, func(fields Fields) { + assert.Equal(t, fields["fields.time"], "hello") + }) +} + +func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) { + LogAndAssertJSON(t, func(log *Logger) { + log.WithField("level", 1).Info("test") + }, func(fields Fields) { + assert.Equal(t, fields["level"], "info") + assert.Equal(t, fields["fields.level"], 1.0) // JSON has floats only + }) +} + +func TestDefaultFieldsAreNotPrefixed(t *testing.T) { + LogAndAssertText(t, func(log *Logger) { + ll := log.WithField("herp", "derp") + ll.Info("hello") + ll.Info("bye") + }, func(fields map[string]string) { + for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} { + if _, ok := fields[fieldName]; ok { + t.Fatalf("should not have prefixed %q: %v", fieldName, fields) + } + } + }) +} + +func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) { + + var buffer bytes.Buffer + var fields Fields + + logger := New() + logger.Out = &buffer + logger.Formatter = new(JSONFormatter) + + llog := logger.WithField("context", "eating raw fish") + + llog.Info("looks delicious") + + err := json.Unmarshal(buffer.Bytes(), &fields) + assert.NoError(t, err, "should have decoded first message") + assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") + assert.Equal(t, fields["msg"], "looks delicious") + assert.Equal(t, fields["context"], "eating raw fish") + + buffer.Reset() + + llog.Warn("omg it is!") + + err = json.Unmarshal(buffer.Bytes(), &fields) + assert.NoError(t, err, "should have decoded second message") + assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields") + assert.Equal(t, fields["msg"], "omg it is!") + assert.Equal(t, fields["context"], "eating raw fish") + assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry") + +} + +func TestConvertLevelToString(t *testing.T) { + assert.Equal(t, "debug", DebugLevel.String()) + assert.Equal(t, "info", InfoLevel.String()) + assert.Equal(t, "warning", WarnLevel.String()) + assert.Equal(t, "error", ErrorLevel.String()) + assert.Equal(t, "fatal", FatalLevel.String()) + assert.Equal(t, "panic", PanicLevel.String()) +} + +func TestParseLevel(t *testing.T) { + l, err := ParseLevel("panic") + assert.Nil(t, err) + assert.Equal(t, PanicLevel, l) + + l, err = ParseLevel("PANIC") + assert.Nil(t, err) + assert.Equal(t, PanicLevel, l) + + l, err = ParseLevel("fatal") + assert.Nil(t, err) + assert.Equal(t, FatalLevel, l) + + l, err = ParseLevel("FATAL") + assert.Nil(t, err) + assert.Equal(t, FatalLevel, l) + + l, err = ParseLevel("error") + assert.Nil(t, err) + assert.Equal(t, ErrorLevel, l) + + l, err = ParseLevel("ERROR") + assert.Nil(t, err) + assert.Equal(t, ErrorLevel, l) + + l, err = ParseLevel("warn") + assert.Nil(t, err) + assert.Equal(t, WarnLevel, l) + + l, err = ParseLevel("WARN") + assert.Nil(t, err) + assert.Equal(t, WarnLevel, l) + + l, err = ParseLevel("warning") + assert.Nil(t, err) + assert.Equal(t, WarnLevel, l) + + l, err = ParseLevel("WARNING") + assert.Nil(t, err) + assert.Equal(t, WarnLevel, l) + + l, err = ParseLevel("info") + assert.Nil(t, err) + assert.Equal(t, InfoLevel, l) + + l, err = ParseLevel("INFO") + assert.Nil(t, err) + assert.Equal(t, InfoLevel, l) + + l, err = ParseLevel("debug") + assert.Nil(t, err) + assert.Equal(t, DebugLevel, l) + + l, err = ParseLevel("DEBUG") + assert.Nil(t, err) + assert.Equal(t, DebugLevel, l) + + l, err = ParseLevel("invalid") + assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error()) +} + +func TestGetSetLevelRace(t *testing.T) { + wg := sync.WaitGroup{} + for i := 0; i < 100; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + if i%2 == 0 { + SetLevel(InfoLevel) + } else { + GetLevel() + } + }(i) + + } + wg.Wait() +} + +func TestLoggingRace(t *testing.T) { + logger := New() + + var wg sync.WaitGroup + wg.Add(100) + + for i := 0; i < 100; i++ { + go func() { + logger.Info("info") + wg.Done() + }() + } + wg.Wait() +} + +// Compile test +func TestLogrusInterface(t *testing.T) { + var buffer bytes.Buffer + fn := func(l FieldLogger) { + b := l.WithField("key", "value") + b.Debug("Test") + } + // test logger + logger := New() + logger.Out = &buffer + fn(logger) + + // test Entry + e := logger.WithField("another", "value") + fn(e) +} + +// Implements io.Writer using channels for synchronization, so we can wait on +// the Entry.Writer goroutine to write in a non-racey way. This does assume that +// there is a single call to Logger.Out for each message. +type channelWriter chan []byte + +func (cw channelWriter) Write(p []byte) (int, error) { + cw <- p + return len(p), nil +} + +func TestEntryWriter(t *testing.T) { + cw := channelWriter(make(chan []byte, 1)) + log := New() + log.Out = cw + log.Formatter = new(JSONFormatter) + log.WithField("foo", "bar").WriterLevel(WarnLevel).Write([]byte("hello\n")) + + bs := <-cw + var fields Fields + err := json.Unmarshal(bs, &fields) + assert.Nil(t, err) + assert.Equal(t, fields["foo"], "bar") + assert.Equal(t, fields["level"], "warning") +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go new file mode 100644 index 00000000..e011a869 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go @@ -0,0 +1,10 @@ +// +build appengine + +package logrus + +import "io" + +// IsTerminal returns true if stderr's file descriptor is a terminal. +func IsTerminal(f io.Writer) bool { + return true +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go new file mode 100644 index 00000000..5f6be4d3 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go @@ -0,0 +1,10 @@ +// +build darwin freebsd openbsd netbsd dragonfly +// +build !appengine + +package logrus + +import "syscall" + +const ioctlReadTermios = syscall.TIOCGETA + +type Termios syscall.Termios diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go new file mode 100644 index 00000000..308160ca --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_linux.go @@ -0,0 +1,14 @@ +// Based on ssh/terminal: +// 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. + +// +build !appengine + +package logrus + +import "syscall" + +const ioctlReadTermios = syscall.TCGETS + +type Termios syscall.Termios diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go new file mode 100644 index 00000000..190297ab --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go @@ -0,0 +1,28 @@ +// Based on ssh/terminal: +// 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. + +// +build linux darwin freebsd openbsd netbsd dragonfly +// +build !appengine + +package logrus + +import ( + "io" + "os" + "syscall" + "unsafe" +) + +// IsTerminal returns true if stderr's file descriptor is a terminal. +func IsTerminal(f io.Writer) bool { + var termios Termios + switch v := f.(type) { + case *os.File: + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(v.Fd()), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 + default: + return false + } +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go new file mode 100644 index 00000000..3c86b1ab --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_solaris.go @@ -0,0 +1,21 @@ +// +build solaris,!appengine + +package logrus + +import ( + "io" + "os" + + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(f io.Writer) bool { + switch v := f.(type) { + case *os.File: + _, err := unix.IoctlGetTermios(int(v.Fd()), unix.TCGETA) + return err == nil + default: + return false + } +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go new file mode 100644 index 00000000..7a336307 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_windows.go @@ -0,0 +1,82 @@ +// Based on ssh/terminal: +// 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. + +// +build windows,!appengine + +package logrus + +import ( + "bytes" + "errors" + "io" + "os" + "os/exec" + "strconv" + "strings" + "syscall" + "unsafe" +) + +var kernel32 = syscall.NewLazyDLL("kernel32.dll") + +var ( + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") +) + +const ( + enableProcessedOutput = 0x0001 + enableWrapAtEolOutput = 0x0002 + enableVirtualTerminalProcessing = 0x0004 +) + +func getVersion() (float64, error) { + stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{} + cmd := exec.Command("cmd", "ver") + cmd.Stdout = stdout + cmd.Stderr = stderr + err := cmd.Run() + if err != nil { + return -1, err + } + + // The output should be like "Microsoft Windows [Version XX.X.XXXXXX]" + version := strings.Replace(stdout.String(), "\n", "", -1) + version = strings.Replace(version, "\r\n", "", -1) + + x1 := strings.Index(version, "[Version") + + if x1 == -1 || strings.Index(version, "]") == -1 { + return -1, errors.New("Can't determine Windows version") + } + + return strconv.ParseFloat(version[x1+9:x1+13], 64) +} + +func init() { + ver, err := getVersion() + if err != nil { + return + } + + // Activate Virtual Processing for Windows CMD + // Info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx + if ver >= 10 { + handle := syscall.Handle(os.Stderr.Fd()) + procSetConsoleMode.Call(uintptr(handle), enableProcessedOutput|enableWrapAtEolOutput|enableVirtualTerminalProcessing) + } +} + +// IsTerminal returns true if stderr's file descriptor is a terminal. +func IsTerminal(f io.Writer) bool { + switch v := f.(type) { + case *os.File: + var st uint32 + r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(v.Fd()), uintptr(unsafe.Pointer(&st)), 0) + return r != 0 && e == 0 + default: + return false + } +} diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go new file mode 100644 index 00000000..cf3f17f2 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go @@ -0,0 +1,175 @@ +package logrus + +import ( + "bytes" + "fmt" + "sort" + "strings" + "sync" + "time" +) + +const ( + nocolor = 0 + red = 31 + green = 32 + yellow = 33 + blue = 36 + gray = 37 +) + +var ( + baseTimestamp time.Time +) + +func init() { + baseTimestamp = time.Now() +} + +type TextFormatter struct { + // Set to true to bypass checking for a TTY before outputting colors. + ForceColors bool + + // Force disabling colors. + DisableColors bool + + // Disable timestamp logging. useful when output is redirected to logging + // system that already adds timestamps. + DisableTimestamp bool + + // Enable logging the full timestamp when a TTY is attached instead of just + // the time passed since beginning of execution. + FullTimestamp bool + + // TimestampFormat to use for display when a full timestamp is printed + TimestampFormat string + + // The fields are sorted by default for a consistent output. For applications + // that log extremely frequently and don't use the JSON formatter this may not + // be desired. + DisableSorting bool + + // QuoteEmptyFields will wrap empty fields in quotes if true + QuoteEmptyFields bool + + // Whether the logger's out is to a terminal + isTerminal bool + + sync.Once +} + +func (f *TextFormatter) init(entry *Entry) { + if entry.Logger != nil { + f.isTerminal = IsTerminal(entry.Logger.Out) + } +} + +func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { + var b *bytes.Buffer + keys := make([]string, 0, len(entry.Data)) + for k := range entry.Data { + keys = append(keys, k) + } + + if !f.DisableSorting { + sort.Strings(keys) + } + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + prefixFieldClashes(entry.Data) + + f.Do(func() { f.init(entry) }) + + isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = DefaultTimestampFormat + } + if isColored { + f.printColored(b, entry, keys, timestampFormat) + } else { + if !f.DisableTimestamp { + f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) + } + f.appendKeyValue(b, "level", entry.Level.String()) + if entry.Message != "" { + f.appendKeyValue(b, "msg", entry.Message) + } + for _, key := range keys { + f.appendKeyValue(b, key, entry.Data[key]) + } + } + + b.WriteByte('\n') + return b.Bytes(), nil +} + +func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { + var levelColor int + switch entry.Level { + case DebugLevel: + levelColor = gray + case WarnLevel: + levelColor = yellow + case ErrorLevel, FatalLevel, PanicLevel: + levelColor = red + default: + levelColor = blue + } + + levelText := strings.ToUpper(entry.Level.String())[0:4] + + if f.DisableTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message) + } else if !f.FullTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message) + } else { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) + } + for _, k := range keys { + v := entry.Data[k] + fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) + f.appendValue(b, v) + } +} + +func (f *TextFormatter) needsQuoting(text string) bool { + if f.QuoteEmptyFields && len(text) == 0 { + return true + } + for _, ch := range text { + if !((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') { + return true + } + } + return false +} + +func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { + + b.WriteString(key) + b.WriteByte('=') + f.appendValue(b, value) + b.WriteByte(' ') +} + +func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { + stringVal, ok := value.(string) + if !ok { + stringVal = fmt.Sprint(value) + } + + if !f.needsQuoting(stringVal) { + b.WriteString(stringVal) + } else { + b.WriteString(fmt.Sprintf("%q", stringVal)) + } +} diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go new file mode 100644 index 00000000..ecb8f127 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go @@ -0,0 +1,122 @@ +package logrus + +import ( + "bytes" + "errors" + "fmt" + "strings" + "testing" + "time" +) + +func TestQuoting(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + checkQuoting := func(q bool, value interface{}) { + b, _ := tf.Format(WithField("test", value)) + idx := bytes.Index(b, ([]byte)("test=")) + cont := bytes.Contains(b[idx+5:], []byte("\"")) + if cont != q { + if q { + t.Errorf("quoting expected for: %#v", value) + } else { + t.Errorf("quoting not expected for: %#v", value) + } + } + } + + checkQuoting(false, "") + checkQuoting(false, "abcd") + checkQuoting(false, "v1.0") + checkQuoting(false, "1234567890") + checkQuoting(false, "/foobar") + checkQuoting(false, "foo_bar") + checkQuoting(false, "foo@bar") + checkQuoting(false, "foobar^") + checkQuoting(false, "+/-_^@f.oobar") + checkQuoting(true, "foobar$") + checkQuoting(true, "&foobar") + checkQuoting(true, "x y") + checkQuoting(true, "x,y") + checkQuoting(false, errors.New("invalid")) + checkQuoting(true, errors.New("invalid argument")) + + // Test for quoting empty fields. + tf.QuoteEmptyFields = true + checkQuoting(true, "") + checkQuoting(false, "abcd") + checkQuoting(true, errors.New("invalid argument")) +} + +func TestEscaping(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + testCases := []struct { + value string + expected string + }{ + {`ba"r`, `ba\"r`}, + {`ba'r`, `ba'r`}, + } + + for _, tc := range testCases { + b, _ := tf.Format(WithField("test", tc.value)) + if !bytes.Contains(b, []byte(tc.expected)) { + t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) + } + } +} + +func TestEscaping_Interface(t *testing.T) { + tf := &TextFormatter{DisableColors: true} + + ts := time.Now() + + testCases := []struct { + value interface{} + expected string + }{ + {ts, fmt.Sprintf("\"%s\"", ts.String())}, + {errors.New("error: something went wrong"), "\"error: something went wrong\""}, + } + + for _, tc := range testCases { + b, _ := tf.Format(WithField("test", tc.value)) + if !bytes.Contains(b, []byte(tc.expected)) { + t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) + } + } +} + +func TestTimestampFormat(t *testing.T) { + checkTimeStr := func(format string) { + customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format} + customStr, _ := customFormatter.Format(WithField("test", "test")) + timeStart := bytes.Index(customStr, ([]byte)("time=")) + timeEnd := bytes.Index(customStr, ([]byte)("level=")) + timeStr := customStr[timeStart+5+len("\"") : timeEnd-1-len("\"")] + if format == "" { + format = time.RFC3339 + } + _, e := time.Parse(format, (string)(timeStr)) + if e != nil { + t.Errorf("time string \"%s\" did not match provided time format \"%s\": %s", timeStr, format, e) + } + } + + checkTimeStr("2006-01-02T15:04:05.000000000Z07:00") + checkTimeStr("Mon Jan _2 15:04:05 2006") + checkTimeStr("") +} + +func TestDisableTimestampWithColoredOutput(t *testing.T) { + tf := &TextFormatter{DisableTimestamp: true, ForceColors: true} + + b, _ := tf.Format(WithField("test", "test")) + if strings.Contains(string(b), "[0000]") { + t.Error("timestamp not expected when DisableTimestamp is true") + } +} + +// TODO add tests for sorting etc., this requires a parser for the text +// formatter output. diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go new file mode 100644 index 00000000..7bdebedc --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/writer.go @@ -0,0 +1,62 @@ +package logrus + +import ( + "bufio" + "io" + "runtime" +) + +func (logger *Logger) Writer() *io.PipeWriter { + return logger.WriterLevel(InfoLevel) +} + +func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { + return NewEntry(logger).WriterLevel(level) +} + +func (entry *Entry) Writer() *io.PipeWriter { + return entry.WriterLevel(InfoLevel) +} + +func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { + reader, writer := io.Pipe() + + var printFunc func(args ...interface{}) + + switch level { + case DebugLevel: + printFunc = entry.Debug + case InfoLevel: + printFunc = entry.Info + case WarnLevel: + printFunc = entry.Warn + case ErrorLevel: + printFunc = entry.Error + case FatalLevel: + printFunc = entry.Fatal + case PanicLevel: + printFunc = entry.Panic + default: + printFunc = entry.Print + } + + go entry.writerScanner(reader, printFunc) + runtime.SetFinalizer(writer, writerFinalizer) + + return writer +} + +func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + printFunc(scanner.Text()) + } + if err := scanner.Err(); err != nil { + entry.Errorf("Error while reading from Writer: %s", err) + } + reader.Close() +} + +func writerFinalizer(writer *io.PipeWriter) { + writer.Close() +} diff --git a/vendor/github.com/osrg/gobgp/VERSION b/vendor/github.com/osrg/gobgp/VERSION index 0f6abf48..0fdd2359 100644 --- a/vendor/github.com/osrg/gobgp/VERSION +++ b/vendor/github.com/osrg/gobgp/VERSION @@ -1 +1 @@ -1.21 \ No newline at end of file +1.20 \ No newline at end of file diff --git a/vendor/github.com/osrg/gobgp/api/gobgp.pb.go b/vendor/github.com/osrg/gobgp/api/gobgp.pb.go index 162e5d42..787b9758 100644 --- a/vendor/github.com/osrg/gobgp/api/gobgp.pb.go +++ b/vendor/github.com/osrg/gobgp/api/gobgp.pb.go @@ -1,5 +1,6 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. +// Code generated by protoc-gen-go. // source: gobgp.proto +// DO NOT EDIT! /* Package gobgpapi is a generated protocol buffer package. @@ -125,31 +126,6 @@ It has these top-level messages: TimersState Transport RouteServer - GracefulRestart - MpGracefulRestartConfig - MpGracefulRestartState - MpGracefulRestart - AfiSafiConfig - AfiSafiState - RouteSelectionOptionsConfig - RouteSelectionOptionsState - RouteSelectionOptions - UseMultiplePathsConfig - UseMultiplePathsState - EbgpConfig - EbgpState - Ebgp - IbgpConfig - IbgpState - Ibgp - UseMultiplePaths - RouteTargetMembershipConfig - RouteTargetMembershipState - RouteTargetMembership - LongLivedGracefulRestartConfig - LongLivedGracefulRestartState - LongLivedGracefulRestart - AfiSafi Prefix DefinedSet MatchSet @@ -529,7 +505,7 @@ var Conditions_RouteType_value = map[string]int32{ func (x Conditions_RouteType) String() string { return proto.EnumName(Conditions_RouteType_name, int32(x)) } -func (Conditions_RouteType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{146, 0} } +func (Conditions_RouteType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{121, 0} } type GetNeighborRequest struct { EnableAdvertised bool `protobuf:"varint,1,opt,name=enableAdvertised" json:"enableAdvertised,omitempty"` @@ -2462,17 +2438,15 @@ func (*ValidateRibResponse) ProtoMessage() {} func (*ValidateRibResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{101} } type Peer struct { - Families []uint32 `protobuf:"varint,1,rep,packed,name=families" json:"families,omitempty"` - ApplyPolicy *ApplyPolicy `protobuf:"bytes,2,opt,name=apply_policy,json=applyPolicy" json:"apply_policy,omitempty"` - Conf *PeerConf `protobuf:"bytes,3,opt,name=conf" json:"conf,omitempty"` - EbgpMultihop *EbgpMultihop `protobuf:"bytes,4,opt,name=ebgp_multihop,json=ebgpMultihop" json:"ebgp_multihop,omitempty"` - RouteReflector *RouteReflector `protobuf:"bytes,5,opt,name=route_reflector,json=routeReflector" json:"route_reflector,omitempty"` - Info *PeerState `protobuf:"bytes,6,opt,name=info" json:"info,omitempty"` - Timers *Timers `protobuf:"bytes,7,opt,name=timers" json:"timers,omitempty"` - Transport *Transport `protobuf:"bytes,8,opt,name=transport" json:"transport,omitempty"` - RouteServer *RouteServer `protobuf:"bytes,9,opt,name=route_server,json=routeServer" json:"route_server,omitempty"` - GracefulRestart *GracefulRestart `protobuf:"bytes,10,opt,name=graceful_restart,json=gracefulRestart" json:"graceful_restart,omitempty"` - AfiSafis []*AfiSafi `protobuf:"bytes,11,rep,name=afi_safis,json=afiSafis" json:"afi_safis,omitempty"` + Families []uint32 `protobuf:"varint,1,rep,packed,name=families" json:"families,omitempty"` + ApplyPolicy *ApplyPolicy `protobuf:"bytes,2,opt,name=apply_policy,json=applyPolicy" json:"apply_policy,omitempty"` + Conf *PeerConf `protobuf:"bytes,3,opt,name=conf" json:"conf,omitempty"` + EbgpMultihop *EbgpMultihop `protobuf:"bytes,4,opt,name=ebgp_multihop,json=ebgpMultihop" json:"ebgp_multihop,omitempty"` + RouteReflector *RouteReflector `protobuf:"bytes,5,opt,name=route_reflector,json=routeReflector" json:"route_reflector,omitempty"` + Info *PeerState `protobuf:"bytes,6,opt,name=info" json:"info,omitempty"` + Timers *Timers `protobuf:"bytes,7,opt,name=timers" json:"timers,omitempty"` + Transport *Transport `protobuf:"bytes,8,opt,name=transport" json:"transport,omitempty"` + RouteServer *RouteServer `protobuf:"bytes,9,opt,name=route_server,json=routeServer" json:"route_server,omitempty"` } func (m *Peer) Reset() { *m = Peer{} } @@ -2543,20 +2517,6 @@ func (m *Peer) GetRouteServer() *RouteServer { return nil } -func (m *Peer) GetGracefulRestart() *GracefulRestart { - if m != nil { - return m.GracefulRestart - } - return nil -} - -func (m *Peer) GetAfiSafis() []*AfiSafi { - if m != nil { - return m.AfiSafis - } - return nil -} - type ApplyPolicy struct { InPolicy *PolicyAssignment `protobuf:"bytes,1,opt,name=in_policy,json=inPolicy" json:"in_policy,omitempty"` ExportPolicy *PolicyAssignment `protobuf:"bytes,2,opt,name=export_policy,json=exportPolicy" json:"export_policy,omitempty"` @@ -2622,28 +2582,25 @@ func (m *PrefixLimit) GetShutdownThresholdPct() uint32 { } type PeerConf struct { - AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword" json:"auth_password,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` - LocalAs uint32 `protobuf:"varint,3,opt,name=local_as,json=localAs" json:"local_as,omitempty"` - NeighborAddress string `protobuf:"bytes,4,opt,name=neighbor_address,json=neighborAddress" json:"neighbor_address,omitempty"` - PeerAs uint32 `protobuf:"varint,5,opt,name=peer_as,json=peerAs" json:"peer_as,omitempty"` - PeerGroup string `protobuf:"bytes,6,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` - PeerType uint32 `protobuf:"varint,7,opt,name=peer_type,json=peerType" json:"peer_type,omitempty"` - RemovePrivateAs PeerConf_RemovePrivateAs `protobuf:"varint,8,opt,name=remove_private_as,json=removePrivateAs,enum=gobgpapi.PeerConf_RemovePrivateAs" json:"remove_private_as,omitempty"` - RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping" json:"route_flap_damping,omitempty"` - SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity" json:"send_community,omitempty"` - RemoteCap [][]byte `protobuf:"bytes,11,rep,name=remote_cap,json=remoteCap,proto3" json:"remote_cap,omitempty"` - LocalCap [][]byte `protobuf:"bytes,12,rep,name=local_cap,json=localCap,proto3" json:"local_cap,omitempty"` - Id string `protobuf:"bytes,13,opt,name=id" json:"id,omitempty"` - // Note: Regarding to the consistency with OpenConfig mode, list of - // PrefixLimit should be removed from here, and list of PrefixLimit in - // AfiSafi should be used instead. - PrefixLimits []*PrefixLimit `protobuf:"bytes,14,rep,name=prefix_limits,json=prefixLimits" json:"prefix_limits,omitempty"` - LocalAddress string `protobuf:"bytes,15,opt,name=local_address,json=localAddress" json:"local_address,omitempty"` - NeighborInterface string `protobuf:"bytes,16,opt,name=neighbor_interface,json=neighborInterface" json:"neighbor_interface,omitempty"` - Vrf string `protobuf:"bytes,17,opt,name=vrf" json:"vrf,omitempty"` - AllowOwnAs uint32 `protobuf:"varint,18,opt,name=allow_own_as,json=allowOwnAs" json:"allow_own_as,omitempty"` - ReplacePeerAs bool `protobuf:"varint,19,opt,name=replace_peer_as,json=replacePeerAs" json:"replace_peer_as,omitempty"` + AuthPassword string `protobuf:"bytes,1,opt,name=auth_password,json=authPassword" json:"auth_password,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` + LocalAs uint32 `protobuf:"varint,3,opt,name=local_as,json=localAs" json:"local_as,omitempty"` + NeighborAddress string `protobuf:"bytes,4,opt,name=neighbor_address,json=neighborAddress" json:"neighbor_address,omitempty"` + PeerAs uint32 `protobuf:"varint,5,opt,name=peer_as,json=peerAs" json:"peer_as,omitempty"` + PeerGroup string `protobuf:"bytes,6,opt,name=peer_group,json=peerGroup" json:"peer_group,omitempty"` + PeerType uint32 `protobuf:"varint,7,opt,name=peer_type,json=peerType" json:"peer_type,omitempty"` + RemovePrivateAs PeerConf_RemovePrivateAs `protobuf:"varint,8,opt,name=remove_private_as,json=removePrivateAs,enum=gobgpapi.PeerConf_RemovePrivateAs" json:"remove_private_as,omitempty"` + RouteFlapDamping bool `protobuf:"varint,9,opt,name=route_flap_damping,json=routeFlapDamping" json:"route_flap_damping,omitempty"` + SendCommunity uint32 `protobuf:"varint,10,opt,name=send_community,json=sendCommunity" json:"send_community,omitempty"` + RemoteCap [][]byte `protobuf:"bytes,11,rep,name=remote_cap,json=remoteCap,proto3" json:"remote_cap,omitempty"` + LocalCap [][]byte `protobuf:"bytes,12,rep,name=local_cap,json=localCap,proto3" json:"local_cap,omitempty"` + Id string `protobuf:"bytes,13,opt,name=id" json:"id,omitempty"` + PrefixLimits []*PrefixLimit `protobuf:"bytes,14,rep,name=prefix_limits,json=prefixLimits" json:"prefix_limits,omitempty"` + LocalAddress string `protobuf:"bytes,15,opt,name=local_address,json=localAddress" json:"local_address,omitempty"` + NeighborInterface string `protobuf:"bytes,16,opt,name=neighbor_interface,json=neighborInterface" json:"neighbor_interface,omitempty"` + Vrf string `protobuf:"bytes,17,opt,name=vrf" json:"vrf,omitempty"` + AllowOwnAs uint32 `protobuf:"varint,18,opt,name=allow_own_as,json=allowOwnAs" json:"allow_own_as,omitempty"` + ReplacePeerAs bool `protobuf:"varint,19,opt,name=replace_peer_as,json=replacePeerAs" json:"replace_peer_as,omitempty"` } func (m *PeerConf) Reset() { *m = PeerConf{} } @@ -3328,788 +3285,6 @@ func (m *RouteServer) GetRouteServerClient() bool { return false } -type GracefulRestart struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` - RestartTime uint32 `protobuf:"varint,2,opt,name=restart_time,json=restartTime" json:"restart_time,omitempty"` - HelperOnly bool `protobuf:"varint,3,opt,name=helper_only,json=helperOnly" json:"helper_only,omitempty"` - DeferralTime uint32 `protobuf:"varint,4,opt,name=deferral_time,json=deferralTime" json:"deferral_time,omitempty"` - NotificationEnabled bool `protobuf:"varint,5,opt,name=notification_enabled,json=notificationEnabled" json:"notification_enabled,omitempty"` - LonglivedEnabled bool `protobuf:"varint,6,opt,name=longlived_enabled,json=longlivedEnabled" json:"longlived_enabled,omitempty"` -} - -func (m *GracefulRestart) Reset() { *m = GracefulRestart{} } -func (m *GracefulRestart) String() string { return proto.CompactTextString(m) } -func (*GracefulRestart) ProtoMessage() {} -func (*GracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{117} } - -func (m *GracefulRestart) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -func (m *GracefulRestart) GetRestartTime() uint32 { - if m != nil { - return m.RestartTime - } - return 0 -} - -func (m *GracefulRestart) GetHelperOnly() bool { - if m != nil { - return m.HelperOnly - } - return false -} - -func (m *GracefulRestart) GetDeferralTime() uint32 { - if m != nil { - return m.DeferralTime - } - return 0 -} - -func (m *GracefulRestart) GetNotificationEnabled() bool { - if m != nil { - return m.NotificationEnabled - } - return false -} - -func (m *GracefulRestart) GetLonglivedEnabled() bool { - if m != nil { - return m.LonglivedEnabled - } - return false -} - -type MpGracefulRestartConfig struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` -} - -func (m *MpGracefulRestartConfig) Reset() { *m = MpGracefulRestartConfig{} } -func (m *MpGracefulRestartConfig) String() string { return proto.CompactTextString(m) } -func (*MpGracefulRestartConfig) ProtoMessage() {} -func (*MpGracefulRestartConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{118} } - -func (m *MpGracefulRestartConfig) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -type MpGracefulRestartState struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` - Received bool `protobuf:"varint,2,opt,name=received" json:"received,omitempty"` - Advertised bool `protobuf:"varint,3,opt,name=advertised" json:"advertised,omitempty"` - EndOfRibReceived bool `protobuf:"varint,4,opt,name=end_of_rib_received,json=endOfRibReceived" json:"end_of_rib_received,omitempty"` - EndOfRibSent bool `protobuf:"varint,5,opt,name=end_of_rib_sent,json=endOfRibSent" json:"end_of_rib_sent,omitempty"` -} - -func (m *MpGracefulRestartState) Reset() { *m = MpGracefulRestartState{} } -func (m *MpGracefulRestartState) String() string { return proto.CompactTextString(m) } -func (*MpGracefulRestartState) ProtoMessage() {} -func (*MpGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{119} } - -func (m *MpGracefulRestartState) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -func (m *MpGracefulRestartState) GetReceived() bool { - if m != nil { - return m.Received - } - return false -} - -func (m *MpGracefulRestartState) GetAdvertised() bool { - if m != nil { - return m.Advertised - } - return false -} - -func (m *MpGracefulRestartState) GetEndOfRibReceived() bool { - if m != nil { - return m.EndOfRibReceived - } - return false -} - -func (m *MpGracefulRestartState) GetEndOfRibSent() bool { - if m != nil { - return m.EndOfRibSent - } - return false -} - -type MpGracefulRestart struct { - Config *MpGracefulRestartConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *MpGracefulRestartState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *MpGracefulRestart) Reset() { *m = MpGracefulRestart{} } -func (m *MpGracefulRestart) String() string { return proto.CompactTextString(m) } -func (*MpGracefulRestart) ProtoMessage() {} -func (*MpGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{120} } - -func (m *MpGracefulRestart) GetConfig() *MpGracefulRestartConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *MpGracefulRestart) GetState() *MpGracefulRestartState { - if m != nil { - return m.State - } - return nil -} - -type AfiSafiConfig struct { - Family uint32 `protobuf:"varint,1,opt,name=family" json:"family,omitempty"` - Enabled bool `protobuf:"varint,2,opt,name=enabled" json:"enabled,omitempty"` -} - -func (m *AfiSafiConfig) Reset() { *m = AfiSafiConfig{} } -func (m *AfiSafiConfig) String() string { return proto.CompactTextString(m) } -func (*AfiSafiConfig) ProtoMessage() {} -func (*AfiSafiConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{121} } - -func (m *AfiSafiConfig) GetFamily() uint32 { - if m != nil { - return m.Family - } - return 0 -} - -func (m *AfiSafiConfig) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -type AfiSafiState struct { - Family uint32 `protobuf:"varint,1,opt,name=family" json:"family,omitempty"` - Enabled bool `protobuf:"varint,2,opt,name=enabled" json:"enabled,omitempty"` - TotalPaths uint32 `protobuf:"varint,3,opt,name=total_paths,json=totalPaths" json:"total_paths,omitempty"` - TotalPrefixes uint32 `protobuf:"varint,4,opt,name=total_prefixes,json=totalPrefixes" json:"total_prefixes,omitempty"` -} - -func (m *AfiSafiState) Reset() { *m = AfiSafiState{} } -func (m *AfiSafiState) String() string { return proto.CompactTextString(m) } -func (*AfiSafiState) ProtoMessage() {} -func (*AfiSafiState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{122} } - -func (m *AfiSafiState) GetFamily() uint32 { - if m != nil { - return m.Family - } - return 0 -} - -func (m *AfiSafiState) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -func (m *AfiSafiState) GetTotalPaths() uint32 { - if m != nil { - return m.TotalPaths - } - return 0 -} - -func (m *AfiSafiState) GetTotalPrefixes() uint32 { - if m != nil { - return m.TotalPrefixes - } - return 0 -} - -type RouteSelectionOptionsConfig struct { - AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` - IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` - ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` - AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` - EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` - IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` -} - -func (m *RouteSelectionOptionsConfig) Reset() { *m = RouteSelectionOptionsConfig{} } -func (m *RouteSelectionOptionsConfig) String() string { return proto.CompactTextString(m) } -func (*RouteSelectionOptionsConfig) ProtoMessage() {} -func (*RouteSelectionOptionsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{123} } - -func (m *RouteSelectionOptionsConfig) GetAlwaysCompareMed() bool { - if m != nil { - return m.AlwaysCompareMed - } - return false -} - -func (m *RouteSelectionOptionsConfig) GetIgnoreAsPathLength() bool { - if m != nil { - return m.IgnoreAsPathLength - } - return false -} - -func (m *RouteSelectionOptionsConfig) GetExternalCompareRouterId() bool { - if m != nil { - return m.ExternalCompareRouterId - } - return false -} - -func (m *RouteSelectionOptionsConfig) GetAdvertiseInactiveRoutes() bool { - if m != nil { - return m.AdvertiseInactiveRoutes - } - return false -} - -func (m *RouteSelectionOptionsConfig) GetEnableAigp() bool { - if m != nil { - return m.EnableAigp - } - return false -} - -func (m *RouteSelectionOptionsConfig) GetIgnoreNextHopIgpMetric() bool { - if m != nil { - return m.IgnoreNextHopIgpMetric - } - return false -} - -type RouteSelectionOptionsState struct { - AlwaysCompareMed bool `protobuf:"varint,1,opt,name=always_compare_med,json=alwaysCompareMed" json:"always_compare_med,omitempty"` - IgnoreAsPathLength bool `protobuf:"varint,2,opt,name=ignore_as_path_length,json=ignoreAsPathLength" json:"ignore_as_path_length,omitempty"` - ExternalCompareRouterId bool `protobuf:"varint,3,opt,name=external_compare_router_id,json=externalCompareRouterId" json:"external_compare_router_id,omitempty"` - AdvertiseInactiveRoutes bool `protobuf:"varint,4,opt,name=advertise_inactive_routes,json=advertiseInactiveRoutes" json:"advertise_inactive_routes,omitempty"` - EnableAigp bool `protobuf:"varint,5,opt,name=enable_aigp,json=enableAigp" json:"enable_aigp,omitempty"` - IgnoreNextHopIgpMetric bool `protobuf:"varint,6,opt,name=ignore_next_hop_igp_metric,json=ignoreNextHopIgpMetric" json:"ignore_next_hop_igp_metric,omitempty"` -} - -func (m *RouteSelectionOptionsState) Reset() { *m = RouteSelectionOptionsState{} } -func (m *RouteSelectionOptionsState) String() string { return proto.CompactTextString(m) } -func (*RouteSelectionOptionsState) ProtoMessage() {} -func (*RouteSelectionOptionsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{124} } - -func (m *RouteSelectionOptionsState) GetAlwaysCompareMed() bool { - if m != nil { - return m.AlwaysCompareMed - } - return false -} - -func (m *RouteSelectionOptionsState) GetIgnoreAsPathLength() bool { - if m != nil { - return m.IgnoreAsPathLength - } - return false -} - -func (m *RouteSelectionOptionsState) GetExternalCompareRouterId() bool { - if m != nil { - return m.ExternalCompareRouterId - } - return false -} - -func (m *RouteSelectionOptionsState) GetAdvertiseInactiveRoutes() bool { - if m != nil { - return m.AdvertiseInactiveRoutes - } - return false -} - -func (m *RouteSelectionOptionsState) GetEnableAigp() bool { - if m != nil { - return m.EnableAigp - } - return false -} - -func (m *RouteSelectionOptionsState) GetIgnoreNextHopIgpMetric() bool { - if m != nil { - return m.IgnoreNextHopIgpMetric - } - return false -} - -type RouteSelectionOptions struct { - Config *RouteSelectionOptionsConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *RouteSelectionOptionsState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *RouteSelectionOptions) Reset() { *m = RouteSelectionOptions{} } -func (m *RouteSelectionOptions) String() string { return proto.CompactTextString(m) } -func (*RouteSelectionOptions) ProtoMessage() {} -func (*RouteSelectionOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{125} } - -func (m *RouteSelectionOptions) GetConfig() *RouteSelectionOptionsConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *RouteSelectionOptions) GetState() *RouteSelectionOptionsState { - if m != nil { - return m.State - } - return nil -} - -type UseMultiplePathsConfig struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` -} - -func (m *UseMultiplePathsConfig) Reset() { *m = UseMultiplePathsConfig{} } -func (m *UseMultiplePathsConfig) String() string { return proto.CompactTextString(m) } -func (*UseMultiplePathsConfig) ProtoMessage() {} -func (*UseMultiplePathsConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{126} } - -func (m *UseMultiplePathsConfig) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -type UseMultiplePathsState struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` -} - -func (m *UseMultiplePathsState) Reset() { *m = UseMultiplePathsState{} } -func (m *UseMultiplePathsState) String() string { return proto.CompactTextString(m) } -func (*UseMultiplePathsState) ProtoMessage() {} -func (*UseMultiplePathsState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{127} } - -func (m *UseMultiplePathsState) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -type EbgpConfig struct { - AllowMultipleAs bool `protobuf:"varint,1,opt,name=allow_multiple_as,json=allowMultipleAs" json:"allow_multiple_as,omitempty"` - MaximumPaths uint32 `protobuf:"varint,2,opt,name=maximum_paths,json=maximumPaths" json:"maximum_paths,omitempty"` -} - -func (m *EbgpConfig) Reset() { *m = EbgpConfig{} } -func (m *EbgpConfig) String() string { return proto.CompactTextString(m) } -func (*EbgpConfig) ProtoMessage() {} -func (*EbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{128} } - -func (m *EbgpConfig) GetAllowMultipleAs() bool { - if m != nil { - return m.AllowMultipleAs - } - return false -} - -func (m *EbgpConfig) GetMaximumPaths() uint32 { - if m != nil { - return m.MaximumPaths - } - return 0 -} - -type EbgpState struct { - AllowMultipleAs bool `protobuf:"varint,1,opt,name=allow_multiple_as,json=allowMultipleAs" json:"allow_multiple_as,omitempty"` - MaximumPaths uint32 `protobuf:"varint,2,opt,name=maximum_paths,json=maximumPaths" json:"maximum_paths,omitempty"` -} - -func (m *EbgpState) Reset() { *m = EbgpState{} } -func (m *EbgpState) String() string { return proto.CompactTextString(m) } -func (*EbgpState) ProtoMessage() {} -func (*EbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{129} } - -func (m *EbgpState) GetAllowMultipleAs() bool { - if m != nil { - return m.AllowMultipleAs - } - return false -} - -func (m *EbgpState) GetMaximumPaths() uint32 { - if m != nil { - return m.MaximumPaths - } - return 0 -} - -type Ebgp struct { - Config *EbgpConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *EbgpState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *Ebgp) Reset() { *m = Ebgp{} } -func (m *Ebgp) String() string { return proto.CompactTextString(m) } -func (*Ebgp) ProtoMessage() {} -func (*Ebgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{130} } - -func (m *Ebgp) GetConfig() *EbgpConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *Ebgp) GetState() *EbgpState { - if m != nil { - return m.State - } - return nil -} - -type IbgpConfig struct { - MaximumPaths uint32 `protobuf:"varint,1,opt,name=maximum_paths,json=maximumPaths" json:"maximum_paths,omitempty"` -} - -func (m *IbgpConfig) Reset() { *m = IbgpConfig{} } -func (m *IbgpConfig) String() string { return proto.CompactTextString(m) } -func (*IbgpConfig) ProtoMessage() {} -func (*IbgpConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{131} } - -func (m *IbgpConfig) GetMaximumPaths() uint32 { - if m != nil { - return m.MaximumPaths - } - return 0 -} - -type IbgpState struct { - MaximumPaths uint32 `protobuf:"varint,1,opt,name=maximum_paths,json=maximumPaths" json:"maximum_paths,omitempty"` -} - -func (m *IbgpState) Reset() { *m = IbgpState{} } -func (m *IbgpState) String() string { return proto.CompactTextString(m) } -func (*IbgpState) ProtoMessage() {} -func (*IbgpState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{132} } - -func (m *IbgpState) GetMaximumPaths() uint32 { - if m != nil { - return m.MaximumPaths - } - return 0 -} - -type Ibgp struct { - Config *IbgpConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *IbgpState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *Ibgp) Reset() { *m = Ibgp{} } -func (m *Ibgp) String() string { return proto.CompactTextString(m) } -func (*Ibgp) ProtoMessage() {} -func (*Ibgp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{133} } - -func (m *Ibgp) GetConfig() *IbgpConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *Ibgp) GetState() *IbgpState { - if m != nil { - return m.State - } - return nil -} - -type UseMultiplePaths struct { - Config *UseMultiplePathsConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *UseMultiplePathsState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` - Ebgp *Ebgp `protobuf:"bytes,3,opt,name=ebgp" json:"ebgp,omitempty"` - Ibgp *Ibgp `protobuf:"bytes,4,opt,name=ibgp" json:"ibgp,omitempty"` -} - -func (m *UseMultiplePaths) Reset() { *m = UseMultiplePaths{} } -func (m *UseMultiplePaths) String() string { return proto.CompactTextString(m) } -func (*UseMultiplePaths) ProtoMessage() {} -func (*UseMultiplePaths) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{134} } - -func (m *UseMultiplePaths) GetConfig() *UseMultiplePathsConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *UseMultiplePaths) GetState() *UseMultiplePathsState { - if m != nil { - return m.State - } - return nil -} - -func (m *UseMultiplePaths) GetEbgp() *Ebgp { - if m != nil { - return m.Ebgp - } - return nil -} - -func (m *UseMultiplePaths) GetIbgp() *Ibgp { - if m != nil { - return m.Ibgp - } - return nil -} - -type RouteTargetMembershipConfig struct { - DeferralTime uint32 `protobuf:"varint,1,opt,name=deferral_time,json=deferralTime" json:"deferral_time,omitempty"` -} - -func (m *RouteTargetMembershipConfig) Reset() { *m = RouteTargetMembershipConfig{} } -func (m *RouteTargetMembershipConfig) String() string { return proto.CompactTextString(m) } -func (*RouteTargetMembershipConfig) ProtoMessage() {} -func (*RouteTargetMembershipConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{135} } - -func (m *RouteTargetMembershipConfig) GetDeferralTime() uint32 { - if m != nil { - return m.DeferralTime - } - return 0 -} - -type RouteTargetMembershipState struct { - DeferralTime uint32 `protobuf:"varint,1,opt,name=deferral_time,json=deferralTime" json:"deferral_time,omitempty"` -} - -func (m *RouteTargetMembershipState) Reset() { *m = RouteTargetMembershipState{} } -func (m *RouteTargetMembershipState) String() string { return proto.CompactTextString(m) } -func (*RouteTargetMembershipState) ProtoMessage() {} -func (*RouteTargetMembershipState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{136} } - -func (m *RouteTargetMembershipState) GetDeferralTime() uint32 { - if m != nil { - return m.DeferralTime - } - return 0 -} - -type RouteTargetMembership struct { - Config *RouteTargetMembershipConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *RouteTargetMembershipState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *RouteTargetMembership) Reset() { *m = RouteTargetMembership{} } -func (m *RouteTargetMembership) String() string { return proto.CompactTextString(m) } -func (*RouteTargetMembership) ProtoMessage() {} -func (*RouteTargetMembership) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{137} } - -func (m *RouteTargetMembership) GetConfig() *RouteTargetMembershipConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *RouteTargetMembership) GetState() *RouteTargetMembershipState { - if m != nil { - return m.State - } - return nil -} - -type LongLivedGracefulRestartConfig struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` - RestartTime uint32 `protobuf:"varint,2,opt,name=restart_time,json=restartTime" json:"restart_time,omitempty"` -} - -func (m *LongLivedGracefulRestartConfig) Reset() { *m = LongLivedGracefulRestartConfig{} } -func (m *LongLivedGracefulRestartConfig) String() string { return proto.CompactTextString(m) } -func (*LongLivedGracefulRestartConfig) ProtoMessage() {} -func (*LongLivedGracefulRestartConfig) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{138} -} - -func (m *LongLivedGracefulRestartConfig) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -func (m *LongLivedGracefulRestartConfig) GetRestartTime() uint32 { - if m != nil { - return m.RestartTime - } - return 0 -} - -type LongLivedGracefulRestartState struct { - Enabled bool `protobuf:"varint,1,opt,name=enabled" json:"enabled,omitempty"` - Received bool `protobuf:"varint,2,opt,name=received" json:"received,omitempty"` - Advertised bool `protobuf:"varint,3,opt,name=advertised" json:"advertised,omitempty"` - PeerRestartTime uint32 `protobuf:"varint,4,opt,name=peer_restart_time,json=peerRestartTime" json:"peer_restart_time,omitempty"` - PeerRestartTimerExpired bool `protobuf:"varint,5,opt,name=peer_restart_timer_expired,json=peerRestartTimerExpired" json:"peer_restart_timer_expired,omitempty"` -} - -func (m *LongLivedGracefulRestartState) Reset() { *m = LongLivedGracefulRestartState{} } -func (m *LongLivedGracefulRestartState) String() string { return proto.CompactTextString(m) } -func (*LongLivedGracefulRestartState) ProtoMessage() {} -func (*LongLivedGracefulRestartState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{139} } - -func (m *LongLivedGracefulRestartState) GetEnabled() bool { - if m != nil { - return m.Enabled - } - return false -} - -func (m *LongLivedGracefulRestartState) GetReceived() bool { - if m != nil { - return m.Received - } - return false -} - -func (m *LongLivedGracefulRestartState) GetAdvertised() bool { - if m != nil { - return m.Advertised - } - return false -} - -func (m *LongLivedGracefulRestartState) GetPeerRestartTime() uint32 { - if m != nil { - return m.PeerRestartTime - } - return 0 -} - -func (m *LongLivedGracefulRestartState) GetPeerRestartTimerExpired() bool { - if m != nil { - return m.PeerRestartTimerExpired - } - return false -} - -type LongLivedGracefulRestart struct { - Config *LongLivedGracefulRestartConfig `protobuf:"bytes,1,opt,name=config" json:"config,omitempty"` - State *LongLivedGracefulRestartState `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` -} - -func (m *LongLivedGracefulRestart) Reset() { *m = LongLivedGracefulRestart{} } -func (m *LongLivedGracefulRestart) String() string { return proto.CompactTextString(m) } -func (*LongLivedGracefulRestart) ProtoMessage() {} -func (*LongLivedGracefulRestart) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{140} } - -func (m *LongLivedGracefulRestart) GetConfig() *LongLivedGracefulRestartConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *LongLivedGracefulRestart) GetState() *LongLivedGracefulRestartState { - if m != nil { - return m.State - } - return nil -} - -type AfiSafi struct { - MpGracefulRestart *MpGracefulRestart `protobuf:"bytes,1,opt,name=mp_graceful_restart,json=mpGracefulRestart" json:"mp_graceful_restart,omitempty"` - Config *AfiSafiConfig `protobuf:"bytes,2,opt,name=config" json:"config,omitempty"` - ApplyPolicy *ApplyPolicy `protobuf:"bytes,3,opt,name=apply_policy,json=applyPolicy" json:"apply_policy,omitempty"` - // TODO: - // Support the following structures: - // - Ipv4Unicast - // - Ipv6Unicast - // - Ipv4LabelledUnicast - // - Ipv6LabelledUnicast - // - L3vpnIpv4Unicast - // - L3vpnIpv6Unicast - // - L3vpnIpv4Multicast - // - L3vpnIpv6Multicast - // - L2vpnVpls - // - L2vpnEvpn - RouteSelectionOptions *RouteSelectionOptions `protobuf:"bytes,4,opt,name=route_selection_options,json=routeSelectionOptions" json:"route_selection_options,omitempty"` - UseMultiplePaths *UseMultiplePaths `protobuf:"bytes,5,opt,name=use_multiple_paths,json=useMultiplePaths" json:"use_multiple_paths,omitempty"` - PrefixLimits *PrefixLimit `protobuf:"bytes,6,opt,name=prefix_limits,json=prefixLimits" json:"prefix_limits,omitempty"` - RouteTargetMembership *RouteTargetMembership `protobuf:"bytes,7,opt,name=route_target_membership,json=routeTargetMembership" json:"route_target_membership,omitempty"` - LongLivedGracefulRestart *LongLivedGracefulRestart `protobuf:"bytes,8,opt,name=long_lived_graceful_restart,json=longLivedGracefulRestart" json:"long_lived_graceful_restart,omitempty"` -} - -func (m *AfiSafi) Reset() { *m = AfiSafi{} } -func (m *AfiSafi) String() string { return proto.CompactTextString(m) } -func (*AfiSafi) ProtoMessage() {} -func (*AfiSafi) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{141} } - -func (m *AfiSafi) GetMpGracefulRestart() *MpGracefulRestart { - if m != nil { - return m.MpGracefulRestart - } - return nil -} - -func (m *AfiSafi) GetConfig() *AfiSafiConfig { - if m != nil { - return m.Config - } - return nil -} - -func (m *AfiSafi) GetApplyPolicy() *ApplyPolicy { - if m != nil { - return m.ApplyPolicy - } - return nil -} - -func (m *AfiSafi) GetRouteSelectionOptions() *RouteSelectionOptions { - if m != nil { - return m.RouteSelectionOptions - } - return nil -} - -func (m *AfiSafi) GetUseMultiplePaths() *UseMultiplePaths { - if m != nil { - return m.UseMultiplePaths - } - return nil -} - -func (m *AfiSafi) GetPrefixLimits() *PrefixLimit { - if m != nil { - return m.PrefixLimits - } - return nil -} - -func (m *AfiSafi) GetRouteTargetMembership() *RouteTargetMembership { - if m != nil { - return m.RouteTargetMembership - } - return nil -} - -func (m *AfiSafi) GetLongLivedGracefulRestart() *LongLivedGracefulRestart { - if m != nil { - return m.LongLivedGracefulRestart - } - return nil -} - type Prefix struct { IpPrefix string `protobuf:"bytes,1,opt,name=ip_prefix,json=ipPrefix" json:"ip_prefix,omitempty"` MaskLengthMin uint32 `protobuf:"varint,2,opt,name=mask_length_min,json=maskLengthMin" json:"mask_length_min,omitempty"` @@ -4119,7 +3294,7 @@ type Prefix struct { func (m *Prefix) Reset() { *m = Prefix{} } func (m *Prefix) String() string { return proto.CompactTextString(m) } func (*Prefix) ProtoMessage() {} -func (*Prefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{142} } +func (*Prefix) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{117} } func (m *Prefix) GetIpPrefix() string { if m != nil { @@ -4152,7 +3327,7 @@ type DefinedSet struct { func (m *DefinedSet) Reset() { *m = DefinedSet{} } func (m *DefinedSet) String() string { return proto.CompactTextString(m) } func (*DefinedSet) ProtoMessage() {} -func (*DefinedSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{143} } +func (*DefinedSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{118} } func (m *DefinedSet) GetType() DefinedType { if m != nil { @@ -4190,7 +3365,7 @@ type MatchSet struct { func (m *MatchSet) Reset() { *m = MatchSet{} } func (m *MatchSet) String() string { return proto.CompactTextString(m) } func (*MatchSet) ProtoMessage() {} -func (*MatchSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{144} } +func (*MatchSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{119} } func (m *MatchSet) GetType() MatchType { if m != nil { @@ -4214,7 +3389,7 @@ type AsPathLength struct { func (m *AsPathLength) Reset() { *m = AsPathLength{} } func (m *AsPathLength) String() string { return proto.CompactTextString(m) } func (*AsPathLength) ProtoMessage() {} -func (*AsPathLength) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{145} } +func (*AsPathLength) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{120} } func (m *AsPathLength) GetType() AsPathLengthType { if m != nil { @@ -4245,7 +3420,7 @@ type Conditions struct { func (m *Conditions) Reset() { *m = Conditions{} } func (m *Conditions) String() string { return proto.CompactTextString(m) } func (*Conditions) ProtoMessage() {} -func (*Conditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{146} } +func (*Conditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{121} } func (m *Conditions) GetPrefixSet() *MatchSet { if m != nil { @@ -4318,7 +3493,7 @@ type CommunityAction struct { func (m *CommunityAction) Reset() { *m = CommunityAction{} } func (m *CommunityAction) String() string { return proto.CompactTextString(m) } func (*CommunityAction) ProtoMessage() {} -func (*CommunityAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{147} } +func (*CommunityAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{122} } func (m *CommunityAction) GetType() CommunityActionType { if m != nil { @@ -4342,7 +3517,7 @@ type MedAction struct { func (m *MedAction) Reset() { *m = MedAction{} } func (m *MedAction) String() string { return proto.CompactTextString(m) } func (*MedAction) ProtoMessage() {} -func (*MedAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{148} } +func (*MedAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{123} } func (m *MedAction) GetType() MedActionType { if m != nil { @@ -4367,7 +3542,7 @@ type AsPrependAction struct { func (m *AsPrependAction) Reset() { *m = AsPrependAction{} } func (m *AsPrependAction) String() string { return proto.CompactTextString(m) } func (*AsPrependAction) ProtoMessage() {} -func (*AsPrependAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{149} } +func (*AsPrependAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{124} } func (m *AsPrependAction) GetAsn() uint32 { if m != nil { @@ -4398,7 +3573,7 @@ type NexthopAction struct { func (m *NexthopAction) Reset() { *m = NexthopAction{} } func (m *NexthopAction) String() string { return proto.CompactTextString(m) } func (*NexthopAction) ProtoMessage() {} -func (*NexthopAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{150} } +func (*NexthopAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{125} } func (m *NexthopAction) GetAddress() string { if m != nil { @@ -4421,7 +3596,7 @@ type LocalPrefAction struct { func (m *LocalPrefAction) Reset() { *m = LocalPrefAction{} } func (m *LocalPrefAction) String() string { return proto.CompactTextString(m) } func (*LocalPrefAction) ProtoMessage() {} -func (*LocalPrefAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{151} } +func (*LocalPrefAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{126} } func (m *LocalPrefAction) GetValue() uint32 { if m != nil { @@ -4444,7 +3619,7 @@ type Actions struct { func (m *Actions) Reset() { *m = Actions{} } func (m *Actions) String() string { return proto.CompactTextString(m) } func (*Actions) ProtoMessage() {} -func (*Actions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{152} } +func (*Actions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{127} } func (m *Actions) GetRouteAction() RouteAction { if m != nil { @@ -4511,7 +3686,7 @@ type Statement struct { func (m *Statement) Reset() { *m = Statement{} } func (m *Statement) String() string { return proto.CompactTextString(m) } func (*Statement) ProtoMessage() {} -func (*Statement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{153} } +func (*Statement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{128} } func (m *Statement) GetName() string { if m != nil { @@ -4542,7 +3717,7 @@ type Policy struct { func (m *Policy) Reset() { *m = Policy{} } func (m *Policy) String() string { return proto.CompactTextString(m) } func (*Policy) ProtoMessage() {} -func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{154} } +func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{129} } func (m *Policy) GetName() string { if m != nil { @@ -4569,7 +3744,7 @@ type PolicyAssignment struct { func (m *PolicyAssignment) Reset() { *m = PolicyAssignment{} } func (m *PolicyAssignment) String() string { return proto.CompactTextString(m) } func (*PolicyAssignment) ProtoMessage() {} -func (*PolicyAssignment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{155} } +func (*PolicyAssignment) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{130} } func (m *PolicyAssignment) GetType() PolicyType { if m != nil { @@ -4617,7 +3792,7 @@ type Roa struct { func (m *Roa) Reset() { *m = Roa{} } func (m *Roa) String() string { return proto.CompactTextString(m) } func (*Roa) ProtoMessage() {} -func (*Roa) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{156} } +func (*Roa) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{131} } func (m *Roa) GetAs() uint32 { if m != nil { @@ -4661,7 +3836,7 @@ type GetRoaRequest struct { func (m *GetRoaRequest) Reset() { *m = GetRoaRequest{} } func (m *GetRoaRequest) String() string { return proto.CompactTextString(m) } func (*GetRoaRequest) ProtoMessage() {} -func (*GetRoaRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{157} } +func (*GetRoaRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{132} } func (m *GetRoaRequest) GetFamily() uint32 { if m != nil { @@ -4677,7 +3852,7 @@ type GetRoaResponse struct { func (m *GetRoaResponse) Reset() { *m = GetRoaResponse{} } func (m *GetRoaResponse) String() string { return proto.CompactTextString(m) } func (*GetRoaResponse) ProtoMessage() {} -func (*GetRoaResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{158} } +func (*GetRoaResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{133} } func (m *GetRoaResponse) GetRoas() []*Roa { if m != nil { @@ -4697,7 +3872,7 @@ type Vrf struct { func (m *Vrf) Reset() { *m = Vrf{} } func (m *Vrf) String() string { return proto.CompactTextString(m) } func (*Vrf) ProtoMessage() {} -func (*Vrf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{159} } +func (*Vrf) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{134} } func (m *Vrf) GetName() string { if m != nil { @@ -4746,7 +3921,7 @@ type Global struct { func (m *Global) Reset() { *m = Global{} } func (m *Global) String() string { return proto.CompactTextString(m) } func (*Global) ProtoMessage() {} -func (*Global) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{160} } +func (*Global) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{135} } func (m *Global) GetAs() uint32 { if m != nil { @@ -4802,7 +3977,7 @@ type TableInfo struct { func (m *TableInfo) Reset() { *m = TableInfo{} } func (m *TableInfo) String() string { return proto.CompactTextString(m) } func (*TableInfo) ProtoMessage() {} -func (*TableInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{161} } +func (*TableInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{136} } func (m *TableInfo) GetType() Resource { if m != nil { @@ -4853,7 +4028,7 @@ type GetRibInfoRequest struct { func (m *GetRibInfoRequest) Reset() { *m = GetRibInfoRequest{} } func (m *GetRibInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetRibInfoRequest) ProtoMessage() {} -func (*GetRibInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{162} } +func (*GetRibInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{137} } func (m *GetRibInfoRequest) GetInfo() *TableInfo { if m != nil { @@ -4869,7 +4044,7 @@ type GetRibInfoResponse struct { func (m *GetRibInfoResponse) Reset() { *m = GetRibInfoResponse{} } func (m *GetRibInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetRibInfoResponse) ProtoMessage() {} -func (*GetRibInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{163} } +func (*GetRibInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{138} } func (m *GetRibInfoResponse) GetInfo() *TableInfo { if m != nil { @@ -4996,31 +4171,6 @@ func init() { proto.RegisterType((*TimersState)(nil), "gobgpapi.TimersState") proto.RegisterType((*Transport)(nil), "gobgpapi.Transport") proto.RegisterType((*RouteServer)(nil), "gobgpapi.RouteServer") - proto.RegisterType((*GracefulRestart)(nil), "gobgpapi.GracefulRestart") - proto.RegisterType((*MpGracefulRestartConfig)(nil), "gobgpapi.MpGracefulRestartConfig") - proto.RegisterType((*MpGracefulRestartState)(nil), "gobgpapi.MpGracefulRestartState") - proto.RegisterType((*MpGracefulRestart)(nil), "gobgpapi.MpGracefulRestart") - proto.RegisterType((*AfiSafiConfig)(nil), "gobgpapi.AfiSafiConfig") - proto.RegisterType((*AfiSafiState)(nil), "gobgpapi.AfiSafiState") - proto.RegisterType((*RouteSelectionOptionsConfig)(nil), "gobgpapi.RouteSelectionOptionsConfig") - proto.RegisterType((*RouteSelectionOptionsState)(nil), "gobgpapi.RouteSelectionOptionsState") - proto.RegisterType((*RouteSelectionOptions)(nil), "gobgpapi.RouteSelectionOptions") - proto.RegisterType((*UseMultiplePathsConfig)(nil), "gobgpapi.UseMultiplePathsConfig") - proto.RegisterType((*UseMultiplePathsState)(nil), "gobgpapi.UseMultiplePathsState") - proto.RegisterType((*EbgpConfig)(nil), "gobgpapi.EbgpConfig") - proto.RegisterType((*EbgpState)(nil), "gobgpapi.EbgpState") - proto.RegisterType((*Ebgp)(nil), "gobgpapi.Ebgp") - proto.RegisterType((*IbgpConfig)(nil), "gobgpapi.IbgpConfig") - proto.RegisterType((*IbgpState)(nil), "gobgpapi.IbgpState") - proto.RegisterType((*Ibgp)(nil), "gobgpapi.Ibgp") - proto.RegisterType((*UseMultiplePaths)(nil), "gobgpapi.UseMultiplePaths") - proto.RegisterType((*RouteTargetMembershipConfig)(nil), "gobgpapi.RouteTargetMembershipConfig") - proto.RegisterType((*RouteTargetMembershipState)(nil), "gobgpapi.RouteTargetMembershipState") - proto.RegisterType((*RouteTargetMembership)(nil), "gobgpapi.RouteTargetMembership") - proto.RegisterType((*LongLivedGracefulRestartConfig)(nil), "gobgpapi.LongLivedGracefulRestartConfig") - proto.RegisterType((*LongLivedGracefulRestartState)(nil), "gobgpapi.LongLivedGracefulRestartState") - proto.RegisterType((*LongLivedGracefulRestart)(nil), "gobgpapi.LongLivedGracefulRestart") - proto.RegisterType((*AfiSafi)(nil), "gobgpapi.AfiSafi") proto.RegisterType((*Prefix)(nil), "gobgpapi.Prefix") proto.RegisterType((*DefinedSet)(nil), "gobgpapi.DefinedSet") proto.RegisterType((*MatchSet)(nil), "gobgpapi.MatchSet") @@ -6872,428 +6022,367 @@ var _GobgpApi_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("gobgp.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 6761 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x7c, 0x4b, 0x8f, 0x1b, 0x49, - 0x72, 0x70, 0xf3, 0xd1, 0x6c, 0x32, 0x48, 0x36, 0xd9, 0xd9, 0x2f, 0x8a, 0x3d, 0x7a, 0xd5, 0x8e, - 0x46, 0x1a, 0x8d, 0x46, 0x33, 0xd2, 0xcc, 0x68, 0x66, 0x47, 0xab, 0xd9, 0xa5, 0xba, 0xa9, 0x16, - 0x77, 0xfa, 0xc1, 0xc9, 0xa6, 0xb4, 0x9a, 0xfd, 0x76, 0xbf, 0x72, 0x35, 0x2b, 0xc9, 0x2e, 0x4f, - 0xb1, 0xaa, 0xa6, 0xaa, 0xd8, 0xea, 0x86, 0x01, 0x1b, 0x58, 0x03, 0x86, 0x01, 0xc3, 0x17, 0x5f, - 0x6d, 0xc0, 0xf7, 0x85, 0x7d, 0xf0, 0xc9, 0x80, 0xcf, 0x5e, 0xc3, 0xc0, 0x02, 0xbe, 0xd8, 0x47, - 0x63, 0x7d, 0xf0, 0x0f, 0xf0, 0xc5, 0x07, 0x1f, 0x7c, 0x30, 0xf2, 0x51, 0x55, 0x59, 0x0f, 0x76, - 0xb7, 0xb4, 0x5a, 0x1b, 0x06, 0x7c, 0x22, 0x2b, 0x22, 0x32, 0x32, 0x32, 0x33, 0x22, 0x32, 0xf2, - 0x15, 0x50, 0x1d, 0xdb, 0x87, 0x63, 0xe7, 0xae, 0xe3, 0xda, 0xbe, 0x8d, 0xca, 0xec, 0x43, 0x73, - 0x0c, 0xe5, 0xc7, 0x80, 0xb6, 0x89, 0xbf, 0x47, 0x8c, 0xf1, 0xd1, 0xa1, 0xed, 0x62, 0xf2, 0xed, - 0x94, 0x78, 0x3e, 0xba, 0x0d, 0x4d, 0x62, 0x69, 0x87, 0x26, 0xe9, 0xe8, 0xc7, 0xc4, 0xf5, 0x0d, - 0x8f, 0xe8, 0xad, 0xdc, 0xb5, 0xdc, 0xad, 0x32, 0x4e, 0xc1, 0x51, 0x0b, 0x16, 0x34, 0x5d, 0x77, - 0x89, 0xe7, 0xb5, 0xf2, 0xd7, 0x72, 0xb7, 0x2a, 0x38, 0xf8, 0x54, 0x1e, 0xc2, 0x72, 0x8c, 0xb7, - 0xe7, 0xd8, 0x96, 0x47, 0xd0, 0xdb, 0x30, 0xef, 0x10, 0xe2, 0x7a, 0xad, 0xdc, 0xb5, 0xc2, 0xad, - 0xea, 0xfd, 0xc5, 0xbb, 0x81, 0x30, 0x77, 0xfb, 0x84, 0xb8, 0x98, 0x23, 0x95, 0x31, 0x54, 0x3a, - 0xee, 0x78, 0x3a, 0x21, 0x96, 0xef, 0xa1, 0xbb, 0x50, 0x76, 0x89, 0x67, 0x4f, 0xdd, 0x21, 0x61, - 0x72, 0x2c, 0xde, 0x47, 0x51, 0x29, 0x2c, 0x30, 0x38, 0xa4, 0x41, 0x6b, 0x50, 0x1a, 0x69, 0x13, - 0xc3, 0x3c, 0x65, 0x22, 0xd5, 0xb1, 0xf8, 0x42, 0x08, 0x8a, 0x96, 0x36, 0x21, 0xad, 0x02, 0x13, - 0x94, 0xfd, 0x57, 0x7e, 0x07, 0x16, 0x3b, 0xba, 0xde, 0xd7, 0xfc, 0xa3, 0xa0, 0xf5, 0xaf, 0x5a, - 0xdb, 0x2a, 0x94, 0x8e, 0xdd, 0x91, 0x6a, 0xe8, 0xa2, 0x03, 0xe6, 0x8f, 0xdd, 0x51, 0x4f, 0x47, - 0x0a, 0x14, 0x1d, 0xcd, 0x3f, 0x62, 0x95, 0xc5, 0x9b, 0x49, 0xeb, 0x62, 0x38, 0xe5, 0x06, 0x34, - 0xc2, 0xca, 0x45, 0xf7, 0x20, 0x28, 0x4e, 0xa7, 0x06, 0xef, 0xef, 0x1a, 0x66, 0xff, 0x95, 0x9f, - 0xe7, 0x60, 0x69, 0x8b, 0x98, 0xc4, 0x27, 0xbf, 0x01, 0x39, 0xa3, 0xce, 0x2a, 0xc4, 0x3a, 0x2b, - 0x90, 0xbf, 0x38, 0x5b, 0xfe, 0x50, 0xd8, 0x79, 0x49, 0xd8, 0x15, 0x40, 0xb2, 0xac, 0xbc, 0x59, - 0xca, 0x67, 0x80, 0x3a, 0xba, 0x9e, 0x54, 0x34, 0x5a, 0x07, 0x21, 0x2e, 0x13, 0x3f, 0xad, 0x0a, - 0x0c, 0xa7, 0xac, 0xc2, 0x72, 0xac, 0xa4, 0x60, 0xf8, 0x10, 0x56, 0x79, 0x35, 0xaf, 0xc3, 0xb3, - 0x05, 0x6b, 0xc9, 0xc2, 0x82, 0xed, 0x73, 0x58, 0xc1, 0xc4, 0x4b, 0x9b, 0x84, 0xa4, 0xe6, 0xb9, - 0x98, 0x9a, 0xa3, 0xb7, 0xa1, 0x3e, 0xb4, 0x27, 0x93, 0xa9, 0x65, 0x0c, 0x35, 0xdf, 0xb0, 0x2d, - 0xd1, 0xbb, 0x71, 0xa0, 0xb2, 0x0e, 0xab, 0x09, 0xbe, 0xa2, 0xc2, 0xbf, 0xc9, 0x41, 0xeb, 0xc0, - 0x1e, 0xf9, 0xaf, 0x58, 0xeb, 0x01, 0x54, 0x74, 0xc3, 0x25, 0xc3, 0xb0, 0xc6, 0xc5, 0xfb, 0x9f, - 0x44, 0x4d, 0x9d, 0xc5, 0x30, 0x42, 0x6c, 0x05, 0x85, 0x71, 0xc4, 0x47, 0xf9, 0x00, 0x50, 0x9a, - 0x00, 0x95, 0x20, 0xdf, 0xdb, 0x6b, 0xce, 0xa1, 0x05, 0x28, 0xec, 0x3f, 0x1b, 0x34, 0x73, 0xa8, - 0x0c, 0xc5, 0xc7, 0xfb, 0x83, 0xa7, 0xcd, 0xbc, 0xb2, 0x01, 0x97, 0x32, 0xaa, 0x12, 0x2d, 0xfb, - 0x1a, 0xd6, 0x0f, 0x8e, 0xa6, 0xbe, 0x6e, 0xbf, 0xb4, 0xde, 0x74, 0x6f, 0xb6, 0xa1, 0x95, 0x66, - 0x2d, 0xaa, 0xbd, 0x07, 0xab, 0x5d, 0xe6, 0xa4, 0x2e, 0x5c, 0x29, 0x55, 0x87, 0x64, 0x11, 0xc1, - 0xec, 0x05, 0xac, 0x6d, 0x19, 0xde, 0x2b, 0x71, 0xbb, 0x60, 0x13, 0x2e, 0xc1, 0x7a, 0x8a, 0xb3, - 0xa8, 0x74, 0x0c, 0x4d, 0x2e, 0xce, 0xae, 0xeb, 0x07, 0xd5, 0x6d, 0x40, 0x45, 0x9f, 0x4e, 0x1c, - 0xd5, 0x3f, 0x75, 0xb8, 0xb5, 0xcf, 0xe3, 0x32, 0x05, 0x0c, 0x4e, 0x1d, 0x82, 0xda, 0x50, 0x1e, - 0x19, 0x26, 0x61, 0xbe, 0x8d, 0x57, 0x16, 0x7e, 0x53, 0x9c, 0x61, 0xf9, 0xc4, 0x3d, 0xd6, 0x4c, - 0x66, 0xe0, 0x45, 0x1c, 0x7e, 0x2b, 0xcb, 0xb0, 0x24, 0x55, 0x24, 0x6a, 0x5f, 0x86, 0x25, 0x21, - 0x58, 0x54, 0x3d, 0x33, 0x6a, 0x09, 0x28, 0x48, 0x7f, 0x0f, 0x9a, 0x3d, 0xeb, 0xb7, 0xc9, 0xd0, - 0x97, 0x04, 0x7d, 0x43, 0x5e, 0x89, 0xce, 0x12, 0x9a, 0x7f, 0xe4, 0xb5, 0x0a, 0xa9, 0x59, 0x82, - 0xba, 0x15, 0x8e, 0xa4, 0xb2, 0x4a, 0x02, 0x08, 0xa9, 0xfe, 0x22, 0x07, 0xf5, 0x8e, 0xae, 0x3f, - 0x9e, 0x38, 0xe7, 0x8f, 0x15, 0x82, 0xa2, 0x63, 0xbb, 0xbe, 0x98, 0x27, 0xd8, 0x7f, 0xf4, 0x3d, - 0x28, 0xb2, 0x5e, 0x2e, 0x30, 0xe9, 0x6f, 0x45, 0x35, 0xc7, 0x98, 0xde, 0xdd, 0xb5, 0x2d, 0xc3, - 0xb7, 0x5d, 0xc3, 0x1a, 0xf7, 0x6d, 0xd3, 0x18, 0x9e, 0x62, 0x56, 0x4a, 0xf9, 0x00, 0x9a, 0x49, - 0x0c, 0xb5, 0x9c, 0x3e, 0xee, 0x36, 0xe7, 0xa8, 0xe5, 0xf4, 0xf7, 0x0f, 0xe2, 0x36, 0xd4, 0x64, - 0x13, 0x10, 0x63, 0x2c, 0x1a, 0xf0, 0x03, 0x68, 0x72, 0xef, 0xf4, 0xba, 0x4d, 0x60, 0x63, 0x18, - 0x71, 0x10, 0x6c, 0x07, 0xb0, 0x24, 0x24, 0xc3, 0xc6, 0x61, 0xc0, 0xf7, 0x06, 0xcc, 0xfb, 0x74, - 0x58, 0x85, 0xbb, 0x6c, 0x44, 0xad, 0x1d, 0x50, 0x30, 0xe6, 0x58, 0x5a, 0xfd, 0x70, 0xea, 0xba, - 0xc4, 0xe2, 0xf5, 0x94, 0x71, 0xf0, 0xa9, 0x74, 0xa1, 0x8c, 0xfb, 0x5f, 0xf6, 0x36, 0x6d, 0x6b, - 0x74, 0x86, 0x90, 0x57, 0xa1, 0xea, 0x92, 0x89, 0xed, 0x13, 0x35, 0x94, 0xb5, 0x82, 0x81, 0x83, - 0xfa, 0x54, 0xe2, 0x3f, 0x2b, 0x42, 0x85, 0xf2, 0x39, 0xf0, 0x35, 0x9f, 0x4d, 0xe0, 0x53, 0xc7, - 0x37, 0x26, 0x5c, 0xac, 0x02, 0x16, 0x5f, 0x54, 0x99, 0xa9, 0xcd, 0x33, 0x4c, 0x9e, 0x61, 0xc2, - 0x6f, 0xb4, 0x08, 0xf9, 0xa9, 0xc3, 0x06, 0xad, 0x8c, 0xf3, 0x53, 0x87, 0x57, 0x39, 0xb4, 0x5d, - 0x5d, 0x35, 0x9c, 0xe3, 0x8f, 0xd9, 0x34, 0x56, 0xa7, 0x55, 0x52, 0x50, 0xcf, 0x39, 0xfe, 0x38, - 0x4e, 0xf0, 0x80, 0xcd, 0x61, 0x32, 0xc1, 0x03, 0x4a, 0xe0, 0xb8, 0x64, 0x64, 0x9c, 0x70, 0x0e, - 0x25, 0x4e, 0xc0, 0x41, 0x01, 0x87, 0x88, 0xe0, 0x41, 0x6b, 0x21, 0x41, 0xf0, 0x80, 0xb6, 0xc3, - 0x23, 0xae, 0xa1, 0x99, 0xad, 0x32, 0x9f, 0x5b, 0xf9, 0x17, 0xfa, 0x0e, 0xd4, 0x5d, 0x32, 0x24, - 0xc6, 0x31, 0x11, 0xd2, 0x55, 0x58, 0x63, 0x6a, 0x01, 0x90, 0x71, 0x4f, 0x10, 0x3d, 0x68, 0x41, - 0x8a, 0xe8, 0x01, 0x25, 0xe2, 0x3c, 0x55, 0xcb, 0xf6, 0x8d, 0xd1, 0x69, 0xab, 0xca, 0x89, 0x38, - 0x70, 0x8f, 0xc1, 0xa8, 0x9c, 0x43, 0x6d, 0x78, 0x44, 0x54, 0x97, 0x3a, 0xea, 0x56, 0x8d, 0x91, - 0x00, 0x03, 0x31, 0xd7, 0x8d, 0x6e, 0xc0, 0x62, 0x48, 0xc0, 0x94, 0xa5, 0x55, 0x67, 0x34, 0xf5, - 0x80, 0x86, 0xc7, 0x26, 0x57, 0xa0, 0x4a, 0x2c, 0x5d, 0xb5, 0x47, 0xaa, 0xae, 0xf9, 0x5a, 0x6b, - 0x91, 0xd1, 0x54, 0x88, 0xa5, 0xef, 0x8f, 0xb6, 0x34, 0x5f, 0x43, 0x2b, 0x30, 0x4f, 0x5c, 0xd7, - 0x76, 0x5b, 0x0d, 0x86, 0xe1, 0x1f, 0xe8, 0x3a, 0x08, 0x69, 0xd4, 0x6f, 0xa7, 0xc4, 0x3d, 0x6d, - 0x35, 0x19, 0xb2, 0xca, 0x61, 0x5f, 0x51, 0x10, 0x1f, 0x0a, 0x8f, 0xf8, 0x82, 0x62, 0x89, 0x0b, - 0xc8, 0x40, 0x8c, 0x40, 0xf9, 0x1a, 0x8a, 0xd8, 0xf9, 0xc6, 0x40, 0xef, 0x40, 0x71, 0x68, 0x5b, - 0x23, 0xa1, 0xad, 0xb2, 0x67, 0x11, 0x3a, 0x88, 0x19, 0x1e, 0xbd, 0x0b, 0xf3, 0x1e, 0xd5, 0x24, - 0xa6, 0x25, 0xd5, 0xfb, 0xcb, 0x71, 0x42, 0xa6, 0x64, 0x98, 0x53, 0x28, 0xb7, 0x60, 0x71, 0x9b, - 0xf8, 0x94, 0x7b, 0x60, 0x13, 0x51, 0x44, 0x94, 0x93, 0x23, 0x22, 0xe5, 0x21, 0x34, 0x42, 0x4a, - 0xd1, 0x23, 0xb7, 0x60, 0xc1, 0x23, 0xee, 0x71, 0x66, 0x38, 0xcb, 0x08, 0x03, 0xb4, 0xf2, 0x63, - 0x66, 0xe6, 0x72, 0x35, 0xaf, 0xe6, 0x95, 0xda, 0x50, 0x36, 0x8d, 0x11, 0x61, 0xaa, 0x5f, 0xe0, - 0xaa, 0x1f, 0x7c, 0x2b, 0x4b, 0x2c, 0x8c, 0x94, 0x05, 0x53, 0x3a, 0x81, 0x07, 0x78, 0xed, 0x1a, - 0xa3, 0x40, 0x2e, 0xc6, 0xf8, 0xfd, 0x60, 0xce, 0xb8, 0x10, 0x63, 0xca, 0x44, 0x26, 0x17, 0x4c, - 0xee, 0x86, 0xd3, 0xc9, 0xc5, 0xb8, 0xac, 0xc2, 0x72, 0x8c, 0x5e, 0xb0, 0xb9, 0x03, 0x4d, 0xa6, - 0xbf, 0x17, 0x63, 0xb2, 0x0c, 0x4b, 0x12, 0xb5, 0x60, 0xf1, 0x21, 0xac, 0x84, 0x11, 0xcc, 0xc5, - 0xd8, 0xac, 0xc3, 0x6a, 0xa2, 0x84, 0x60, 0xf5, 0xcb, 0x5c, 0xd0, 0xd6, 0x1f, 0x93, 0x43, 0x57, - 0x0b, 0x38, 0x35, 0xa1, 0x30, 0x75, 0x4d, 0xc1, 0x85, 0xfe, 0x65, 0xda, 0x6e, 0x4f, 0x7d, 0xc2, - 0x26, 0x73, 0xba, 0x6c, 0x2a, 0x30, 0x67, 0x48, 0x41, 0x74, 0x3a, 0xf7, 0x68, 0xe5, 0x54, 0x67, - 0x68, 0xec, 0xc0, 0x63, 0xf2, 0xe0, 0x13, 0x7d, 0x0c, 0x6b, 0x16, 0x39, 0xf1, 0x8f, 0x6c, 0x47, - 0xf5, 0x5d, 0x63, 0x3c, 0x26, 0xae, 0xca, 0x57, 0x64, 0xcc, 0xbf, 0x95, 0xf1, 0x8a, 0xc0, 0x0e, - 0x38, 0x92, 0x8b, 0x83, 0xee, 0xc3, 0x6a, 0xb2, 0x94, 0x4e, 0x4c, 0xed, 0x54, 0xf8, 0xbc, 0xe5, - 0x78, 0xa1, 0x2d, 0x8a, 0xa2, 0x5d, 0x1e, 0x6b, 0x8c, 0x68, 0x64, 0x03, 0xea, 0xdb, 0xc4, 0x7f, - 0xee, 0x8e, 0x82, 0xc8, 0xe0, 0x23, 0x66, 0x3e, 0x0c, 0x20, 0x6c, 0xe2, 0x3a, 0x14, 0x8f, 0xdd, - 0x51, 0x60, 0x10, 0xf5, 0xc8, 0x20, 0x28, 0x11, 0x43, 0x29, 0x1f, 0xb2, 0x19, 0x3a, 0xe2, 0x82, - 0xae, 0x42, 0xe1, 0xd8, 0x0d, 0xcc, 0x3a, 0x51, 0x84, 0x62, 0xc4, 0x2c, 0x29, 0x55, 0xa3, 0x7c, - 0x14, 0xcc, 0x92, 0xaf, 0xc2, 0x26, 0x9c, 0x18, 0x65, 0x4e, 0xcf, 0x60, 0x65, 0x9b, 0xf8, 0x5b, - 0x64, 0x64, 0x58, 0x44, 0x3f, 0x20, 0x61, 0x28, 0xf3, 0xae, 0x08, 0x04, 0x78, 0x18, 0xb3, 0x1a, - 0xb1, 0x13, 0xa4, 0x74, 0xb0, 0xf8, 0xac, 0x1f, 0xae, 0x2c, 0xf3, 0xd2, 0xca, 0xb2, 0x03, 0xab, - 0x09, 0xb6, 0xa1, 0xd3, 0x28, 0x7a, 0xc4, 0x0f, 0x3a, 0x68, 0x25, 0xc5, 0x97, 0xd2, 0x32, 0x0a, - 0xe5, 0x0b, 0x58, 0xe9, 0xe8, 0x7a, 0x5a, 0xb2, 0x77, 0xa0, 0x40, 0x1d, 0x39, 0x6f, 0x67, 0x36, - 0x03, 0x4a, 0x40, 0x75, 0x35, 0x51, 0x5e, 0x34, 0xf9, 0x00, 0xd6, 0x79, 0x3f, 0xbc, 0x36, 0x6f, - 0xaa, 0xd7, 0x9a, 0x69, 0x8a, 0x70, 0x80, 0xfe, 0xa5, 0x51, 0x79, 0x9a, 0xa9, 0xa8, 0xf0, 0x31, - 0xb4, 0x30, 0x71, 0x4c, 0x6d, 0xf8, 0xfa, 0x35, 0xd2, 0xd5, 0x46, 0x06, 0x0f, 0x51, 0xc1, 0x2a, - 0xdb, 0x6d, 0x60, 0x9e, 0x7d, 0x42, 0xac, 0x30, 0x70, 0xfd, 0x92, 0x8d, 0xad, 0x04, 0x16, 0x63, - 0xf0, 0x11, 0x80, 0x17, 0x00, 0x83, 0x91, 0x90, 0x66, 0x89, 0xa8, 0x80, 0x44, 0xa6, 0x3c, 0x65, - 0x4b, 0xd1, 0x64, 0x1d, 0xe8, 0x1e, 0x54, 0x42, 0x22, 0xd1, 0x8a, 0x4c, 0x56, 0x11, 0x95, 0xb2, - 0xc6, 0x06, 0x36, 0x25, 0x96, 0xf2, 0xd3, 0x60, 0x61, 0xfa, 0x06, 0x2a, 0xc9, 0x18, 0xa1, 0x4b, - 0xc1, 0xb0, 0xa7, 0x6b, 0xde, 0x81, 0x75, 0xd1, 0xb9, 0x6f, 0xa2, 0x7d, 0xed, 0x70, 0xb8, 0xd3, - 0x35, 0x21, 0x68, 0x6e, 0x13, 0x5f, 0x04, 0xcd, 0x62, 0x98, 0x3a, 0xb0, 0x24, 0xc1, 0xc4, 0x18, - 0xdd, 0x81, 0xb2, 0x43, 0x21, 0x06, 0x09, 0x46, 0xa8, 0x29, 0x2d, 0x03, 0x38, 0x6d, 0x48, 0xa1, - 0x9c, 0x40, 0xb3, 0xa3, 0xeb, 0x31, 0xb6, 0xe8, 0x16, 0x94, 0x18, 0xfe, 0x54, 0x88, 0x9d, 0x2e, - 0x2f, 0xf0, 0xe8, 0x73, 0xb8, 0xe4, 0x92, 0x11, 0x75, 0xa7, 0x27, 0x86, 0xe7, 0x1b, 0xd6, 0x58, - 0x95, 0xd4, 0x83, 0xf7, 0xe0, 0x3a, 0x23, 0xe8, 0x0a, 0xfc, 0x41, 0xa4, 0x16, 0xcb, 0xb0, 0x24, - 0xd5, 0x2c, 0x5a, 0xf9, 0xb3, 0x1c, 0x2c, 0x8b, 0x7d, 0x90, 0xd7, 0x14, 0xe9, 0x03, 0x58, 0x76, - 0x68, 0x08, 0xe4, 0x1e, 0x93, 0xb4, 0x30, 0x28, 0x40, 0x45, 0x72, 0x04, 0xe3, 0x5d, 0x88, 0xc6, - 0x7b, 0x0d, 0x56, 0xe2, 0x32, 0x08, 0xe1, 0xfe, 0x32, 0x07, 0x2b, 0x62, 0x7c, 0xfe, 0x07, 0x3a, - 0x6c, 0x56, 0xcb, 0x0a, 0xb3, 0x5a, 0xc6, 0x77, 0x4f, 0x62, 0xe2, 0x86, 0xeb, 0xf3, 0x76, 0xa8, - 0x37, 0x1d, 0xcf, 0x33, 0xc6, 0x96, 0xac, 0xb8, 0x9f, 0x03, 0x68, 0x21, 0x50, 0xb4, 0xa8, 0x9d, - 0x6c, 0x91, 0x54, 0x4c, 0xa2, 0x56, 0xbe, 0x86, 0x8d, 0x4c, 0xce, 0x42, 0x37, 0x7f, 0x1d, 0xd6, - 0x2f, 0xa0, 0x1d, 0xea, 0xcb, 0x9b, 0x15, 0xfa, 0x32, 0x6c, 0x64, 0x72, 0x16, 0xbd, 0x35, 0x81, - 0xcb, 0xb2, 0x3a, 0xbc, 0xd1, 0xba, 0x33, 0xbc, 0xcd, 0x35, 0xb8, 0x32, 0xab, 0x3a, 0x21, 0xd0, - 0x4f, 0xe0, 0x4a, 0x6c, 0x5c, 0xdf, 0x6c, 0x6f, 0x5c, 0x87, 0xab, 0x33, 0xb9, 0xc7, 0x7c, 0xd1, - 0x01, 0x8b, 0xd1, 0x03, 0x5f, 0xf4, 0x88, 0xf9, 0xa2, 0x00, 0x16, 0xce, 0xd9, 0xa5, 0xb1, 0x69, - 0x1f, 0x6a, 0x66, 0xda, 0x30, 0xb6, 0x19, 0x1c, 0x0b, 0xbc, 0xf2, 0x05, 0xa0, 0x03, 0x5f, 0x73, - 0xe3, 0x4c, 0x5f, 0xa1, 0xfc, 0x2a, 0x2c, 0xc7, 0xca, 0x47, 0xdb, 0x32, 0x07, 0xbe, 0xed, 0xc4, - 0x45, 0x5d, 0xa1, 0x75, 0x45, 0x40, 0x41, 0xfa, 0xab, 0x02, 0x14, 0xfb, 0x62, 0x7b, 0xd6, 0x32, - 0x5d, 0x23, 0xd8, 0x4b, 0xa6, 0xff, 0xe9, 0xe2, 0xc6, 0xd1, 0x7c, 0xdf, 0xe5, 0x71, 0x67, 0x0d, - 0x8b, 0x2f, 0x36, 0x7c, 0xe3, 0x60, 0x69, 0x41, 0xff, 0xd2, 0xd2, 0x87, 0xc4, 0xf3, 0x45, 0x64, - 0xc9, 0xfe, 0xd3, 0xd0, 0xd5, 0xf0, 0xd4, 0x97, 0x86, 0x7f, 0xa4, 0xbb, 0xda, 0x4b, 0x16, 0x3f, - 0x96, 0x31, 0x18, 0xde, 0x8f, 0x04, 0x04, 0x5d, 0x01, 0x38, 0xd6, 0x4c, 0x43, 0xe7, 0x3b, 0x5f, - 0x25, 0xb6, 0x51, 0x25, 0x41, 0xd0, 0x87, 0xb0, 0x62, 0xd9, 0xaa, 0x31, 0x71, 0xa8, 0xd7, 0xf6, - 0x23, 0x4e, 0x0b, 0xdc, 0xf6, 0x2d, 0xbb, 0x27, 0x50, 0x21, 0xc7, 0x68, 0x35, 0x56, 0x8e, 0xed, - 0x4f, 0x5f, 0x06, 0xe0, 0x5b, 0x48, 0xaa, 0xe6, 0x59, 0x6c, 0x01, 0x5d, 0xc7, 0x15, 0x0e, 0xe9, - 0x78, 0x16, 0xda, 0x00, 0xf1, 0xa1, 0x1a, 0x3a, 0x5b, 0x39, 0x57, 0x70, 0x99, 0x03, 0x7a, 0xba, - 0xd8, 0x30, 0xf3, 0x89, 0x4b, 0x74, 0xb6, 0x60, 0x2e, 0xe3, 0xf0, 0x9b, 0x2e, 0x62, 0x3d, 0x5f, - 0x33, 0x09, 0x5b, 0x26, 0x97, 0x31, 0xff, 0x40, 0xb7, 0xa0, 0x69, 0x78, 0xea, 0xc8, 0xb5, 0x27, - 0x2a, 0x39, 0xf1, 0x89, 0x6b, 0x69, 0x26, 0x5b, 0x23, 0x97, 0xf1, 0xa2, 0xe1, 0x3d, 0x71, 0xed, - 0x49, 0x57, 0x40, 0x69, 0x17, 0x59, 0x62, 0x47, 0x4f, 0x35, 0x1c, 0xb6, 0x48, 0xae, 0x60, 0x08, - 0x40, 0x3d, 0x27, 0xdc, 0x34, 0x6f, 0x44, 0x9b, 0xe6, 0xe8, 0x0e, 0x20, 0xc3, 0x53, 0x83, 0x20, - 0xdd, 0xb0, 0x58, 0x8f, 0xb1, 0x95, 0x72, 0x19, 0x37, 0x0d, 0x6f, 0x8f, 0x23, 0x7a, 0x1c, 0xae, - 0xfc, 0x79, 0x0e, 0xaa, 0x5b, 0x84, 0x7a, 0x55, 0xde, 0xa9, 0x74, 0x4c, 0xd9, 0xa6, 0x83, 0x58, - 0x65, 0x88, 0xaf, 0x68, 0x13, 0x2d, 0x7f, 0xc6, 0x26, 0x1a, 0xba, 0x09, 0x0d, 0xd3, 0xb6, 0xe8, - 0xa2, 0x80, 0x17, 0x23, 0x81, 0x27, 0x5e, 0xe4, 0xe0, 0xbe, 0x80, 0xa2, 0x77, 0xa1, 0xe9, 0x1d, - 0xd9, 0xae, 0x2f, 0x53, 0x72, 0xe5, 0x68, 0x08, 0x78, 0x40, 0xaa, 0xfc, 0x75, 0x0e, 0xe6, 0xd9, - 0x06, 0x12, 0x5d, 0xb1, 0x4b, 0x41, 0x74, 0xd6, 0x5e, 0xe0, 0xcc, 0x08, 0x7a, 0xe6, 0xd1, 0xc4, - 0x77, 0xa1, 0xa6, 0x47, 0xcd, 0xa7, 0x42, 0xd0, 0xe6, 0xc5, 0x02, 0xf4, 0x10, 0x8b, 0x63, 0xa4, - 0x6c, 0xcb, 0xc6, 0xf6, 0x7c, 0x55, 0xcc, 0x72, 0x42, 0x81, 0x29, 0x88, 0xfb, 0x08, 0xe5, 0x01, - 0x5b, 0xe0, 0xbc, 0xf2, 0x0e, 0x99, 0xf2, 0x29, 0xdf, 0x46, 0xa0, 0xe5, 0x84, 0xcb, 0xb8, 0x60, - 0x41, 0x13, 0xd0, 0x73, 0x6e, 0x1f, 0x44, 0xaa, 0xf5, 0xa2, 0xdd, 0x36, 0xeb, 0xa8, 0x2b, 0x52, - 0x89, 0x82, 0xac, 0x12, 0xd4, 0xbb, 0xc4, 0x6a, 0x0b, 0x4e, 0x21, 0x8a, 0x50, 0xec, 0x13, 0xe2, - 0x32, 0xcb, 0xa0, 0x1c, 0x82, 0x98, 0xab, 0x8e, 0xc3, 0x6f, 0xf4, 0x19, 0xd4, 0x34, 0xc7, 0x31, - 0x4f, 0x83, 0xce, 0xe3, 0x7b, 0x2b, 0x52, 0xb7, 0x77, 0x28, 0x56, 0xcc, 0xd0, 0x55, 0x2d, 0xfa, - 0x08, 0xb7, 0x6d, 0x0a, 0xc9, 0x6d, 0x1b, 0x5a, 0xa7, 0xb4, 0x6d, 0xf3, 0x10, 0xea, 0xe4, 0x70, - 0xec, 0xa8, 0x93, 0xa9, 0xe9, 0x1b, 0x47, 0xb6, 0x23, 0x0e, 0x9f, 0xd6, 0xa2, 0x02, 0xdd, 0xc3, - 0xb1, 0xb3, 0x2b, 0xb0, 0xb8, 0x46, 0xa4, 0x2f, 0xd4, 0x81, 0x06, 0x5f, 0x56, 0xbb, 0x64, 0x64, - 0x92, 0xa1, 0x6f, 0xbb, 0x6c, 0x78, 0xab, 0xf7, 0x5b, 0x52, 0xef, 0x51, 0x02, 0x1c, 0xe0, 0xf1, - 0xa2, 0x1b, 0xfb, 0x46, 0x37, 0xa1, 0x68, 0x58, 0x23, 0x9b, 0xf9, 0xad, 0x58, 0x90, 0x4b, 0xe5, - 0xe4, 0xbb, 0x46, 0x8c, 0x80, 0xba, 0x73, 0xdf, 0x98, 0x10, 0xd7, 0x63, 0x8e, 0x2b, 0xe6, 0xce, - 0x07, 0x0c, 0x8e, 0x05, 0x9e, 0x06, 0xcf, 0xbe, 0xab, 0x59, 0x1e, 0xdb, 0x5e, 0x29, 0x27, 0xf9, - 0x0e, 0x02, 0x14, 0x8e, 0xa8, 0x68, 0x3f, 0xf3, 0x86, 0xf0, 0xbd, 0x23, 0xe6, 0xdb, 0x62, 0xfd, - 0xcc, 0x5a, 0x21, 0x9c, 0x3e, 0xdf, 0x4a, 0xe0, 0x1f, 0x68, 0x0b, 0x9a, 0x63, 0x57, 0x1b, 0x92, - 0xd1, 0xd4, 0x54, 0x5d, 0xe2, 0xd1, 0x69, 0x84, 0xf9, 0xbe, 0xea, 0xfd, 0x4b, 0xd2, 0x7c, 0x23, - 0x28, 0x30, 0x27, 0xc0, 0x8d, 0x71, 0x1c, 0x80, 0xee, 0x42, 0x45, 0x1b, 0x19, 0xaa, 0xa7, 0x8d, - 0x0c, 0xaf, 0x55, 0x65, 0xb6, 0xb5, 0x24, 0x0d, 0xf2, 0xc8, 0x38, 0xd0, 0x46, 0x06, 0x2e, 0x6b, - 0xfc, 0x8f, 0xa7, 0xfc, 0x7d, 0x0e, 0xaa, 0xd2, 0xd0, 0xa3, 0x4f, 0xa1, 0x62, 0x58, 0x6a, 0x2c, - 0x8e, 0x3c, 0x6b, 0xca, 0x2e, 0x1b, 0x96, 0x28, 0xf8, 0x7d, 0xa8, 0x93, 0x13, 0xda, 0x05, 0x71, - 0x0d, 0x3b, 0xab, 0x70, 0x8d, 0x17, 0x88, 0x18, 0x18, 0x13, 0x99, 0x41, 0xe1, 0x7c, 0x06, 0xbc, - 0x80, 0xb0, 0xfe, 0xdf, 0x85, 0x2a, 0xf7, 0x61, 0x3b, 0xc6, 0xc4, 0x98, 0xb9, 0x13, 0x88, 0xae, - 0x43, 0x6d, 0xa2, 0x9d, 0x44, 0x5e, 0x90, 0xdb, 0x5e, 0x75, 0xa2, 0x9d, 0x84, 0xce, 0xf2, 0x63, - 0x58, 0xf3, 0xc4, 0x11, 0x95, 0xea, 0x1f, 0xb9, 0xc4, 0x3b, 0xb2, 0x4d, 0x5d, 0x75, 0x86, 0xbe, - 0xf0, 0x65, 0x2b, 0x01, 0x76, 0x10, 0x20, 0xfb, 0x43, 0x5f, 0xf9, 0xcf, 0x79, 0x28, 0x07, 0x36, - 0x81, 0xbe, 0x03, 0x75, 0x6d, 0xea, 0x1f, 0xa9, 0x8e, 0xe6, 0x79, 0x2f, 0x6d, 0x57, 0x17, 0xde, - 0xbd, 0x46, 0x81, 0x7d, 0x01, 0x43, 0xd7, 0xa0, 0xaa, 0x13, 0x6f, 0xe8, 0x1a, 0x8e, 0x74, 0xd6, - 0x24, 0x83, 0xd0, 0x25, 0x28, 0x9b, 0xf6, 0x50, 0x33, 0x55, 0xcd, 0x0b, 0xb6, 0x93, 0xd8, 0x77, - 0x87, 0x79, 0xf4, 0x70, 0xae, 0x0a, 0xb6, 0xbb, 0x8a, 0x8c, 0x43, 0x23, 0x80, 0x77, 0xc4, 0x0e, - 0xe1, 0x3a, 0x2c, 0x38, 0x84, 0xb8, 0x94, 0x09, 0xdf, 0x35, 0x2a, 0xd1, 0xcf, 0x8e, 0x47, 0xe7, - 0x61, 0x86, 0x18, 0xbb, 0xf6, 0xd4, 0x61, 0x96, 0x53, 0xc1, 0x15, 0x0a, 0xd9, 0xa6, 0x00, 0x3a, - 0x0f, 0x33, 0x34, 0xf3, 0x66, 0x7c, 0x87, 0xbc, 0x4c, 0x01, 0xec, 0xe0, 0x6a, 0x0f, 0x96, 0x5c, - 0x32, 0xb1, 0x8f, 0x89, 0xea, 0xb8, 0xc6, 0xb1, 0xe6, 0xd3, 0xb9, 0x9c, 0x19, 0xc9, 0xe2, 0x7d, - 0x25, 0xed, 0x24, 0xee, 0x62, 0x46, 0xdb, 0xe7, 0xa4, 0x1d, 0x0f, 0x37, 0xdc, 0x38, 0x80, 0x4e, - 0xa3, 0xdc, 0x72, 0x46, 0xa6, 0xe6, 0xa8, 0xba, 0x36, 0x71, 0x0c, 0x6b, 0xcc, 0xec, 0xa7, 0x8c, - 0x9b, 0x0c, 0xf3, 0xc4, 0xd4, 0x9c, 0x2d, 0x0e, 0x47, 0x37, 0x60, 0xd1, 0x23, 0x96, 0xae, 0x8a, - 0x83, 0x39, 0xff, 0x94, 0xd9, 0x4a, 0x1d, 0xd7, 0x29, 0x74, 0x33, 0x00, 0xd2, 0x06, 0x8a, 0xb3, - 0x8b, 0xa1, 0xe6, 0x30, 0x7b, 0xa8, 0xe1, 0x0a, 0x87, 0x6c, 0x6a, 0xac, 0x81, 0xbc, 0x7b, 0x29, - 0xb6, 0xc6, 0xb0, 0xbc, 0xbf, 0x29, 0x72, 0x11, 0xf2, 0x86, 0xce, 0x02, 0x85, 0x0a, 0xce, 0x1b, - 0x3a, 0xfa, 0x1c, 0xea, 0xe2, 0xc4, 0xc0, 0xa4, 0x0a, 0xe6, 0xb5, 0x16, 0x93, 0x53, 0x97, 0xa4, - 0x7e, 0xb8, 0xe6, 0x44, 0x1f, 0x1e, 0x55, 0x07, 0x31, 0x8e, 0x62, 0xa4, 0x1a, 0x5c, 0x1d, 0xf8, - 0x60, 0x8a, 0x61, 0x7a, 0x1f, 0x50, 0x14, 0x7d, 0x58, 0x3e, 0x71, 0x47, 0xda, 0x90, 0xb0, 0x40, - 0xa2, 0x82, 0x97, 0xc2, 0x20, 0x24, 0x40, 0xd0, 0xa8, 0xef, 0xd8, 0x1d, 0xb1, 0x0d, 0xf7, 0x0a, - 0xdb, 0x21, 0x43, 0xd7, 0xa0, 0xa6, 0x99, 0xa6, 0xfd, 0x52, 0xa5, 0x8a, 0xab, 0x79, 0x2d, 0xc4, - 0x0f, 0x35, 0x18, 0x6c, 0xff, 0xa5, 0xd5, 0xf1, 0xd0, 0x3b, 0xd0, 0x70, 0x79, 0x58, 0xad, 0x06, - 0x1a, 0xb1, 0xcc, 0x7a, 0xb8, 0x2e, 0xc0, 0x7d, 0xa6, 0x18, 0xca, 0x3d, 0x68, 0x24, 0x06, 0x0c, - 0x95, 0xa1, 0xb8, 0xb7, 0xbf, 0xd7, 0xe5, 0x87, 0xc9, 0x9d, 0x9d, 0x9d, 0x66, 0x0e, 0x55, 0x61, - 0x01, 0x77, 0xfb, 0x3b, 0x9d, 0xcd, 0x6e, 0x33, 0xaf, 0x7c, 0x09, 0x35, 0xd9, 0xc1, 0xa3, 0x16, - 0x2c, 0xf0, 0xed, 0xcd, 0xe0, 0xfe, 0x49, 0xf0, 0xc9, 0x2c, 0x50, 0x50, 0xa9, 0xbe, 0x6f, 0x86, - 0x16, 0x28, 0x60, 0x03, 0xdf, 0x54, 0x7e, 0x3f, 0x07, 0x8b, 0x71, 0x7f, 0x4f, 0x8d, 0x32, 0x31, - 0x45, 0xa8, 0x43, 0xd3, 0x08, 0x56, 0x16, 0x65, 0xbc, 0x12, 0x9f, 0x0f, 0x36, 0x19, 0x0e, 0x3d, - 0x84, 0x76, 0xba, 0xd4, 0xd4, 0xa3, 0x71, 0x50, 0x78, 0x6c, 0xb9, 0x9e, 0x2c, 0xc9, 0xf0, 0x3d, - 0x5d, 0xf9, 0xab, 0x12, 0x54, 0xc2, 0xd9, 0xe3, 0xbf, 0xc1, 0xa4, 0xef, 0x42, 0x79, 0x42, 0x3c, - 0x4f, 0x1b, 0x8b, 0xe0, 0x2c, 0x36, 0xdd, 0xee, 0x0a, 0x0c, 0x0e, 0x69, 0x32, 0x5d, 0xc0, 0xfc, - 0xb9, 0x2e, 0xa0, 0x74, 0x86, 0x0b, 0x58, 0x38, 0xd3, 0x05, 0x94, 0x13, 0x2e, 0xe0, 0x16, 0x94, - 0xbe, 0x9d, 0x92, 0x29, 0xf1, 0xc4, 0x34, 0x27, 0xcd, 0xa4, 0x5f, 0x31, 0x38, 0x16, 0x78, 0x74, - 0x3b, 0xcb, 0x59, 0x70, 0x8b, 0xbd, 0xa0, 0x23, 0xa8, 0x5e, 0xd8, 0x11, 0xd4, 0xb2, 0x1c, 0x01, - 0x3b, 0x6b, 0xf3, 0x3c, 0xc3, 0xb6, 0xf8, 0xae, 0x05, 0xb3, 0xeb, 0x3a, 0xae, 0x09, 0x20, 0x1f, - 0xe1, 0x4f, 0x60, 0xcd, 0x9b, 0x3a, 0x74, 0x4a, 0x21, 0x3a, 0x75, 0x09, 0xda, 0xa1, 0x61, 0x1a, - 0x3e, 0x0d, 0xa7, 0x16, 0xd9, 0x3e, 0xff, 0x6a, 0x88, 0xdd, 0x94, 0x90, 0xb4, 0x8f, 0x68, 0xe0, - 0xc3, 0xf9, 0x72, 0xc3, 0x2e, 0x1f, 0x8e, 0x1d, 0xce, 0xf3, 0xfb, 0x50, 0xd5, 0xf4, 0x89, 0x11, - 0x54, 0xdb, 0x64, 0x0e, 0xf2, 0x4a, 0x46, 0x74, 0x72, 0xb7, 0x43, 0xc9, 0x78, 0xa0, 0x02, 0x5a, - 0xf8, 0x9f, 0x46, 0x75, 0xc1, 0xa9, 0x21, 0xb3, 0xf5, 0x3a, 0x0e, 0xbf, 0x29, 0x4e, 0x1b, 0x0e, - 0x89, 0xe3, 0x13, 0x5d, 0x18, 0x7b, 0xf8, 0x4d, 0x57, 0x73, 0x5a, 0x74, 0x05, 0x6c, 0x59, 0xb8, - 0x82, 0xe8, 0xf2, 0xd7, 0x32, 0xcc, 0xdb, 0x53, 0x5f, 0xfd, 0xb6, 0xb5, 0xc2, 0xcf, 0x8d, 0xec, - 0xa9, 0xff, 0x15, 0x5d, 0x40, 0x8d, 0x4c, 0xdb, 0xf1, 0x5a, 0xab, 0x0c, 0xc8, 0x3f, 0x94, 0xdb, - 0x00, 0x91, 0x70, 0xa8, 0x04, 0xf9, 0x67, 0x7d, 0x7e, 0x20, 0xbe, 0xb5, 0xff, 0xa3, 0xbd, 0x66, - 0x0e, 0x01, 0x94, 0xfa, 0x4f, 0x5e, 0xa8, 0x9b, 0x83, 0x66, 0x5e, 0xf9, 0x2d, 0x28, 0x07, 0x9a, - 0x8a, 0xde, 0x97, 0x44, 0xe7, 0xb1, 0xc4, 0x52, 0x4a, 0x9f, 0xa5, 0xd6, 0xdc, 0x80, 0xa2, 0x17, - 0x9c, 0x52, 0x67, 0x92, 0x32, 0xb4, 0xf2, 0x8b, 0x1c, 0x2c, 0x08, 0x08, 0x52, 0xa0, 0xb6, 0xb7, - 0x3f, 0xe8, 0x3d, 0xe9, 0x6d, 0x76, 0x06, 0xbd, 0xfd, 0x3d, 0x56, 0x4b, 0x11, 0xc7, 0x60, 0x34, - 0x10, 0x78, 0xd6, 0xdf, 0xea, 0x0c, 0xba, 0x8c, 0x71, 0x11, 0x8b, 0x2f, 0xba, 0x6a, 0xd9, 0xef, - 0x77, 0xf7, 0xc4, 0xcd, 0x0a, 0xf6, 0x1f, 0xbd, 0x05, 0x95, 0x2f, 0xbb, 0xdd, 0x7e, 0x67, 0xa7, - 0xf7, 0xbc, 0xcb, 0x4c, 0xb0, 0x88, 0x23, 0x00, 0x75, 0x69, 0xb8, 0xfb, 0x04, 0x77, 0x0f, 0x9e, - 0x32, 0x33, 0x2b, 0xe2, 0xe0, 0x93, 0x96, 0xdb, 0xea, 0x1d, 0x6c, 0x76, 0xf0, 0x56, 0x77, 0x8b, - 0x19, 0x58, 0x11, 0x47, 0x00, 0xda, 0xab, 0x83, 0xfd, 0x41, 0x67, 0x87, 0x99, 0x57, 0x11, 0xf3, - 0x0f, 0xe5, 0x01, 0x94, 0xb8, 0x95, 0x50, 0xbc, 0x61, 0x39, 0x53, 0x5f, 0x44, 0x2a, 0xfc, 0x83, - 0xca, 0x6d, 0x4f, 0x7d, 0x0a, 0x16, 0xcb, 0x03, 0xfe, 0xa5, 0x10, 0x28, 0xf1, 0x38, 0x15, 0xdd, - 0x85, 0x12, 0x0d, 0xbd, 0x8d, 0xb1, 0xe8, 0xdd, 0xb5, 0x64, 0x24, 0xbb, 0xc9, 0xb0, 0x58, 0x50, - 0xa1, 0xf7, 0xe2, 0x27, 0xab, 0xab, 0x49, 0xf2, 0xd8, 0xd9, 0xea, 0x2f, 0x72, 0x50, 0x93, 0xb9, - 0x50, 0x13, 0x1a, 0xda, 0x96, 0x45, 0x86, 0xbe, 0xea, 0x12, 0xdf, 0x3d, 0x0d, 0x3a, 0x5b, 0x00, - 0x31, 0x85, 0x51, 0x5b, 0x60, 0xc1, 0x52, 0x78, 0xcc, 0x5f, 0xc4, 0x65, 0x0a, 0xa0, 0x9c, 0xe8, - 0x04, 0xf7, 0x0d, 0x21, 0x8e, 0x66, 0x1a, 0xc7, 0x44, 0x4d, 0xdc, 0x6c, 0x59, 0x0a, 0x31, 0x3d, - 0x81, 0x40, 0x5b, 0x70, 0x65, 0x62, 0x58, 0xc6, 0x64, 0x3a, 0x51, 0x43, 0xbd, 0xa5, 0x71, 0x5f, - 0x54, 0x94, 0x8f, 0xd0, 0x5b, 0x82, 0xaa, 0x23, 0x13, 0x05, 0x5c, 0x94, 0x9f, 0xe7, 0xa1, 0x2a, - 0x35, 0xef, 0x7f, 0x69, 0x33, 0xd8, 0xe6, 0x0b, 0x19, 0xdb, 0xbe, 0xa1, 0x51, 0xe7, 0x14, 0x09, - 0xc7, 0x15, 0x11, 0x45, 0xb8, 0xa7, 0x81, 0x98, 0xd1, 0x45, 0x0c, 0xae, 0x90, 0x59, 0x17, 0x31, - 0xb8, 0x42, 0x86, 0xdf, 0xca, 0x7f, 0xe4, 0xa0, 0x12, 0xae, 0x6b, 0xd2, 0x51, 0x4b, 0x2e, 0x23, - 0x6a, 0xb9, 0x0c, 0xc0, 0x89, 0xa4, 0x43, 0x68, 0x1e, 0x55, 0xf5, 0x05, 0x8f, 0x89, 0x3f, 0x55, - 0x75, 0xc3, 0x1b, 0xda, 0xc7, 0xc4, 0x3d, 0x15, 0xfb, 0x13, 0xb5, 0x89, 0x3f, 0xdd, 0x0a, 0x60, - 0x34, 0x22, 0xa0, 0xb3, 0x2a, 0xed, 0xcf, 0x89, 0xad, 0x07, 0x07, 0xa2, 0x55, 0x01, 0xdb, 0xb5, - 0x75, 0xba, 0x22, 0x5f, 0x14, 0x91, 0x5c, 0x7c, 0xa6, 0xab, 0x73, 0x68, 0x27, 0xfb, 0xb2, 0x4a, - 0x29, 0xb8, 0x18, 0x12, 0x5c, 0x56, 0xa1, 0x13, 0xa1, 0x3f, 0x74, 0xd4, 0x89, 0xe7, 0x89, 0x88, - 0xb6, 0xe4, 0x0f, 0x9d, 0x5d, 0xcf, 0x53, 0x1e, 0x41, 0x55, 0x5a, 0x9b, 0xa1, 0xbb, 0xb0, 0x2c, - 0x2f, 0xe4, 0xe2, 0xb1, 0xc6, 0x92, 0xb4, 0x70, 0xe3, 0x81, 0x86, 0xf2, 0xef, 0x39, 0x68, 0x24, - 0x56, 0x67, 0x67, 0x87, 0x40, 0x62, 0x8d, 0x17, 0xa9, 0x58, 0x1d, 0x57, 0x05, 0x8c, 0x0d, 0xdf, - 0x55, 0xa8, 0x1e, 0x11, 0xd3, 0x21, 0xae, 0x6a, 0x5b, 0x66, 0xd0, 0x6d, 0xc0, 0x41, 0xfb, 0x96, - 0xc9, 0xa6, 0x34, 0x9d, 0x8c, 0x88, 0xeb, 0x6a, 0x26, 0x67, 0xc2, 0xaf, 0xc9, 0xd4, 0x02, 0x20, - 0xe3, 0x72, 0x0f, 0x56, 0xd8, 0xe5, 0x12, 0x71, 0x75, 0x4d, 0x0d, 0xe4, 0xe1, 0x9b, 0x27, 0xcb, - 0x32, 0xae, 0x2b, 0x64, 0x7b, 0x0f, 0x96, 0x4c, 0xdb, 0x1a, 0x9b, 0xec, 0xf2, 0x4a, 0x40, 0x5f, - 0xe2, 0xd3, 0x6f, 0x88, 0x10, 0xc4, 0xca, 0x47, 0xb0, 0xbe, 0xeb, 0x24, 0xda, 0x2d, 0xfc, 0xc5, - 0xcc, 0xd6, 0x2b, 0x7f, 0x9b, 0x83, 0xb5, 0x54, 0x29, 0x6e, 0x9d, 0xb3, 0xbb, 0x4c, 0x9e, 0x07, - 0xf9, 0x46, 0x75, 0x34, 0x73, 0xc4, 0xe7, 0x3a, 0xd1, 0x55, 0xd2, 0x5c, 0xf7, 0x3e, 0x2c, 0x8b, - 0xcb, 0x2f, 0xae, 0x71, 0xa8, 0x86, 0x6c, 0x8a, 0xc1, 0xbd, 0x68, 0x7d, 0x7f, 0xc4, 0x76, 0x54, - 0xc2, 0x89, 0xa8, 0x21, 0x91, 0xb3, 0x39, 0x89, 0xf7, 0x57, 0x2d, 0x20, 0x3d, 0xa0, 0x43, 0xfe, - 0x07, 0x39, 0x58, 0x4a, 0x35, 0x03, 0x7d, 0x37, 0xe1, 0x94, 0xaf, 0x4b, 0xf3, 0x58, 0x76, 0x4f, - 0x85, 0xfe, 0xf9, 0x41, 0xdc, 0x3f, 0x5f, 0x3b, 0xa3, 0x64, 0xcc, 0x55, 0x77, 0xa0, 0x2e, 0x56, - 0xf6, 0xa2, 0xeb, 0x67, 0xad, 0x7d, 0xa5, 0xde, 0xcd, 0xc7, 0x87, 0xe4, 0x0f, 0x73, 0x50, 0x13, - 0x3c, 0xc2, 0x6b, 0x5c, 0xaf, 0xc6, 0x82, 0x2a, 0xac, 0x6f, 0xfb, 0xd4, 0x11, 0x88, 0xcb, 0x7f, - 0xcc, 0xf4, 0x18, 0xa8, 0xcf, 0x36, 0x2b, 0x6f, 0xc0, 0xa2, 0x20, 0x90, 0x77, 0x20, 0xeb, 0xb8, - 0xce, 0x69, 0x82, 0xfd, 0xc7, 0x7f, 0xca, 0xc3, 0x86, 0xb0, 0x44, 0x93, 0x5f, 0x63, 0xdd, 0x67, - 0x91, 0x73, 0x30, 0x0f, 0xdd, 0x01, 0xa4, 0x99, 0x2f, 0xb5, 0x53, 0x8f, 0xc6, 0x7c, 0x8e, 0xe6, - 0x12, 0x75, 0x12, 0xdd, 0x71, 0xe7, 0x98, 0x4d, 0x8e, 0xd8, 0x25, 0x3a, 0xba, 0x07, 0xab, 0xc6, - 0xd8, 0xb2, 0x5d, 0x1a, 0x71, 0x32, 0xc9, 0x54, 0x93, 0x58, 0x63, 0xff, 0x28, 0x38, 0x8b, 0xe3, - 0xc8, 0x8e, 0x47, 0x45, 0xdc, 0x61, 0x18, 0xba, 0x66, 0x08, 0xf6, 0x89, 0xc3, 0x2a, 0x98, 0xc1, - 0xb3, 0x35, 0x03, 0xd7, 0xae, 0xf5, 0x80, 0x42, 0x54, 0xc5, 0x04, 0x76, 0x7b, 0x74, 0x95, 0x78, - 0x29, 0x54, 0x3c, 0xd5, 0xb0, 0xb4, 0xa1, 0x4f, 0xbd, 0x1a, 0x2b, 0x1e, 0xec, 0xb8, 0xae, 0x87, - 0x04, 0x3d, 0x81, 0x67, 0xa5, 0x99, 0xf3, 0xe2, 0x9d, 0xa9, 0x6a, 0xc6, 0xd8, 0x09, 0x36, 0x38, - 0xc5, 0xb5, 0x7d, 0x63, 0xec, 0xa0, 0xcf, 0xa1, 0x2d, 0x1a, 0x63, 0x91, 0x13, 0x5f, 0x65, 0xfb, - 0xcd, 0x63, 0x47, 0x9d, 0x10, 0xdf, 0x35, 0x86, 0xc2, 0x46, 0xd7, 0x38, 0xc5, 0x1e, 0x39, 0xf1, - 0x9f, 0xda, 0x4e, 0x6f, 0xec, 0xec, 0x32, 0xac, 0xf2, 0x8f, 0x79, 0x68, 0x67, 0x76, 0x2b, 0x1f, - 0xef, 0xff, 0xeb, 0xd5, 0xd7, 0xea, 0xd5, 0x3f, 0xc9, 0xc1, 0x6a, 0x66, 0xaf, 0xa2, 0x47, 0x09, - 0x3f, 0x70, 0x23, 0xb5, 0x07, 0x98, 0xa5, 0xdd, 0xa1, 0x2f, 0xf8, 0x3c, 0xee, 0x0b, 0xde, 0x3e, - 0xa7, 0x74, 0xcc, 0x1f, 0xdc, 0x87, 0xb5, 0x67, 0x1e, 0x61, 0x2b, 0x71, 0xc7, 0x64, 0x77, 0xf9, - 0xbd, 0x73, 0x7d, 0xf2, 0x3d, 0x58, 0x4d, 0x96, 0x39, 0xc7, 0x23, 0x2b, 0x3f, 0x05, 0xa0, 0x2b, - 0x7e, 0xc1, 0xfa, 0x36, 0x2c, 0xf1, 0xcd, 0x87, 0x89, 0xe0, 0x41, 0x97, 0x78, 0xbc, 0x44, 0x83, - 0x21, 0x02, 0xde, 0x1d, 0xb6, 0x1d, 0x32, 0xd1, 0x4e, 0x58, 0x48, 0x14, 0x1c, 0x72, 0xb0, 0xa9, - 0x4b, 0x00, 0x59, 0xed, 0xca, 0x4f, 0xa0, 0xd2, 0x0d, 0x97, 0x51, 0x6f, 0x9c, 0xbb, 0x0a, 0x45, - 0xca, 0x1d, 0xdd, 0x49, 0x0c, 0xd3, 0x4a, 0x7c, 0xbf, 0x3a, 0x31, 0x2a, 0xb3, 0xef, 0x26, 0x86, - 0xa2, 0x06, 0x83, 0x70, 0x0f, 0xa0, 0x17, 0xf5, 0x4e, 0x4a, 0xa6, 0x5c, 0x86, 0x4c, 0x1f, 0x42, - 0xa5, 0x17, 0xb6, 0xf8, 0x42, 0x25, 0x54, 0x28, 0xf6, 0xce, 0x69, 0x45, 0xef, 0x55, 0x5a, 0xd1, - 0x4b, 0xb6, 0xe2, 0x97, 0x39, 0x68, 0x26, 0xf5, 0x02, 0x7d, 0x96, 0xa8, 0x4d, 0x9a, 0xa8, 0xb2, - 0xf5, 0x2e, 0xac, 0xf9, 0x93, 0x78, 0xcd, 0x57, 0x67, 0x17, 0x94, 0xa5, 0x40, 0x0a, 0x14, 0xc9, - 0xe1, 0xd8, 0x49, 0xbf, 0xc7, 0xa1, 0xbd, 0x8e, 0x19, 0x8e, 0xd2, 0x18, 0x94, 0x26, 0xf5, 0xe6, - 0xa5, 0xc7, 0x68, 0x28, 0x4e, 0x79, 0x2c, 0x66, 0x96, 0x81, 0xe6, 0x8e, 0x89, 0xbf, 0x4b, 0x26, - 0x87, 0xc4, 0xf5, 0x8e, 0x0c, 0x69, 0x90, 0xe2, 0x11, 0x55, 0x2e, 0x1d, 0x51, 0x29, 0x1d, 0xe1, - 0x46, 0x93, 0x3c, 0xc2, 0x51, 0x3b, 0x9f, 0x45, 0xe8, 0x34, 0x92, 0x3c, 0xce, 0x75, 0x1a, 0xd9, - 0x82, 0x5f, 0xd4, 0x69, 0x64, 0x8a, 0x1c, 0x8c, 0xf4, 0x4f, 0xe1, 0xca, 0x8e, 0x6d, 0x8d, 0x77, - 0x68, 0x04, 0xf4, 0x8a, 0x01, 0xdd, 0x05, 0xc2, 0x59, 0xe5, 0x57, 0x39, 0xb8, 0x3c, 0x8b, 0xff, - 0x6f, 0x32, 0xf4, 0xbb, 0x0d, 0x4b, 0x6c, 0x03, 0x2b, 0x26, 0x1f, 0x8f, 0x3b, 0x1a, 0x14, 0x81, - 0xa5, 0x90, 0xfb, 0x21, 0xb4, 0x53, 0xb4, 0xae, 0x4a, 0x4e, 0x1c, 0xc3, 0x0d, 0x43, 0xe6, 0xf5, - 0x44, 0x21, 0xb7, 0xcb, 0xd1, 0xca, 0x9f, 0xe6, 0xa0, 0x35, 0xab, 0x81, 0xe8, 0x07, 0x89, 0x71, - 0x95, 0x5e, 0x26, 0x9c, 0xdd, 0xe9, 0xe1, 0xd0, 0x3e, 0x8a, 0x0f, 0xed, 0xcd, 0xf3, 0x19, 0xc4, - 0x46, 0xf7, 0x9f, 0x8b, 0xb0, 0x20, 0xe2, 0x3b, 0xf4, 0x25, 0x2c, 0x4f, 0x1c, 0x35, 0x75, 0xd8, - 0xc4, 0x25, 0xdb, 0x38, 0x23, 0xe8, 0xc4, 0x4b, 0x93, 0x54, 0xb8, 0xfb, 0x41, 0xd8, 0x32, 0x2e, - 0xd8, 0x7a, 0xea, 0xb4, 0x29, 0xd1, 0x90, 0xe4, 0x49, 0x64, 0xe1, 0xc2, 0x27, 0x91, 0x3f, 0x82, - 0xf5, 0x60, 0x49, 0x26, 0x26, 0x3f, 0xd5, 0x76, 0x82, 0x53, 0xe4, 0x84, 0x3b, 0xc9, 0x9c, 0x24, - 0xf1, 0xaa, 0x9b, 0x39, 0x55, 0x3f, 0x05, 0x34, 0xf5, 0x48, 0x34, 0xb5, 0x70, 0x7f, 0x3b, 0x9f, - 0x3c, 0x7f, 0x4a, 0xba, 0x28, 0xdc, 0x9c, 0x26, 0x3d, 0x63, 0xea, 0x8c, 0xa0, 0x94, 0x6c, 0xdd, - 0xec, 0x33, 0x82, 0xb0, 0x79, 0x3e, 0x33, 0x53, 0x75, 0x12, 0xda, 0xa9, 0x38, 0xa8, 0xbc, 0x7a, - 0x8e, 0x39, 0x8b, 0xe6, 0xa5, 0x9c, 0x8a, 0x06, 0x1b, 0x74, 0xdd, 0xa6, 0xf2, 0x15, 0x5d, 0x6a, - 0xdc, 0xf9, 0xc1, 0xa6, 0x72, 0xbe, 0x42, 0xe1, 0x96, 0x39, 0x03, 0xa3, 0x4c, 0xa1, 0xc4, 0x1b, - 0x86, 0x36, 0xa0, 0x62, 0x38, 0x6a, 0xec, 0x4a, 0x43, 0xd9, 0x70, 0x04, 0xf2, 0x1d, 0x68, 0x4c, - 0x34, 0xef, 0x1b, 0x11, 0x2c, 0xaa, 0x13, 0xc3, 0x12, 0xae, 0xa2, 0x4e, 0xc1, 0x3c, 0x50, 0xdc, - 0x35, 0xac, 0x14, 0x9d, 0x76, 0x22, 0x96, 0x13, 0x32, 0x9d, 0x76, 0xa2, 0xfc, 0x71, 0x0e, 0x20, - 0xba, 0x4f, 0xfa, 0x6b, 0x5e, 0xfa, 0xa5, 0x30, 0xd3, 0xf0, 0x7c, 0xf6, 0x6c, 0xa9, 0x82, 0xd9, - 0x7f, 0x76, 0x8f, 0x31, 0x5a, 0xad, 0x24, 0xef, 0x31, 0x32, 0x0c, 0x0e, 0x29, 0x94, 0x6d, 0x28, - 0xef, 0x6a, 0xfe, 0xf0, 0x88, 0x0a, 0x73, 0x33, 0x26, 0x8c, 0x34, 0xc7, 0x32, 0x8a, 0x73, 0xee, - 0x1f, 0x3f, 0x87, 0x5a, 0x2c, 0x78, 0xbe, 0x1b, 0x63, 0x26, 0xe9, 0xa4, 0x4c, 0x25, 0xf1, 0x5c, - 0x83, 0x92, 0x14, 0x90, 0xd7, 0xb1, 0xf8, 0x52, 0xfe, 0xad, 0x08, 0xb0, 0x69, 0x5b, 0xba, 0xc1, - 0x15, 0xff, 0x1e, 0x88, 0x17, 0x2f, 0x6a, 0x74, 0x89, 0x17, 0x25, 0x24, 0x3d, 0x20, 0x3e, 0xae, - 0x70, 0x2a, 0xda, 0xac, 0x4f, 0xa0, 0x16, 0x9e, 0x39, 0xd0, 0x42, 0xf9, 0x99, 0x85, 0xc2, 0xab, - 0x34, 0xb4, 0xd8, 0xf7, 0x60, 0x31, 0xb1, 0x52, 0x28, 0x24, 0xb7, 0x2c, 0xe5, 0xa6, 0xe0, 0x9a, - 0x26, 0x37, 0xff, 0x3e, 0x54, 0x83, 0xd2, 0xb4, 0xce, 0xe2, 0x6c, 0x41, 0x79, 0x31, 0x5a, 0xe3, - 0xa7, 0xe1, 0x53, 0x3e, 0xff, 0x94, 0x95, 0x9a, 0x9f, 0x59, 0xaa, 0x16, 0x12, 0xd2, 0x82, 0x5f, - 0xc0, 0x12, 0x5d, 0x06, 0xc4, 0x0b, 0x97, 0x66, 0x16, 0x6e, 0x90, 0x13, 0x7f, 0x53, 0x2e, 0x7f, - 0x15, 0xaa, 0xae, 0xf3, 0x8d, 0x41, 0xed, 0x6b, 0x6a, 0xfa, 0xcc, 0x76, 0xe7, 0x31, 0xb8, 0xfc, - 0xb9, 0xc1, 0xd4, 0xf4, 0xd1, 0x23, 0x80, 0xe8, 0x0d, 0x81, 0x38, 0x32, 0x95, 0x4e, 0x04, 0xa2, - 0xf1, 0x11, 0x66, 0x4e, 0x87, 0xb5, 0x12, 0x3e, 0x31, 0x40, 0x8f, 0x61, 0xd9, 0xa4, 0x26, 0x9e, - 0x90, 0xb0, 0x32, 0x53, 0xc2, 0x25, 0x46, 0x2e, 0xcb, 0xa8, 0x1c, 0x41, 0x25, 0xe4, 0x8d, 0x96, - 0xa1, 0x81, 0xf7, 0x9f, 0x0d, 0xba, 0xea, 0xe0, 0xeb, 0x7e, 0x57, 0x15, 0x87, 0x7c, 0xeb, 0xb0, - 0x2c, 0x01, 0x7b, 0x7b, 0x83, 0x2e, 0xde, 0xeb, 0xec, 0x34, 0x73, 0x09, 0x44, 0xf7, 0x85, 0x40, - 0xe4, 0xd1, 0x0a, 0x34, 0x25, 0xc4, 0xce, 0xfe, 0x66, 0x67, 0xa7, 0x59, 0x50, 0x46, 0xd0, 0x08, - 0x6b, 0xee, 0xf0, 0x47, 0xa9, 0xf7, 0x62, 0xca, 0x7c, 0x59, 0x6e, 0x79, 0x8c, 0x50, 0xd2, 0xe7, - 0x6b, 0x50, 0x0d, 0x5a, 0x6b, 0x84, 0xcf, 0x2e, 0x64, 0x90, 0xb2, 0x07, 0x95, 0x5d, 0xa2, 0x8b, - 0x1a, 0xde, 0x8b, 0xd5, 0xb0, 0x2e, 0x9f, 0x24, 0xe8, 0x29, 0xde, 0x2b, 0x30, 0x7f, 0xac, 0x99, - 0xd3, 0xe0, 0x55, 0x1a, 0xff, 0x50, 0x54, 0x68, 0x74, 0xbc, 0xbe, 0x4b, 0x1c, 0x62, 0x05, 0x5c, - 0x9b, 0x50, 0xd0, 0x3c, 0x4b, 0x44, 0x74, 0xf4, 0x2f, 0x35, 0x33, 0x4a, 0xa1, 0x85, 0x5b, 0xf4, - 0xfc, 0x0b, 0x29, 0x50, 0xa7, 0x13, 0x8a, 0x49, 0x46, 0xbe, 0x3a, 0xb1, 0x3d, 0x5f, 0xc4, 0x25, - 0xd5, 0xa9, 0x47, 0x76, 0xc8, 0xc8, 0xdf, 0xb5, 0xd9, 0x55, 0xc5, 0xba, 0xb8, 0x1a, 0x26, 0xd8, - 0x9f, 0xf9, 0xc2, 0xc7, 0x23, 0xe6, 0x48, 0xc4, 0x3e, 0xec, 0xbf, 0x72, 0x13, 0x1a, 0x3b, 0x6c, - 0x93, 0xd5, 0x25, 0x23, 0xc1, 0x20, 0x6c, 0x88, 0x38, 0x46, 0xe0, 0x0d, 0xf9, 0x87, 0x02, 0x2c, - 0x70, 0x02, 0x2f, 0xba, 0x9d, 0xa2, 0xf1, 0xc7, 0xc7, 0x29, 0x47, 0xc9, 0x94, 0x82, 0x53, 0x8b, - 0xdb, 0x29, 0x82, 0xf7, 0xa7, 0x50, 0x89, 0x4e, 0xd8, 0xf2, 0xc9, 0x6b, 0x29, 0x89, 0x81, 0xc3, - 0x11, 0x2d, 0xba, 0x01, 0x85, 0x89, 0x08, 0xcc, 0x62, 0x2b, 0x8d, 0x70, 0x24, 0x30, 0xc5, 0xa3, - 0xcf, 0x00, 0xa8, 0x85, 0xf3, 0xfe, 0x16, 0x06, 0x7e, 0x29, 0xe6, 0x1b, 0xe4, 0xa1, 0x60, 0x76, - 0xce, 0x01, 0xe8, 0x0b, 0xa8, 0xc7, 0xcc, 0x55, 0xd8, 0xf9, 0x19, 0xd2, 0xd5, 0x64, 0x8b, 0x45, - 0xf7, 0x60, 0x41, 0xdc, 0xdd, 0x13, 0x46, 0x2e, 0xa9, 0x4b, 0x6c, 0x80, 0x70, 0x40, 0x47, 0x85, - 0x15, 0x5b, 0xde, 0x2e, 0x19, 0x89, 0xc9, 0xf9, 0x92, 0x3c, 0x7f, 0xc6, 0xc6, 0x25, 0xd8, 0x0d, - 0x77, 0xc9, 0x08, 0x3d, 0x86, 0x46, 0xc2, 0x76, 0xc5, 0xf4, 0x7b, 0x86, 0xb8, 0x8b, 0x71, 0xf3, - 0x55, 0x7e, 0x96, 0x83, 0x4a, 0x78, 0xbf, 0x3a, 0x9c, 0x3d, 0x72, 0xd2, 0x44, 0xf6, 0x31, 0xc0, - 0x30, 0x74, 0x22, 0x62, 0xb4, 0x56, 0xb2, 0x1c, 0x0c, 0x96, 0xe8, 0xd0, 0x7b, 0xb0, 0xc0, 0xd5, - 0xc2, 0x13, 0xa3, 0x25, 0x5f, 0x1c, 0xe2, 0x08, 0x1c, 0x50, 0x28, 0x5f, 0x41, 0x49, 0x44, 0x65, - 0x59, 0x02, 0xc4, 0x5f, 0x68, 0xe4, 0x2f, 0xf6, 0x42, 0xe3, 0x5f, 0x72, 0xd0, 0x4c, 0x5e, 0xf1, - 0x41, 0xb7, 0x62, 0x96, 0xbc, 0x92, 0xbc, 0x0c, 0x24, 0x99, 0xb1, 0xfc, 0x78, 0x39, 0x7f, 0x81, - 0xc7, 0xcb, 0x19, 0x09, 0x25, 0x62, 0xaf, 0x16, 0x8a, 0xe7, 0xbd, 0x5a, 0x40, 0x1f, 0xc0, 0x82, - 0x4e, 0x46, 0x1a, 0x75, 0xf2, 0xf3, 0x67, 0x19, 0x52, 0x40, 0xa5, 0xfc, 0x51, 0x0e, 0x0a, 0xd8, - 0xd6, 0xd0, 0x22, 0xe4, 0xb5, 0x60, 0x3d, 0x9f, 0xd7, 0x3c, 0xf4, 0x16, 0x88, 0x09, 0xd6, 0x24, - 0x41, 0x40, 0x14, 0x01, 0xa8, 0x93, 0x99, 0x68, 0x0c, 0x25, 0x6e, 0x52, 0xf2, 0x2f, 0xe9, 0x9a, - 0x60, 0x31, 0x76, 0x73, 0x34, 0xb8, 0xb0, 0x37, 0x7f, 0xf6, 0x3b, 0x4b, 0xe5, 0x26, 0xbf, 0x2d, - 0x69, 0x6b, 0xe7, 0xbd, 0x9d, 0xe4, 0xcf, 0xc4, 0x18, 0x61, 0xf4, 0x4c, 0xcc, 0xb5, 0xb5, 0x8c, - 0x67, 0x62, 0x94, 0x88, 0xa1, 0x14, 0x0f, 0x0a, 0xcf, 0xdd, 0x51, 0xa6, 0x76, 0x2c, 0x42, 0xde, - 0xe5, 0x0b, 0xb9, 0x1a, 0xce, 0xbb, 0x3a, 0x0b, 0x19, 0xf9, 0xcd, 0x2f, 0x97, 0x07, 0x5f, 0x35, - 0x5c, 0xe6, 0x00, 0xcc, 0x1e, 0xcf, 0x8b, 0x7b, 0x65, 0xae, 0xcf, 0xc6, 0xa4, 0x86, 0xcb, 0x1c, - 0x80, 0x7d, 0x71, 0x45, 0x87, 0xdf, 0x69, 0xca, 0x1b, 0xba, 0xf2, 0xcb, 0x1c, 0x94, 0xf8, 0x95, - 0xec, 0x54, 0x1f, 0x6f, 0x40, 0x25, 0xda, 0x6d, 0x14, 0x0f, 0xed, 0xdd, 0x60, 0x7b, 0xf1, 0x2a, - 0x54, 0x69, 0xb4, 0x47, 0x2c, 0x7e, 0x6a, 0x54, 0xe0, 0x53, 0x36, 0x07, 0xb1, 0x53, 0xa3, 0x77, - 0xa1, 0x29, 0x08, 0x84, 0x4f, 0x16, 0x0a, 0x52, 0xc1, 0x0d, 0x0e, 0xef, 0x04, 0xe0, 0xd8, 0x2d, - 0xcc, 0xf9, 0xc4, 0x2d, 0xcc, 0x3b, 0x99, 0x0b, 0x0d, 0x71, 0xb6, 0x92, 0x5c, 0x4c, 0x28, 0x7f, - 0x97, 0x83, 0x0a, 0xbb, 0x6e, 0xda, 0xb3, 0x46, 0xf6, 0x6f, 0xe4, 0x32, 0xee, 0x4d, 0x68, 0x58, - 0xd3, 0x89, 0x2a, 0xdd, 0xb2, 0x15, 0x67, 0x91, 0x8b, 0xd6, 0x74, 0x22, 0xdf, 0x52, 0xbe, 0x04, - 0x65, 0x4b, 0x6c, 0x44, 0x05, 0x47, 0xdf, 0x16, 0xdf, 0x83, 0xa2, 0x6b, 0x7f, 0x8a, 0x0a, 0xef, - 0x21, 0xf0, 0xc3, 0xc6, 0xaa, 0x35, 0x9d, 0x74, 0x04, 0x48, 0xf9, 0x1e, 0xbb, 0x95, 0x8f, 0x8d, - 0x43, 0xda, 0x90, 0x40, 0xdb, 0x82, 0xfb, 0x9a, 0xa9, 0x47, 0x49, 0x61, 0x93, 0xf9, 0x7d, 0x4d, - 0xe5, 0x11, 0xcb, 0x73, 0x13, 0x96, 0x16, 0x2a, 0x78, 0xd1, 0xe2, 0xb7, 0x37, 0xa1, 0x1c, 0xf4, - 0x10, 0x02, 0x28, 0x6d, 0xef, 0xec, 0x3f, 0xee, 0xec, 0x34, 0xe7, 0x50, 0x05, 0xe6, 0x79, 0x8c, - 0xc2, 0xee, 0x2f, 0x74, 0xb6, 0x7e, 0xa8, 0xf6, 0xf6, 0x9a, 0x79, 0x54, 0x85, 0x05, 0xfa, 0x7f, - 0xff, 0xd9, 0xa0, 0x59, 0x40, 0x0b, 0x50, 0x78, 0x8e, 0x9f, 0x34, 0x8b, 0xb7, 0x7d, 0xa8, 0x4a, - 0x6b, 0x08, 0x76, 0xe1, 0x01, 0x77, 0x9f, 0xf4, 0x5e, 0x34, 0xe7, 0x50, 0x0d, 0xca, 0x7b, 0xdd, - 0xde, 0xf6, 0xd3, 0xc7, 0xfb, 0xb8, 0x99, 0xa3, 0x25, 0x06, 0x9d, 0x6d, 0xc1, 0xe7, 0x40, 0xed, - 0x77, 0x06, 0x4f, 0x9b, 0x05, 0x54, 0x87, 0xca, 0xe6, 0xfe, 0xee, 0xee, 0xb3, 0xbd, 0xde, 0xe0, - 0xeb, 0x66, 0x11, 0x2d, 0x41, 0xbd, 0xfb, 0x62, 0xa0, 0x46, 0xa0, 0x79, 0x1a, 0x83, 0xed, 0x74, - 0xf0, 0x76, 0x57, 0x02, 0x96, 0x6e, 0xbf, 0x0b, 0x95, 0x70, 0xb1, 0xc0, 0x6e, 0x5d, 0xed, 0x7d, - 0x2d, 0x5f, 0xbf, 0x02, 0x28, 0xf5, 0xf6, 0x9e, 0x77, 0xf1, 0xa0, 0x99, 0xbf, 0x7d, 0x1b, 0x9a, - 0xc9, 0xa5, 0x00, 0x2a, 0x41, 0xbe, 0xfb, 0x55, 0x73, 0x8e, 0xfe, 0x6e, 0x77, 0x9b, 0x39, 0xfa, - 0xbb, 0xd3, 0x6d, 0xe6, 0x6f, 0x7f, 0x20, 0x4e, 0x3a, 0xc5, 0xd4, 0x1e, 0x5d, 0xec, 0xa2, 0xfd, - 0xb0, 0xb9, 0xd9, 0xed, 0x0f, 0x38, 0x73, 0xdc, 0xfd, 0x61, 0x77, 0x93, 0x32, 0x7f, 0x06, 0xcb, - 0x19, 0xa1, 0x19, 0x6d, 0x46, 0x28, 0xad, 0xda, 0xd9, 0xda, 0x6a, 0xce, 0xd1, 0x18, 0x30, 0x02, - 0xe1, 0xee, 0xee, 0xfe, 0x73, 0x5a, 0xf1, 0x2a, 0x2c, 0xc9, 0x50, 0x71, 0x63, 0xec, 0xf6, 0xfb, - 0x50, 0x8f, 0xc5, 0x63, 0xb4, 0xcf, 0x76, 0xbb, 0x5b, 0xea, 0xee, 0x3e, 0x65, 0xd5, 0x80, 0x2a, - 0xfd, 0x08, 0xc8, 0x73, 0xb7, 0xef, 0x00, 0x44, 0x4e, 0x3f, 0xcc, 0x6c, 0x42, 0x3b, 0x61, 0xb7, - 0xbf, 0x8f, 0x85, 0xcc, 0xdd, 0x17, 0xec, 0x7f, 0xfe, 0xfe, 0xbf, 0x5e, 0x85, 0xf2, 0x36, 0xd5, - 0x89, 0x8e, 0x63, 0xa0, 0x1d, 0xa8, 0x4a, 0xef, 0x32, 0xd0, 0x5b, 0xb1, 0xa9, 0x28, 0xf1, 0xdc, - 0xa3, 0x7d, 0x79, 0x06, 0x56, 0x5c, 0xb7, 0x9e, 0x43, 0x3d, 0x80, 0xe8, 0xe5, 0x06, 0xda, 0x90, - 0xc9, 0x13, 0x8f, 0x3c, 0xda, 0x6f, 0x65, 0x23, 0x43, 0x56, 0x4f, 0xa0, 0x12, 0xbe, 0x57, 0x41, - 0xd2, 0xb2, 0x2e, 0xf9, 0xb0, 0xa5, 0xbd, 0x91, 0x89, 0x0b, 0xf9, 0xec, 0x40, 0x55, 0x4a, 0xb4, - 0x23, 0x37, 0x30, 0x9d, 0xb9, 0x47, 0x6e, 0x60, 0x56, 0x76, 0x9e, 0x39, 0xf4, 0x0c, 0x16, 0xe3, - 0x29, 0x76, 0xd0, 0x55, 0x79, 0x2d, 0x9d, 0x91, 0xb9, 0xa7, 0x7d, 0x6d, 0x36, 0x81, 0x2c, 0xa4, - 0x94, 0x54, 0x4a, 0x16, 0x32, 0x9d, 0xc7, 0x4a, 0x16, 0x32, 0x23, 0x13, 0x95, 0x32, 0x87, 0x30, - 0xd4, 0x63, 0xb9, 0x6b, 0xd0, 0x95, 0x98, 0x4b, 0x4c, 0x73, 0xbc, 0x3a, 0x13, 0x1f, 0xf2, 0xfc, - 0xff, 0xb0, 0x94, 0xca, 0x89, 0x83, 0x94, 0xf3, 0x73, 0xf3, 0xb4, 0xbf, 0x73, 0x26, 0x4d, 0xc8, - 0xff, 0xff, 0x41, 0x33, 0x99, 0xfb, 0x06, 0x49, 0xe7, 0xc3, 0x33, 0x52, 0xee, 0xb4, 0x95, 0xb3, - 0x48, 0xe4, 0x51, 0x8b, 0x67, 0xc2, 0x91, 0x47, 0x2d, 0x33, 0xad, 0x8e, 0x3c, 0x6a, 0x33, 0x92, - 0xe8, 0xcc, 0xa1, 0x17, 0xd0, 0x48, 0x24, 0xbb, 0x41, 0xf2, 0x60, 0x67, 0x66, 0xd8, 0x69, 0x5f, - 0x3f, 0x83, 0x22, 0xe4, 0xfc, 0x08, 0x4a, 0xdc, 0xb1, 0xa3, 0xf5, 0xd8, 0x60, 0x47, 0x4f, 0x29, - 0xda, 0xad, 0x34, 0x42, 0x56, 0x27, 0xe9, 0x39, 0x84, 0xac, 0x4e, 0xe9, 0x37, 0x19, 0xb2, 0x3a, - 0x65, 0xbd, 0xa1, 0x98, 0x43, 0x3f, 0x80, 0x05, 0x91, 0xce, 0x0b, 0xb5, 0x62, 0xf6, 0x21, 0xa5, - 0xed, 0x6a, 0x5f, 0xca, 0xc0, 0xc8, 0x6e, 0x21, 0x4a, 0x9e, 0x25, 0xbb, 0x85, 0x54, 0xfa, 0x2f, - 0xd9, 0x2d, 0x64, 0xe4, 0xdb, 0x9a, 0x43, 0x5b, 0x00, 0x51, 0xba, 0x17, 0x99, 0x55, 0x2a, 0x09, - 0x4c, 0x3b, 0xfb, 0xe5, 0x8c, 0x32, 0xf7, 0x61, 0x0e, 0x3d, 0x0c, 0xd3, 0xd9, 0x44, 0x97, 0x58, - 0xa5, 0x89, 0x32, 0xcc, 0xd1, 0xd6, 0x4e, 0x24, 0xda, 0x62, 0x85, 0x9f, 0x40, 0x25, 0xcc, 0x2f, - 0x24, 0x7b, 0xa6, 0x64, 0x76, 0x23, 0xd9, 0x33, 0xa5, 0x13, 0x12, 0xf1, 0x5e, 0x09, 0xb3, 0x0f, - 0xc5, 0x7a, 0x25, 0x99, 0xa8, 0x28, 0xd6, 0x2b, 0xe9, 0x84, 0x45, 0x73, 0xe8, 0x29, 0x54, 0xc2, - 0x8c, 0x41, 0xb2, 0x48, 0xc9, 0x3c, 0x46, 0xb2, 0x48, 0xe9, 0x14, 0x43, 0x73, 0xb7, 0x72, 0x54, - 0xf3, 0x78, 0xde, 0x1e, 0x59, 0xf3, 0x62, 0x29, 0x82, 0xda, 0xad, 0x34, 0x42, 0xf6, 0xda, 0x61, - 0x8a, 0x1e, 0x59, 0x90, 0x64, 0xe6, 0x9f, 0xf6, 0x46, 0x26, 0x4e, 0xd6, 0x39, 0x91, 0x94, 0x04, - 0x25, 0x14, 0x3d, 0xca, 0x66, 0x21, 0xeb, 0x5c, 0x22, 0x83, 0x49, 0xa8, 0xb5, 0x49, 0x0e, 0xf1, - 0x64, 0x25, 0x09, 0xad, 0x4d, 0x70, 0x08, 0xb5, 0x96, 0x31, 0x49, 0x09, 0x2c, 0xf3, 0x79, 0x2b, - 0x1b, 0x29, 0xb3, 0x8a, 0xf2, 0x85, 0xa0, 0x94, 0x5e, 0xcc, 0x60, 0x95, 0x91, 0x62, 0x84, 0xd9, - 0xb6, 0x94, 0x34, 0x04, 0xa5, 0x35, 0x43, 0x66, 0x76, 0x79, 0x06, 0x56, 0x1e, 0xaf, 0x30, 0xe5, - 0x87, 0x3c, 0x5e, 0xc9, 0xcc, 0x21, 0xf2, 0x78, 0xa5, 0x73, 0x84, 0xb0, 0x29, 0x27, 0x96, 0x3e, - 0x44, 0x9e, 0x72, 0xb2, 0x32, 0x91, 0xc8, 0x53, 0x4e, 0x76, 0xde, 0x91, 0xd0, 0x09, 0xda, 0x5a, - 0xd2, 0x09, 0x86, 0xeb, 0xb2, 0xa4, 0x13, 0x8c, 0xd6, 0x61, 0xbc, 0xa3, 0xa4, 0x54, 0x1f, 0x28, - 0xd5, 0xaf, 0x72, 0x3a, 0x13, 0xb9, 0xa3, 0xb2, 0xf2, 0x83, 0xcc, 0x09, 0xbb, 0xa0, 0xeb, 0xb6, - 0xb8, 0x5d, 0x44, 0x69, 0x3a, 0x12, 0x76, 0x21, 0xa7, 0xe2, 0x90, 0xec, 0x82, 0x72, 0x48, 0xd9, - 0x85, 0xc4, 0x64, 0x23, 0x13, 0x97, 0xe8, 0x93, 0x84, 0x18, 0xb1, 0xd4, 0x25, 0x89, 0x3e, 0x89, - 0x17, 0xc7, 0x6c, 0x61, 0x2b, 0x9d, 0x0b, 0x5c, 0x89, 0x11, 0xa7, 0x92, 0x58, 0xc8, 0xc3, 0x94, - 0x99, 0xf5, 0x83, 0xf3, 0x8c, 0x65, 0xe3, 0x90, 0x79, 0x66, 0xa5, 0xf9, 0x90, 0x79, 0x66, 0xa7, - 0xf1, 0x60, 0xd1, 0x40, 0x32, 0xe7, 0x86, 0x1c, 0x0d, 0xcc, 0x48, 0xf2, 0x21, 0x47, 0x03, 0x33, - 0x53, 0x76, 0xb0, 0x50, 0x26, 0x95, 0x70, 0x43, 0x0e, 0x65, 0x66, 0x65, 0xf4, 0x90, 0x43, 0x99, - 0xd9, 0x19, 0x3b, 0xe6, 0xd0, 0x3e, 0xd4, 0xe4, 0xe4, 0x1c, 0x28, 0x1e, 0xaf, 0x25, 0xf3, 0x50, - 0xb4, 0xaf, 0xcc, 0x42, 0xcb, 0x0c, 0xe5, 0xb4, 0x1a, 0x28, 0x1e, 0xa5, 0x9e, 0xc5, 0x30, 0x33, - 0x1b, 0x07, 0x0f, 0x5c, 0xe2, 0x09, 0x33, 0x50, 0x2a, 0x4a, 0x4d, 0xb1, 0xbd, 0x7e, 0x06, 0x85, - 0x3c, 0x70, 0xc9, 0x0c, 0x19, 0xf2, 0xc0, 0xcd, 0xc8, 0xc5, 0xd1, 0x56, 0xce, 0x22, 0x49, 0x2c, - 0x09, 0xc4, 0xe6, 0x5a, 0x7c, 0x49, 0x10, 0xcb, 0xf7, 0x90, 0x58, 0x12, 0x24, 0x92, 0x2b, 0x30, - 0x3e, 0x61, 0x3e, 0x01, 0x99, 0x4f, 0x32, 0xd1, 0x86, 0xcc, 0x27, 0x9d, 0x0a, 0x83, 0x8d, 0x8b, - 0x9c, 0x09, 0x40, 0x1e, 0x97, 0x8c, 0x1c, 0x19, 0xf2, 0xb8, 0x64, 0xa6, 0xaf, 0x10, 0x81, 0xbb, - 0xf4, 0xb4, 0x3f, 0x1e, 0xb8, 0xa7, 0x13, 0x5b, 0xc4, 0x03, 0xf7, 0xac, 0x4c, 0x12, 0x73, 0x48, - 0x67, 0x19, 0x64, 0x52, 0xbb, 0x87, 0x6f, 0x67, 0x74, 0x51, 0x2a, 0x4f, 0x41, 0xfb, 0xc6, 0x39, - 0x54, 0x72, 0x2d, 0x19, 0x29, 0x1a, 0xe4, 0x5a, 0x66, 0xe7, 0x86, 0x90, 0x6b, 0x39, 0x2b, 0xcf, - 0xc3, 0x1c, 0x9a, 0x04, 0x79, 0x64, 0x52, 0x15, 0xdd, 0xcc, 0xee, 0xdb, 0x74, 0x5d, 0xb7, 0xce, - 0x27, 0x0c, 0xab, 0x73, 0xc2, 0xe4, 0x31, 0xe9, 0xcd, 0xd7, 0x19, 0x1d, 0x9f, 0xae, 0xf0, 0xdd, - 0x0b, 0x50, 0xca, 0x71, 0x42, 0xb4, 0xa1, 0x83, 0x36, 0x92, 0x21, 0xbe, 0xb4, 0x49, 0xd4, 0x7e, - 0x2b, 0x1b, 0x19, 0xb0, 0x3a, 0x2c, 0xb1, 0xa4, 0xc8, 0x1f, 0xfd, 0x57, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x0c, 0xb2, 0x36, 0x62, 0x23, 0x59, 0x00, 0x00, + // 5779 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xd4, 0x3c, 0xcb, 0x72, 0x1b, 0x49, + 0x72, 0xc4, 0x83, 0x20, 0x90, 0x78, 0xb2, 0xf8, 0x82, 0xa0, 0x77, 0xef, 0x6a, 0x44, 0x69, 0x67, + 0x38, 0x23, 0xcd, 0xac, 0x66, 0xbd, 0xda, 0x99, 0x5d, 0x88, 0x84, 0x28, 0xec, 0xf0, 0x81, 0x29, + 0x42, 0x5a, 0x69, 0xfc, 0x68, 0x37, 0xd1, 0x05, 0xb0, 0x3d, 0x8d, 0xee, 0x9e, 0xee, 0x06, 0x45, + 0x86, 0x23, 0xec, 0x88, 0xf5, 0xd1, 0xe1, 0x3f, 0x70, 0x84, 0xef, 0x1b, 0xf6, 0xc1, 0x27, 0x47, + 0xf8, 0xec, 0x75, 0x38, 0x62, 0x23, 0xfc, 0x09, 0xf6, 0xc1, 0x1f, 0xe0, 0xab, 0x0f, 0x3e, 0x38, + 0xea, 0xd1, 0xdd, 0xd5, 0x0f, 0x50, 0x94, 0x56, 0x6b, 0x87, 0x4f, 0x44, 0x67, 0x66, 0x65, 0x65, + 0x55, 0x65, 0x66, 0x65, 0x65, 0x55, 0x12, 0xaa, 0x13, 0xfb, 0x78, 0xe2, 0x6c, 0x39, 0xae, 0xed, + 0xdb, 0xa8, 0xcc, 0x3e, 0x34, 0xc7, 0x50, 0xbe, 0x01, 0xb4, 0x4b, 0xfc, 0x03, 0x62, 0x4c, 0x4e, + 0x8e, 0x6d, 0x17, 0x93, 0xef, 0x66, 0xc4, 0xf3, 0xd1, 0x7d, 0x68, 0x11, 0x4b, 0x3b, 0x36, 0x49, + 0x57, 0x3f, 0x25, 0xae, 0x6f, 0x78, 0x44, 0x6f, 0xe7, 0x6e, 0xe5, 0x36, 0xcb, 0x38, 0x05, 0x47, + 0x6d, 0x58, 0xd2, 0x74, 0xdd, 0x25, 0x9e, 0xd7, 0xce, 0xdf, 0xca, 0x6d, 0x56, 0x70, 0xf0, 0xa9, + 0x3c, 0x86, 0x95, 0x18, 0x6f, 0xcf, 0xb1, 0x2d, 0x8f, 0xa0, 0xef, 0xc3, 0xa2, 0x43, 0x88, 0xeb, + 0xb5, 0x73, 0xb7, 0x0a, 0x9b, 0xd5, 0x87, 0x8d, 0xad, 0x40, 0x98, 0xad, 0x01, 0x21, 0x2e, 0xe6, + 0x48, 0x65, 0x02, 0x95, 0xae, 0x3b, 0x99, 0x4d, 0x89, 0xe5, 0x7b, 0x68, 0x0b, 0xca, 0x2e, 0xf1, + 0xec, 0x99, 0x3b, 0x22, 0x4c, 0x8e, 0xc6, 0x43, 0x14, 0xb5, 0xc2, 0x02, 0x83, 0x43, 0x1a, 0xb4, + 0x0e, 0xa5, 0xb1, 0x36, 0x35, 0xcc, 0x73, 0x26, 0x52, 0x1d, 0x8b, 0x2f, 0x84, 0xa0, 0x68, 0x69, + 0x53, 0xd2, 0x2e, 0x30, 0x41, 0xd9, 0x6f, 0xe5, 0x4f, 0xa1, 0xd1, 0xd5, 0xf5, 0x81, 0xe6, 0x9f, + 0x04, 0xa3, 0x7f, 0xdb, 0xde, 0xd6, 0xa0, 0x74, 0xea, 0x8e, 0x55, 0x43, 0x17, 0x13, 0xb0, 0x78, + 0xea, 0x8e, 0xfb, 0x3a, 0x52, 0xa0, 0xe8, 0x68, 0xfe, 0x09, 0xeb, 0x2c, 0x3e, 0x4c, 0xda, 0x17, + 0xc3, 0x29, 0x77, 0xa0, 0x19, 0x76, 0x2e, 0xa6, 0x07, 0x41, 0x71, 0x36, 0x33, 0xf8, 0x7c, 0xd7, + 0x30, 0xfb, 0xad, 0xfc, 0x2a, 0x07, 0xcb, 0x3b, 0xc4, 0x24, 0x3e, 0xf9, 0x1d, 0xc8, 0x19, 0x4d, + 0x56, 0x21, 0x36, 0x59, 0x81, 0xfc, 0xc5, 0xf9, 0xf2, 0x87, 0xc2, 0x2e, 0x4a, 0xc2, 0xae, 0x02, + 0x92, 0x65, 0xe5, 0xc3, 0x52, 0x7e, 0x04, 0xa8, 0xab, 0xeb, 0x49, 0x45, 0xa3, 0x7d, 0x10, 0xe2, + 0x32, 0xf1, 0xd3, 0xaa, 0xc0, 0x70, 0xca, 0x1a, 0xac, 0xc4, 0x5a, 0x0a, 0x86, 0x8f, 0x61, 0x8d, + 0x77, 0xf3, 0x2e, 0x3c, 0xdb, 0xb0, 0x9e, 0x6c, 0x2c, 0xd8, 0xbe, 0x80, 0x55, 0x4c, 0xbc, 0xb4, + 0x49, 0x48, 0x6a, 0x9e, 0x8b, 0xa9, 0x39, 0xfa, 0x3e, 0xd4, 0x47, 0xf6, 0x74, 0x3a, 0xb3, 0x8c, + 0x91, 0xe6, 0x1b, 0xb6, 0x25, 0x66, 0x37, 0x0e, 0x54, 0x36, 0x60, 0x2d, 0xc1, 0x57, 0x74, 0xf8, + 0x8f, 0x39, 0x68, 0x1f, 0xd9, 0x63, 0xff, 0x2d, 0x7b, 0x3d, 0x82, 0x8a, 0x6e, 0xb8, 0x64, 0x14, + 0xf6, 0xd8, 0x78, 0xf8, 0xc3, 0x68, 0xa8, 0xf3, 0x18, 0x46, 0x88, 0x9d, 0xa0, 0x31, 0x8e, 0xf8, + 0x28, 0x1f, 0x03, 0x4a, 0x13, 0xa0, 0x12, 0xe4, 0xfb, 0x07, 0xad, 0x05, 0xb4, 0x04, 0x85, 0xc3, + 0xe7, 0xc3, 0x56, 0x0e, 0x95, 0xa1, 0xf8, 0xe4, 0x70, 0xf8, 0xac, 0x95, 0x57, 0xae, 0xc2, 0x95, + 0x8c, 0xae, 0xc4, 0xc8, 0x5e, 0xc1, 0xc6, 0xd1, 0xc9, 0xcc, 0xd7, 0xed, 0xd7, 0xd6, 0xfb, 0x9e, + 0xcd, 0x0e, 0xb4, 0xd3, 0xac, 0x45, 0xb7, 0x0f, 0x60, 0xad, 0xc7, 0x9c, 0xd4, 0xa5, 0x3b, 0xa5, + 0xea, 0x90, 0x6c, 0x22, 0x98, 0xbd, 0x84, 0xf5, 0x1d, 0xc3, 0x7b, 0x2b, 0x6e, 0x97, 0x1c, 0xc2, + 0x15, 0xd8, 0x48, 0x71, 0x16, 0x9d, 0x4e, 0xa0, 0xc5, 0xc5, 0xd9, 0x77, 0xfd, 0xa0, 0xbb, 0xab, + 0x50, 0xd1, 0x67, 0x53, 0x47, 0xf5, 0xcf, 0x1d, 0x6e, 0xed, 0x8b, 0xb8, 0x4c, 0x01, 0xc3, 0x73, + 0x87, 0xa0, 0x0e, 0x94, 0xc7, 0x86, 0x49, 0x98, 0x6f, 0xe3, 0x9d, 0x85, 0xdf, 0x14, 0x67, 0x58, + 0x3e, 0x71, 0x4f, 0x35, 0x93, 0x19, 0x78, 0x11, 0x87, 0xdf, 0xca, 0x0a, 0x2c, 0x4b, 0x1d, 0x89, + 0xde, 0x57, 0x60, 0x59, 0x08, 0x16, 0x75, 0xcf, 0x8c, 0x5a, 0x02, 0x0a, 0xd2, 0x3f, 0x87, 0x56, + 0xdf, 0xfa, 0x13, 0x32, 0xf2, 0x25, 0x41, 0xdf, 0x93, 0x57, 0xa2, 0xbb, 0x84, 0xe6, 0x9f, 0x78, + 0xed, 0x42, 0x6a, 0x97, 0xa0, 0x6e, 0x85, 0x23, 0xa9, 0xac, 0x92, 0x00, 0x42, 0xaa, 0xbf, 0xcd, + 0x41, 0xbd, 0xab, 0xeb, 0x4f, 0xa6, 0xce, 0x9b, 0xd7, 0x0a, 0x41, 0xd1, 0xb1, 0x5d, 0x5f, 0xec, + 0x13, 0xec, 0x37, 0xfa, 0x09, 0x14, 0xd9, 0x2c, 0x17, 0x98, 0xf4, 0x9b, 0x51, 0xcf, 0x31, 0xa6, + 0x5b, 0xfb, 0xb6, 0x65, 0xf8, 0xb6, 0x6b, 0x58, 0x93, 0x81, 0x6d, 0x1a, 0xa3, 0x73, 0xcc, 0x5a, + 0x29, 0x1f, 0x43, 0x2b, 0x89, 0xa1, 0x96, 0x33, 0xc0, 0xbd, 0xd6, 0x02, 0xb5, 0x9c, 0xc1, 0xe1, + 0x51, 0xdc, 0x86, 0x5a, 0x6c, 0x03, 0x62, 0x8c, 0xc5, 0x00, 0x7e, 0x06, 0x2d, 0xee, 0x9d, 0xde, + 0x75, 0x08, 0x6c, 0x0d, 0x23, 0x0e, 0x82, 0xed, 0x10, 0x96, 0x85, 0x64, 0xd8, 0x38, 0x0e, 0xf8, + 0xde, 0x81, 0x45, 0x9f, 0x2e, 0xab, 0x70, 0x97, 0xcd, 0x68, 0xb4, 0x43, 0x0a, 0xc6, 0x1c, 0x4b, + 0xbb, 0x1f, 0xcd, 0x5c, 0x97, 0x58, 0xbc, 0x9f, 0x32, 0x0e, 0x3e, 0x95, 0x1e, 0x94, 0xf1, 0xe0, + 0xab, 0xfe, 0xb6, 0x6d, 0x8d, 0x2f, 0x10, 0xf2, 0x26, 0x54, 0x5d, 0x32, 0xb5, 0x7d, 0xa2, 0x86, + 0xb2, 0x56, 0x30, 0x70, 0xd0, 0x80, 0x4a, 0xfc, 0xd7, 0x45, 0xa8, 0x50, 0x3e, 0x47, 0xbe, 0xe6, + 0xb3, 0x0d, 0x7c, 0xe6, 0xf8, 0xc6, 0x94, 0x8b, 0x55, 0xc0, 0xe2, 0x8b, 0x2a, 0x33, 0xb5, 0x79, + 0x86, 0xc9, 0x33, 0x4c, 0xf8, 0x8d, 0x1a, 0x90, 0x9f, 0x39, 0x6c, 0xd1, 0xca, 0x38, 0x3f, 0x73, + 0x78, 0x97, 0x23, 0xdb, 0xd5, 0x55, 0xc3, 0x39, 0xfd, 0x8c, 0x6d, 0x63, 0x75, 0xda, 0x25, 0x05, + 0xf5, 0x9d, 0xd3, 0xcf, 0xe2, 0x04, 0x8f, 0xd8, 0x1e, 0x26, 0x13, 0x3c, 0xa2, 0x04, 0x8e, 0x4b, + 0xc6, 0xc6, 0x19, 0xe7, 0x50, 0xe2, 0x04, 0x1c, 0x14, 0x70, 0x88, 0x08, 0x1e, 0xb5, 0x97, 0x12, + 0x04, 0x8f, 0xe8, 0x38, 0x3c, 0xe2, 0x1a, 0x9a, 0xd9, 0x2e, 0xf3, 0xbd, 0x95, 0x7f, 0xa1, 0xef, + 0x41, 0xdd, 0x25, 0x23, 0x62, 0x9c, 0x12, 0x21, 0x5d, 0x85, 0x0d, 0xa6, 0x16, 0x00, 0x19, 0xf7, + 0x04, 0xd1, 0xa3, 0x36, 0xa4, 0x88, 0x1e, 0x51, 0x22, 0xce, 0x53, 0xb5, 0x6c, 0xdf, 0x18, 0x9f, + 0xb7, 0xab, 0x9c, 0x88, 0x03, 0x0f, 0x18, 0x8c, 0xca, 0x39, 0xd2, 0x46, 0x27, 0x44, 0x75, 0xa9, + 0xa3, 0x6e, 0xd7, 0x18, 0x09, 0x30, 0x10, 0x73, 0xdd, 0xe8, 0x0e, 0x34, 0x42, 0x02, 0xa6, 0x2c, + 0xed, 0x3a, 0xa3, 0xa9, 0x07, 0x34, 0x3c, 0x36, 0xb9, 0x01, 0x55, 0x62, 0xe9, 0xaa, 0x3d, 0x56, + 0x75, 0xcd, 0xd7, 0xda, 0x0d, 0x46, 0x53, 0x21, 0x96, 0x7e, 0x38, 0xde, 0xd1, 0x7c, 0x0d, 0xad, + 0xc2, 0x22, 0x71, 0x5d, 0xdb, 0x6d, 0x37, 0x19, 0x86, 0x7f, 0xa0, 0xdb, 0x20, 0xa4, 0x51, 0xbf, + 0x9b, 0x11, 0xf7, 0xbc, 0xdd, 0x62, 0xc8, 0x2a, 0x87, 0x7d, 0x4d, 0x41, 0x7c, 0x29, 0x3c, 0xe2, + 0x0b, 0x8a, 0x65, 0x2e, 0x20, 0x03, 0x31, 0x02, 0xe5, 0x15, 0x14, 0xb1, 0xf3, 0xad, 0x81, 0x3e, + 0x80, 0xe2, 0xc8, 0xb6, 0xc6, 0x42, 0x5b, 0x65, 0xcf, 0x22, 0x74, 0x10, 0x33, 0x3c, 0xba, 0x07, + 0x8b, 0x1e, 0xd5, 0x24, 0xa6, 0x25, 0xd5, 0x87, 0x2b, 0x71, 0x42, 0xa6, 0x64, 0x98, 0x53, 0x28, + 0x9b, 0xd0, 0xd8, 0x25, 0x3e, 0xe5, 0x1e, 0xd8, 0x44, 0x14, 0x11, 0xe5, 0xe4, 0x88, 0x48, 0x79, + 0x0c, 0xcd, 0x90, 0x52, 0xcc, 0xc8, 0x26, 0x2c, 0x79, 0xc4, 0x3d, 0xcd, 0x0c, 0x67, 0x19, 0x61, + 0x80, 0x56, 0xbe, 0x61, 0x66, 0x2e, 0x77, 0xf3, 0x76, 0x5e, 0xa9, 0x03, 0x65, 0xd3, 0x18, 0x13, + 0xa6, 0xfa, 0x05, 0xae, 0xfa, 0xc1, 0xb7, 0xb2, 0xcc, 0xc2, 0x48, 0x59, 0x30, 0xa5, 0x1b, 0x78, + 0x80, 0x77, 0xee, 0x31, 0x0a, 0xe4, 0x62, 0x8c, 0x3f, 0x0a, 0xf6, 0x8c, 0x4b, 0x31, 0xa6, 0x4c, + 0x64, 0x72, 0xc1, 0x64, 0x2b, 0xdc, 0x4e, 0x2e, 0xc7, 0x65, 0x0d, 0x56, 0x62, 0xf4, 0x82, 0xcd, + 0x87, 0xd0, 0x62, 0xfa, 0x7b, 0x39, 0x26, 0x2b, 0xb0, 0x2c, 0x51, 0x0b, 0x16, 0x9f, 0xc0, 0x6a, + 0x18, 0xc1, 0x5c, 0x8e, 0xcd, 0x06, 0xac, 0x25, 0x5a, 0x08, 0x56, 0xbf, 0xc9, 0x05, 0x63, 0xfd, + 0x86, 0x1c, 0xbb, 0x5a, 0xc0, 0xa9, 0x05, 0x85, 0x99, 0x6b, 0x0a, 0x2e, 0xf4, 0x27, 0xd3, 0x76, + 0x7b, 0xe6, 0x13, 0xb6, 0x99, 0xd3, 0x63, 0x53, 0x81, 0x39, 0x43, 0x0a, 0xa2, 0xdb, 0xb9, 0x47, + 0x3b, 0xa7, 0x3a, 0x43, 0x63, 0x07, 0x1e, 0x93, 0x07, 0x9f, 0xe8, 0x33, 0x58, 0xb7, 0xc8, 0x99, + 0x7f, 0x62, 0x3b, 0xaa, 0xef, 0x1a, 0x93, 0x09, 0x71, 0x55, 0x7e, 0x22, 0x63, 0xfe, 0xad, 0x8c, + 0x57, 0x05, 0x76, 0xc8, 0x91, 0x5c, 0x1c, 0xf4, 0x10, 0xd6, 0x92, 0xad, 0x74, 0x62, 0x6a, 0xe7, + 0xc2, 0xe7, 0xad, 0xc4, 0x1b, 0xed, 0x50, 0x14, 0x9d, 0xf2, 0xd8, 0x60, 0xc4, 0x20, 0x9b, 0x50, + 0xdf, 0x25, 0xfe, 0x0b, 0x77, 0x1c, 0x44, 0x06, 0x9f, 0x32, 0xf3, 0x61, 0x00, 0x61, 0x13, 0xb7, + 0xa1, 0x78, 0xea, 0x8e, 0x03, 0x83, 0xa8, 0x47, 0x06, 0x41, 0x89, 0x18, 0x4a, 0xf9, 0x84, 0xed, + 0xd0, 0x11, 0x17, 0x74, 0x13, 0x0a, 0xa7, 0x6e, 0x60, 0xd6, 0x89, 0x26, 0x14, 0x23, 0x76, 0x49, + 0xa9, 0x1b, 0xe5, 0xd3, 0x60, 0x97, 0x7c, 0x1b, 0x36, 0xe1, 0xc6, 0x28, 0x73, 0x7a, 0x0e, 0xab, + 0xbb, 0xc4, 0xdf, 0x21, 0x63, 0xc3, 0x22, 0xfa, 0x11, 0x09, 0x43, 0x99, 0x7b, 0x22, 0x10, 0xe0, + 0x61, 0xcc, 0x5a, 0xc4, 0x4e, 0x90, 0xd2, 0xc5, 0xe2, 0xbb, 0x7e, 0x78, 0xb2, 0xcc, 0x4b, 0x27, + 0xcb, 0x2e, 0xac, 0x25, 0xd8, 0x86, 0x4e, 0xa3, 0xe8, 0x11, 0x3f, 0x98, 0xa0, 0xd5, 0x14, 0x5f, + 0x4a, 0xcb, 0x28, 0x94, 0x2f, 0x61, 0xb5, 0xab, 0xeb, 0x69, 0xc9, 0x3e, 0x80, 0x02, 0x75, 0xe4, + 0x7c, 0x9c, 0xd9, 0x0c, 0x28, 0x01, 0xd5, 0xd5, 0x44, 0x7b, 0x31, 0xe4, 0x23, 0xd8, 0xe0, 0xf3, + 0xf0, 0xce, 0xbc, 0xa9, 0x5e, 0x6b, 0xa6, 0x29, 0xc2, 0x01, 0xfa, 0x93, 0x46, 0xe5, 0x69, 0xa6, + 0xa2, 0xc3, 0x27, 0xd0, 0xc6, 0xc4, 0x31, 0xb5, 0xd1, 0xbb, 0xf7, 0x48, 0x4f, 0x1b, 0x19, 0x3c, + 0x44, 0x07, 0x6b, 0x2c, 0xdb, 0xc0, 0x3c, 0xfb, 0x94, 0x58, 0x61, 0xe0, 0xfa, 0x15, 0x5b, 0x5b, + 0x09, 0x2c, 0xd6, 0xe0, 0x53, 0x00, 0x2f, 0x00, 0x06, 0x2b, 0x21, 0xed, 0x12, 0x51, 0x03, 0x89, + 0x4c, 0x79, 0xc6, 0x8e, 0xa2, 0xc9, 0x3e, 0xd0, 0x03, 0xa8, 0x84, 0x44, 0x62, 0x14, 0x99, 0xac, + 0x22, 0x2a, 0x65, 0x9d, 0x2d, 0x6c, 0x4a, 0x2c, 0xe5, 0x0f, 0x83, 0x83, 0xe9, 0x7b, 0xe8, 0x24, + 0x63, 0x85, 0xae, 0x04, 0xcb, 0x9e, 0xee, 0x79, 0x0f, 0x36, 0xc4, 0xe4, 0xbe, 0x8f, 0xf1, 0x75, + 0xc2, 0xe5, 0x4e, 0xf7, 0x84, 0xa0, 0xb5, 0x4b, 0x7c, 0x11, 0x34, 0x8b, 0x65, 0xea, 0xc2, 0xb2, + 0x04, 0x13, 0x6b, 0xf4, 0x21, 0x94, 0x1d, 0x0a, 0x31, 0x48, 0xb0, 0x42, 0x2d, 0xe9, 0x18, 0xc0, + 0x69, 0x43, 0x0a, 0xe5, 0x0c, 0x5a, 0x5d, 0x5d, 0x8f, 0xb1, 0x45, 0x9b, 0x50, 0x62, 0xf8, 0x73, + 0x21, 0x76, 0xba, 0xbd, 0xc0, 0xa3, 0x1f, 0xc3, 0x15, 0x97, 0x8c, 0xa9, 0x3b, 0x3d, 0x33, 0x3c, + 0xdf, 0xb0, 0x26, 0xaa, 0xa4, 0x1e, 0x7c, 0x06, 0x37, 0x18, 0x41, 0x4f, 0xe0, 0x8f, 0x22, 0xb5, + 0x58, 0x81, 0x65, 0xa9, 0x67, 0x31, 0xca, 0x5f, 0xe6, 0x60, 0x45, 0xe4, 0x41, 0xde, 0x51, 0xa4, + 0x8f, 0x61, 0xc5, 0xa1, 0x21, 0x90, 0x7b, 0x4a, 0xd2, 0xc2, 0xa0, 0x00, 0x15, 0xc9, 0x11, 0xac, + 0x77, 0x21, 0x5a, 0xef, 0x75, 0x58, 0x8d, 0xcb, 0x20, 0x84, 0xfb, 0xbb, 0x1c, 0xac, 0x8a, 0xf5, + 0xf9, 0x3f, 0x98, 0xb0, 0x79, 0x23, 0x2b, 0xcc, 0x1b, 0x19, 0xcf, 0x9e, 0xc4, 0xc4, 0x0d, 0xcf, + 0xe7, 0x9d, 0x50, 0x6f, 0xba, 0x9e, 0x67, 0x4c, 0x2c, 0x59, 0x71, 0x7f, 0x0c, 0xa0, 0x85, 0x40, + 0x31, 0xa2, 0x4e, 0x72, 0x44, 0x52, 0x33, 0x89, 0x5a, 0x79, 0x05, 0x57, 0x33, 0x39, 0x0b, 0xdd, + 0xfc, 0x6d, 0x58, 0xbf, 0x84, 0x4e, 0xa8, 0x2f, 0xef, 0x57, 0xe8, 0xeb, 0x70, 0x35, 0x93, 0xb3, + 0x98, 0xad, 0x29, 0x5c, 0x97, 0xd5, 0xe1, 0xbd, 0xf6, 0x9d, 0xe1, 0x6d, 0x6e, 0xc1, 0x8d, 0x79, + 0xdd, 0x09, 0x81, 0xfe, 0x00, 0x6e, 0xc4, 0xd6, 0xf5, 0xfd, 0xce, 0xc6, 0x6d, 0xb8, 0x39, 0x97, + 0x7b, 0xcc, 0x17, 0x1d, 0xb1, 0x18, 0x3d, 0xf0, 0x45, 0x5f, 0x30, 0x5f, 0x14, 0xc0, 0xc2, 0x3d, + 0xbb, 0x34, 0x31, 0xed, 0x63, 0xcd, 0x4c, 0x1b, 0xc6, 0x2e, 0x83, 0x63, 0x81, 0x57, 0xbe, 0x04, + 0x74, 0xe4, 0x6b, 0x6e, 0x9c, 0xe9, 0x5b, 0xb4, 0x5f, 0x83, 0x95, 0x58, 0xfb, 0x28, 0x2d, 0x73, + 0xe4, 0xdb, 0x4e, 0x5c, 0xd4, 0x55, 0xda, 0x57, 0x04, 0x14, 0xa4, 0xff, 0x56, 0x80, 0xe2, 0x40, + 0xa4, 0x67, 0x2d, 0xd3, 0x35, 0x82, 0x5c, 0x32, 0xfd, 0x4d, 0x0f, 0x37, 0x8e, 0xe6, 0xfb, 0x2e, + 0x8f, 0x3b, 0x6b, 0x58, 0x7c, 0xb1, 0xe5, 0x9b, 0x04, 0x47, 0x0b, 0xfa, 0x93, 0xb6, 0x3e, 0x26, + 0x9e, 0x2f, 0x22, 0x4b, 0xf6, 0x9b, 0x86, 0xae, 0x86, 0xa7, 0xbe, 0x36, 0xfc, 0x13, 0xdd, 0xd5, + 0x5e, 0xb3, 0xf8, 0xb1, 0x8c, 0xc1, 0xf0, 0x7e, 0x21, 0x20, 0xe8, 0x06, 0xc0, 0xa9, 0x66, 0x1a, + 0x3a, 0xcf, 0x7c, 0x95, 0x58, 0xa2, 0x4a, 0x82, 0xa0, 0x4f, 0x60, 0xd5, 0xb2, 0x55, 0x63, 0xea, + 0x50, 0xaf, 0xed, 0x47, 0x9c, 0x96, 0xb8, 0xed, 0x5b, 0x76, 0x5f, 0xa0, 0x42, 0x8e, 0xd1, 0x69, + 0xac, 0x1c, 0xcb, 0x4f, 0x5f, 0x07, 0xe0, 0x29, 0x24, 0x55, 0xf3, 0x2c, 0x76, 0x80, 0xae, 0xe3, + 0x0a, 0x87, 0x74, 0x3d, 0x0b, 0x5d, 0x05, 0xf1, 0xa1, 0x1a, 0x3a, 0x3b, 0x39, 0x57, 0x70, 0x99, + 0x03, 0xfa, 0xba, 0x48, 0x98, 0xf9, 0xc4, 0x25, 0x3a, 0x3b, 0x30, 0x97, 0x71, 0xf8, 0x4d, 0x0f, + 0xb1, 0x9e, 0xaf, 0x99, 0x84, 0x1d, 0x93, 0xcb, 0x98, 0x7f, 0xa0, 0x4d, 0x68, 0x19, 0x9e, 0x3a, + 0x76, 0xed, 0xa9, 0x4a, 0xce, 0x7c, 0xe2, 0x5a, 0x9a, 0xc9, 0xce, 0xc8, 0x65, 0xdc, 0x30, 0xbc, + 0xa7, 0xae, 0x3d, 0xed, 0x09, 0x28, 0x9d, 0x22, 0x4b, 0x64, 0xf4, 0x54, 0xc3, 0x61, 0x87, 0xe4, + 0x0a, 0x86, 0x00, 0xd4, 0x77, 0xc2, 0xa4, 0x79, 0x33, 0x4a, 0x9a, 0xa3, 0x0f, 0x01, 0x19, 0x9e, + 0x1a, 0x04, 0xe9, 0x86, 0xc5, 0x66, 0x8c, 0x9d, 0x94, 0xcb, 0xb8, 0x65, 0x78, 0x07, 0x1c, 0xd1, + 0xe7, 0x70, 0xe5, 0x6f, 0x72, 0x50, 0xdd, 0x21, 0xd4, 0xab, 0xf2, 0x49, 0xa5, 0x6b, 0xca, 0x92, + 0x0e, 0xe2, 0x94, 0x21, 0xbe, 0xa2, 0x24, 0x5a, 0xfe, 0x82, 0x24, 0x1a, 0xba, 0x0b, 0x4d, 0xd3, + 0xb6, 0xe8, 0xa1, 0x80, 0x37, 0x23, 0x81, 0x27, 0x6e, 0x70, 0xf0, 0x40, 0x40, 0xd1, 0x3d, 0x68, + 0x79, 0x27, 0xb6, 0xeb, 0xcb, 0x94, 0x5c, 0x39, 0x9a, 0x02, 0x1e, 0x90, 0x2a, 0xff, 0x90, 0x83, + 0x45, 0x96, 0x40, 0xa2, 0x27, 0x76, 0x29, 0x88, 0xce, 0xca, 0x05, 0xce, 0x8d, 0xa0, 0xe7, 0x5e, + 0x4d, 0xfc, 0x1e, 0xd4, 0xf4, 0x68, 0xf8, 0x54, 0x08, 0x3a, 0xbc, 0x58, 0x80, 0x1e, 0x62, 0x71, + 0x8c, 0x94, 0xa5, 0x6c, 0x6c, 0xcf, 0x57, 0xc5, 0x2e, 0x27, 0x14, 0x98, 0x82, 0xb8, 0x8f, 0x50, + 0x1e, 0xb1, 0x03, 0xce, 0x5b, 0x67, 0xc8, 0x94, 0xcf, 0x79, 0x1a, 0x81, 0xb6, 0x13, 0x2e, 0xe3, + 0x92, 0x0d, 0x4d, 0x40, 0x2f, 0xb8, 0x7d, 0x10, 0xa9, 0xd7, 0xcb, 0x4e, 0xdb, 0xbc, 0xab, 0xae, + 0x48, 0x25, 0x0a, 0xb2, 0x4a, 0x50, 0xef, 0x12, 0xeb, 0x4d, 0xb8, 0x8c, 0x7f, 0xa2, 0x2e, 0x83, + 0x10, 0x97, 0x59, 0x06, 0xe5, 0x10, 0xc4, 0x5c, 0x75, 0x1c, 0x7e, 0xa3, 0x1f, 0x41, 0x4d, 0x73, + 0x1c, 0xf3, 0x3c, 0x98, 0x3c, 0x9e, 0x5b, 0x91, 0xa6, 0xbd, 0x4b, 0xb1, 0x62, 0x87, 0xae, 0x6a, + 0xd1, 0x47, 0x98, 0xb6, 0x29, 0x24, 0xd3, 0x36, 0xb4, 0x4f, 0x29, 0x6d, 0xf3, 0x18, 0xea, 0xe4, + 0x78, 0xe2, 0xa8, 0xd3, 0x99, 0xe9, 0x1b, 0x27, 0xb6, 0x23, 0x2e, 0x9f, 0xd6, 0xa3, 0x06, 0xbd, + 0xe3, 0x89, 0xb3, 0x2f, 0xb0, 0xb8, 0x46, 0xa4, 0x2f, 0xd4, 0x85, 0x26, 0x3f, 0x56, 0xbb, 0x64, + 0x6c, 0x92, 0x91, 0x6f, 0xbb, 0x6c, 0x79, 0xab, 0x0f, 0xdb, 0xd2, 0xec, 0x51, 0x02, 0x1c, 0xe0, + 0x71, 0xc3, 0x8d, 0x7d, 0xa3, 0xbb, 0x50, 0x34, 0xac, 0xb1, 0xcd, 0xfc, 0x56, 0x2c, 0xc8, 0xa5, + 0x72, 0xf2, 0xac, 0x11, 0x23, 0xa0, 0xee, 0xdc, 0x37, 0xa6, 0xc4, 0xf5, 0x98, 0xe3, 0x8a, 0xb9, + 0xf3, 0x21, 0x83, 0x63, 0x81, 0xa7, 0xc1, 0xb3, 0xef, 0x6a, 0x96, 0xc7, 0xd2, 0x2b, 0xe5, 0x24, + 0xdf, 0x61, 0x80, 0xc2, 0x11, 0x15, 0x9d, 0x67, 0x3e, 0x10, 0x9e, 0x3b, 0x62, 0xbe, 0x2d, 0x36, + 0xcf, 0x6c, 0x14, 0xc2, 0xe9, 0xf3, 0x54, 0x02, 0xff, 0x50, 0xfe, 0x25, 0x07, 0x55, 0x69, 0x11, + 0xd0, 0xe7, 0x50, 0x31, 0x2c, 0x35, 0x16, 0xd1, 0x5d, 0xb4, 0x79, 0x96, 0x0d, 0x4b, 0x34, 0xfc, + 0x29, 0xd4, 0xc9, 0x19, 0x15, 0x26, 0xbe, 0xd6, 0x17, 0x35, 0xae, 0xf1, 0x06, 0x11, 0x03, 0x63, + 0x2a, 0x33, 0x28, 0xbc, 0x99, 0x01, 0x6f, 0x20, 0xec, 0xf0, 0xcf, 0xa0, 0xca, 0xbd, 0xc9, 0x9e, + 0x31, 0x35, 0xe6, 0xe6, 0xe4, 0xd0, 0x6d, 0xa8, 0x4d, 0xb5, 0xb3, 0xc8, 0x1f, 0x71, 0x2b, 0xa8, + 0x4e, 0xb5, 0xb3, 0xd0, 0x6d, 0x7d, 0x06, 0xeb, 0x9e, 0xb8, 0x2c, 0x52, 0xfd, 0x13, 0x97, 0x78, + 0x27, 0xb6, 0xa9, 0xab, 0xce, 0xc8, 0x17, 0x5e, 0x65, 0x35, 0xc0, 0x0e, 0x03, 0xe4, 0x60, 0xe4, + 0x2b, 0xff, 0xbd, 0x08, 0xe5, 0x40, 0x3b, 0xd1, 0xf7, 0xa0, 0xae, 0xcd, 0xfc, 0x13, 0xd5, 0xd1, + 0x3c, 0xef, 0xb5, 0xed, 0xea, 0xc2, 0xcf, 0xd6, 0x28, 0x70, 0x20, 0x60, 0xe8, 0x16, 0x54, 0x75, + 0xe2, 0x8d, 0x5c, 0xc3, 0x91, 0x6e, 0x7d, 0x64, 0x10, 0xba, 0x02, 0x65, 0xd3, 0x1e, 0x69, 0xa6, + 0xaa, 0x79, 0x41, 0x62, 0x87, 0x7d, 0x77, 0x99, 0x6f, 0x0d, 0x77, 0x8d, 0x20, 0xf1, 0x54, 0x64, + 0x1c, 0x9a, 0x01, 0xbc, 0x2b, 0x72, 0x75, 0x1b, 0xb0, 0xe4, 0x10, 0xe2, 0x52, 0x26, 0x3c, 0x7f, + 0x53, 0xa2, 0x9f, 0x5d, 0x8f, 0xee, 0x88, 0x0c, 0x31, 0x71, 0xed, 0x99, 0xc3, 0x74, 0xb8, 0x82, + 0x2b, 0x14, 0xb2, 0x4b, 0x01, 0x74, 0x47, 0x64, 0x68, 0xe6, 0x57, 0x78, 0xae, 0xba, 0x4c, 0x01, + 0xec, 0x0a, 0xe9, 0x00, 0x96, 0x5d, 0x32, 0xb5, 0x4f, 0x89, 0xea, 0xb8, 0xc6, 0xa9, 0xe6, 0xd3, + 0x5d, 0x95, 0xa9, 0x6b, 0xe3, 0xa1, 0x92, 0x36, 0xd7, 0x2d, 0xcc, 0x68, 0x07, 0x9c, 0xb4, 0xeb, + 0xe1, 0xa6, 0x1b, 0x07, 0xd0, 0x0d, 0x8d, 0xeb, 0xf0, 0xd8, 0xd4, 0x1c, 0x55, 0xd7, 0xa6, 0x8e, + 0x61, 0x4d, 0x98, 0x26, 0x97, 0x71, 0x8b, 0x61, 0x9e, 0x9a, 0x9a, 0xb3, 0xc3, 0xe1, 0xe8, 0x0e, + 0x34, 0x3c, 0x62, 0xe9, 0xaa, 0xb8, 0x22, 0xf3, 0xcf, 0xd9, 0x8e, 0x5d, 0xc7, 0x75, 0x0a, 0xdd, + 0x0e, 0x80, 0x74, 0x80, 0xe2, 0x16, 0x61, 0xa4, 0x39, 0xed, 0x2a, 0x8b, 0x5f, 0x2a, 0x1c, 0xb2, + 0xad, 0xb1, 0x01, 0xf2, 0xe9, 0xa5, 0xd8, 0x1a, 0xc3, 0xf2, 0xf9, 0xa6, 0xc8, 0x06, 0xe4, 0x0d, + 0x9d, 0x6d, 0xd9, 0x15, 0x9c, 0x37, 0x74, 0xf4, 0x63, 0xa8, 0x8b, 0xdc, 0xbd, 0x49, 0x15, 0xcc, + 0x6b, 0x37, 0x92, 0x9b, 0x88, 0xa4, 0x7e, 0xb8, 0xe6, 0x44, 0x1f, 0x1e, 0x55, 0x07, 0xb1, 0x8e, + 0x62, 0xa5, 0x9a, 0x5c, 0x1d, 0xf8, 0x62, 0x8a, 0x65, 0xfa, 0x08, 0x50, 0x14, 0x07, 0x58, 0x3e, + 0x71, 0xc7, 0xda, 0x88, 0xb0, 0x2d, 0xbd, 0x82, 0x97, 0xc3, 0x70, 0x20, 0x40, 0xd0, 0xf8, 0xeb, + 0xd4, 0x1d, 0xb3, 0xd4, 0x77, 0x85, 0xe5, 0xaa, 0xd0, 0x2d, 0xa8, 0x69, 0xa6, 0x69, 0xbf, 0x56, + 0xa9, 0xe2, 0x6a, 0x5e, 0x1b, 0xf1, 0xeb, 0x05, 0x06, 0x3b, 0x7c, 0x6d, 0x75, 0x3d, 0xf4, 0x01, + 0x34, 0x5d, 0x1e, 0xe0, 0xaa, 0x81, 0x46, 0xac, 0xb0, 0x19, 0xae, 0x0b, 0xf0, 0x80, 0x29, 0x86, + 0xf2, 0x00, 0x9a, 0x89, 0x05, 0x43, 0x65, 0x28, 0x1e, 0x1c, 0x1e, 0xf4, 0xf8, 0xb5, 0x6e, 0x77, + 0x6f, 0xaf, 0x95, 0x43, 0x55, 0x58, 0xc2, 0xbd, 0xc1, 0x5e, 0x77, 0xbb, 0xd7, 0xca, 0x2b, 0x5f, + 0x41, 0x4d, 0x76, 0xb5, 0xa8, 0x0d, 0x4b, 0x3c, 0xd1, 0x18, 0xbc, 0x04, 0x09, 0x3e, 0x99, 0x05, + 0x0a, 0x2a, 0xd5, 0xf7, 0xcd, 0xd0, 0x02, 0x05, 0x6c, 0xe8, 0x9b, 0xca, 0x5f, 0xe4, 0xa0, 0x11, + 0xf7, 0xbc, 0xd4, 0x28, 0x13, 0xce, 0x5a, 0x1d, 0x99, 0x46, 0x10, 0xe3, 0x97, 0xf1, 0x6a, 0xdc, + 0x33, 0x6f, 0x33, 0x1c, 0x7a, 0x0c, 0x9d, 0x74, 0xab, 0x99, 0x47, 0x23, 0x92, 0xf0, 0x02, 0x71, + 0x23, 0xd9, 0x92, 0xe1, 0xfb, 0xba, 0xf2, 0xf7, 0x25, 0xa8, 0x84, 0x7e, 0xfc, 0x7f, 0xc1, 0xa4, + 0xb7, 0xa0, 0x3c, 0x25, 0x9e, 0xa7, 0x4d, 0x44, 0x98, 0x14, 0xdb, 0xf8, 0xf6, 0x05, 0x06, 0x87, + 0x34, 0x99, 0x2e, 0x60, 0xf1, 0x8d, 0x2e, 0xa0, 0x74, 0x81, 0x0b, 0x58, 0xba, 0xd0, 0x05, 0x94, + 0x13, 0x2e, 0x60, 0x13, 0x4a, 0xdf, 0xcd, 0xc8, 0x8c, 0x78, 0x62, 0xc3, 0x91, 0xf6, 0xb4, 0xaf, + 0x19, 0x1c, 0x0b, 0x3c, 0xba, 0x9f, 0xe5, 0x2c, 0xb8, 0xc5, 0x5e, 0xd2, 0x11, 0x54, 0x2f, 0xed, + 0x08, 0x6a, 0x59, 0x8e, 0x80, 0xdd, 0x7a, 0x79, 0x9e, 0x61, 0x5b, 0x3c, 0x7f, 0xc0, 0xec, 0xba, + 0x8e, 0x6b, 0x02, 0xc8, 0x57, 0xf8, 0x87, 0xb0, 0xee, 0xcd, 0x1c, 0xba, 0xa5, 0x10, 0x9d, 0xba, + 0x04, 0xed, 0xd8, 0x30, 0x0d, 0x9f, 0x06, 0x36, 0x0d, 0x96, 0x71, 0x5f, 0x0b, 0xb1, 0xdb, 0x12, + 0x92, 0xce, 0x11, 0x0d, 0x41, 0x38, 0x5f, 0x6e, 0xd8, 0xe5, 0xe3, 0x89, 0xc3, 0x79, 0xfe, 0x14, + 0xaa, 0x9a, 0x3e, 0x35, 0x82, 0x6e, 0x5b, 0xcc, 0x41, 0xde, 0xc8, 0x88, 0x13, 0xb6, 0xba, 0x94, + 0x8c, 0x87, 0x0c, 0xa0, 0x85, 0xbf, 0x69, 0x7c, 0x15, 0xdc, 0xdf, 0x31, 0x5b, 0xaf, 0xe3, 0xf0, + 0x9b, 0xe2, 0xb4, 0xd1, 0x88, 0x38, 0x3e, 0xd1, 0x85, 0xb1, 0x87, 0xdf, 0xf4, 0x5c, 0xa5, 0x45, + 0x8f, 0xb1, 0x56, 0x84, 0x2b, 0x88, 0x9e, 0x61, 0xad, 0xc0, 0xa2, 0x3d, 0xf3, 0xd5, 0xef, 0xda, + 0xab, 0xfc, 0x06, 0xc7, 0x9e, 0xf9, 0x5f, 0xd3, 0xa3, 0xcc, 0xd8, 0xb4, 0x1d, 0xaf, 0xbd, 0xc6, + 0x80, 0xfc, 0x43, 0xb9, 0x0f, 0x10, 0x09, 0x87, 0x4a, 0x90, 0x7f, 0x3e, 0xe0, 0x57, 0xd3, 0x3b, + 0x87, 0xbf, 0x38, 0x68, 0xe5, 0x10, 0x40, 0x69, 0xf0, 0xf4, 0xa5, 0xba, 0x3d, 0x6c, 0xe5, 0x95, + 0x3f, 0x86, 0x72, 0xa0, 0xa9, 0xe8, 0x23, 0x49, 0x74, 0x1e, 0x4b, 0x2c, 0xa7, 0xf4, 0x59, 0x1a, + 0xcd, 0x1d, 0x28, 0x7a, 0xc1, 0x7d, 0x71, 0x26, 0x29, 0x43, 0x2b, 0xbf, 0xce, 0xc1, 0x92, 0x80, + 0x20, 0x05, 0x6a, 0x07, 0x87, 0xc3, 0xfe, 0xd3, 0xfe, 0x76, 0x77, 0xd8, 0x3f, 0x3c, 0x60, 0xbd, + 0x14, 0x71, 0x0c, 0x46, 0x03, 0x81, 0xe7, 0x83, 0x9d, 0xee, 0xb0, 0xc7, 0x18, 0x17, 0xb1, 0xf8, + 0xa2, 0xe7, 0x87, 0xc3, 0x41, 0xef, 0x40, 0xbc, 0x71, 0x60, 0xbf, 0xd1, 0x35, 0xa8, 0x7c, 0xd5, + 0xeb, 0x0d, 0xba, 0x7b, 0xfd, 0x17, 0x3d, 0x66, 0x82, 0x45, 0x1c, 0x01, 0xa8, 0x4b, 0xc3, 0xbd, + 0xa7, 0xb8, 0x77, 0xf4, 0x8c, 0x99, 0x59, 0x11, 0x07, 0x9f, 0xb4, 0xdd, 0x4e, 0xff, 0x68, 0xbb, + 0x8b, 0x77, 0x7a, 0x3b, 0xcc, 0xc0, 0x8a, 0x38, 0x02, 0xd0, 0x59, 0x1d, 0x1e, 0x0e, 0xbb, 0x7b, + 0xcc, 0xbc, 0x8a, 0x98, 0x7f, 0x28, 0x8f, 0xa0, 0xc4, 0xad, 0x84, 0xe2, 0x0d, 0xcb, 0x99, 0xf9, + 0x22, 0x52, 0xe1, 0x1f, 0x54, 0x6e, 0x7b, 0xe6, 0x53, 0xb0, 0x08, 0xd4, 0xf9, 0x97, 0x42, 0xa0, + 0xc4, 0x23, 0x46, 0xb4, 0x05, 0x25, 0x1a, 0x04, 0x1b, 0x13, 0x31, 0xbb, 0xeb, 0xc9, 0x98, 0x72, + 0x9b, 0x61, 0xb1, 0xa0, 0x42, 0x3f, 0x88, 0xdf, 0x71, 0xae, 0x25, 0xc9, 0x63, 0xb7, 0x9c, 0xbf, + 0xce, 0x41, 0x4d, 0xe6, 0x42, 0x4d, 0x68, 0x64, 0x5b, 0x16, 0x19, 0xf9, 0xaa, 0x4b, 0x7c, 0xf7, + 0x3c, 0x98, 0x6c, 0x01, 0xc4, 0x14, 0x46, 0x6d, 0x81, 0x05, 0x4b, 0xe1, 0x85, 0x7b, 0x11, 0x97, + 0x29, 0x80, 0x72, 0xa2, 0x1b, 0xdc, 0xb7, 0x84, 0x38, 0x9a, 0x69, 0x9c, 0x12, 0x35, 0xf1, 0xc6, + 0x64, 0x39, 0xc4, 0xf4, 0x05, 0x02, 0xed, 0xc0, 0x8d, 0xa9, 0x61, 0x19, 0xd3, 0xd9, 0x54, 0x0d, + 0xf5, 0x96, 0xc6, 0x7d, 0x51, 0x53, 0xbe, 0x42, 0xd7, 0x04, 0x55, 0x57, 0x26, 0x0a, 0xb8, 0x28, + 0xbf, 0xca, 0x43, 0x55, 0x1a, 0xde, 0xff, 0xd3, 0x61, 0xb0, 0x34, 0x08, 0x99, 0xd8, 0xbe, 0xa1, + 0x51, 0xe7, 0x14, 0x09, 0xc7, 0x15, 0x11, 0x45, 0xb8, 0x67, 0x81, 0x98, 0xd1, 0x93, 0x08, 0xae, + 0x90, 0x59, 0x4f, 0x22, 0xb8, 0x42, 0x86, 0xdf, 0xca, 0x7f, 0xe5, 0xa0, 0x12, 0x9e, 0x30, 0xd2, + 0x51, 0x4b, 0x2e, 0x23, 0x6a, 0xb9, 0x0e, 0xc0, 0x89, 0xa4, 0xeb, 0x60, 0x1e, 0x55, 0x0d, 0x04, + 0x8f, 0xa9, 0x3f, 0x53, 0x75, 0xc3, 0x1b, 0xd9, 0xa7, 0xc4, 0x3d, 0x17, 0x99, 0x82, 0xda, 0xd4, + 0x9f, 0xed, 0x04, 0x30, 0x1a, 0x11, 0xd0, 0x5d, 0x95, 0xce, 0xe7, 0xd4, 0xd6, 0x83, 0xab, 0xc9, + 0xaa, 0x80, 0xed, 0xdb, 0x3a, 0x3d, 0x1b, 0x37, 0x44, 0x24, 0x17, 0xdf, 0xe9, 0xea, 0x1c, 0xda, + 0xcd, 0x7e, 0x36, 0x52, 0x0a, 0x9e, 0x68, 0x04, 0xcf, 0x46, 0xe8, 0x46, 0xe8, 0x8f, 0x1c, 0x75, + 0xea, 0x79, 0x22, 0xa2, 0x2d, 0xf9, 0x23, 0x67, 0xdf, 0xf3, 0x94, 0x2f, 0xa0, 0x2a, 0x9d, 0x92, + 0xd0, 0x16, 0xac, 0xc8, 0x47, 0xaa, 0x78, 0xac, 0xb1, 0x2c, 0x1d, 0xa1, 0x78, 0xa0, 0xa1, 0xcc, + 0xa0, 0xc4, 0xc3, 0x3f, 0xaa, 0x3b, 0x86, 0xa3, 0xc6, 0xd2, 0x2b, 0x65, 0xc3, 0x11, 0xc8, 0x0f, + 0xa0, 0x39, 0xd5, 0xbc, 0x6f, 0x55, 0x93, 0x58, 0x13, 0xff, 0x44, 0x9d, 0x1a, 0x96, 0x98, 0xb2, + 0x3a, 0x05, 0xef, 0x31, 0xe8, 0xbe, 0x61, 0xa5, 0xe8, 0xb4, 0x33, 0x11, 0x2c, 0xc8, 0x74, 0xda, + 0x99, 0xf2, 0x57, 0x39, 0x80, 0xe8, 0x6e, 0xeb, 0xb7, 0xbc, 0x80, 0xa4, 0x30, 0xd3, 0xf0, 0x7c, + 0xf6, 0x84, 0xaa, 0x82, 0xd9, 0x6f, 0x76, 0xa7, 0x12, 0xe5, 0x6e, 0x92, 0x77, 0x2a, 0x0c, 0x83, + 0x43, 0x0a, 0x65, 0x17, 0xca, 0xfb, 0x9a, 0x3f, 0x3a, 0xa1, 0xc2, 0xdc, 0x8d, 0x09, 0x23, 0x9d, + 0x61, 0x19, 0xc5, 0x1b, 0xee, 0x42, 0x5f, 0x40, 0xad, 0xeb, 0x0d, 0x34, 0xff, 0x84, 0x8f, 0x15, + 0x6d, 0xc5, 0x98, 0x49, 0xa7, 0x42, 0x99, 0x4a, 0xe2, 0xb9, 0x0e, 0x25, 0x3e, 0x77, 0x81, 0xf7, + 0xe4, 0x5f, 0xca, 0x7f, 0x16, 0x01, 0xb6, 0x6d, 0x4b, 0x37, 0x78, 0x76, 0xe7, 0x01, 0x88, 0xd7, + 0x37, 0x6a, 0x74, 0xa1, 0x88, 0x12, 0x92, 0x1e, 0x11, 0x1f, 0x57, 0x38, 0x15, 0x1d, 0xd6, 0x0f, + 0xa1, 0x16, 0x46, 0x5d, 0xb4, 0x51, 0x7e, 0x6e, 0xa3, 0x30, 0xad, 0x47, 0x9b, 0xfd, 0x04, 0x1a, + 0x9a, 0xa7, 0x3a, 0x9a, 0x7f, 0x22, 0x16, 0x55, 0x1c, 0x70, 0xd7, 0xb3, 0x87, 0x82, 0x6b, 0x9a, + 0x3c, 0xfc, 0x87, 0x50, 0x0d, 0x5a, 0xd3, 0x3e, 0x8b, 0xf3, 0x05, 0xe5, 0xcd, 0x68, 0x8f, 0x9f, + 0x87, 0xcf, 0x0a, 0xfd, 0x73, 0xd6, 0x6a, 0x71, 0x6e, 0xab, 0x5a, 0x48, 0x48, 0x1b, 0x7e, 0x09, + 0xcb, 0xe4, 0xcc, 0x57, 0xe3, 0x8d, 0x4b, 0x73, 0x1b, 0x37, 0xc9, 0x99, 0xbf, 0x2d, 0xb7, 0xa7, + 0x46, 0xe8, 0x7c, 0x6b, 0xa8, 0x2e, 0xf1, 0x66, 0xa6, 0xcf, 0xec, 0x6c, 0x11, 0x83, 0xcb, 0x9f, + 0x3e, 0xcc, 0x4c, 0x1f, 0x7d, 0x01, 0x10, 0xbd, 0x67, 0x10, 0x87, 0x46, 0x29, 0x26, 0x8a, 0xd6, + 0x87, 0x27, 0x2e, 0xd8, 0xb2, 0x56, 0xc2, 0xe7, 0x0e, 0xe8, 0x09, 0xac, 0x98, 0x9a, 0x3b, 0x21, + 0x09, 0x09, 0x2b, 0x73, 0x25, 0x5c, 0x66, 0xe4, 0xb2, 0x8c, 0xca, 0x09, 0x54, 0x42, 0xde, 0x68, + 0x05, 0x9a, 0xf8, 0xf0, 0xf9, 0xb0, 0xa7, 0x0e, 0x5f, 0x0d, 0x7a, 0xaa, 0x38, 0xe6, 0x6c, 0xc0, + 0x8a, 0x04, 0xec, 0x1f, 0x0c, 0x7b, 0xf8, 0xa0, 0x4b, 0x8f, 0x3d, 0x71, 0x44, 0xef, 0xa5, 0x40, + 0xe4, 0xd1, 0x2a, 0xb4, 0x24, 0xc4, 0xde, 0xe1, 0x76, 0x77, 0xaf, 0x55, 0x50, 0xc6, 0xd0, 0x0c, + 0x7b, 0xee, 0xf2, 0x07, 0xb2, 0x0f, 0x62, 0xca, 0x7c, 0x5d, 0x1e, 0x79, 0x8c, 0x50, 0xd2, 0xe7, + 0x5b, 0x50, 0x0d, 0x46, 0x6b, 0x84, 0x4f, 0x40, 0x64, 0x90, 0x72, 0x00, 0x95, 0x7d, 0xa2, 0x8b, + 0x1e, 0x7e, 0x10, 0xeb, 0x61, 0x43, 0x8e, 0xa5, 0xf4, 0x14, 0xef, 0x55, 0x58, 0x3c, 0xd5, 0xcc, + 0x59, 0xf0, 0x42, 0x8e, 0x7f, 0x28, 0x2a, 0x34, 0xbb, 0xde, 0xc0, 0x25, 0x0e, 0xb1, 0x02, 0xae, + 0x2d, 0x28, 0x68, 0x9e, 0x25, 0xc2, 0x14, 0xfa, 0x93, 0x9a, 0x19, 0xa5, 0xd0, 0xc2, 0x20, 0x85, + 0x7f, 0x21, 0x05, 0xea, 0x33, 0x8f, 0xa8, 0x26, 0x19, 0xfb, 0xea, 0xd4, 0xf6, 0x7c, 0xe1, 0xf6, + 0xab, 0x33, 0x8f, 0xec, 0x91, 0xb1, 0xbf, 0x6f, 0xb3, 0x6b, 0x93, 0xba, 0x48, 0x53, 0x0b, 0xf6, + 0x17, 0xbe, 0x36, 0xf2, 0x88, 0x39, 0x16, 0x77, 0x45, 0xec, 0xb7, 0x72, 0x17, 0x9a, 0x7b, 0x6c, + 0x9b, 0x71, 0xc9, 0x58, 0x30, 0x08, 0x07, 0x22, 0x02, 0x29, 0x3e, 0x90, 0x7f, 0x2d, 0xc0, 0x12, + 0x27, 0xf0, 0xa2, 0x4c, 0x99, 0xc6, 0x1f, 0x42, 0xa7, 0x1c, 0x25, 0x53, 0x0a, 0x4e, 0x2d, 0x32, + 0x65, 0x82, 0xf7, 0xe7, 0x50, 0x89, 0xce, 0x18, 0xdc, 0xe6, 0xaf, 0xcc, 0x5d, 0x38, 0x1c, 0xd1, + 0xa2, 0x3b, 0x50, 0x98, 0x12, 0x5d, 0x58, 0xfb, 0x4a, 0xc6, 0x4a, 0x60, 0x8a, 0x47, 0x3f, 0x02, + 0xa0, 0x16, 0xce, 0xe7, 0x5b, 0x18, 0xf8, 0x95, 0x98, 0x6f, 0x90, 0x97, 0x82, 0xd9, 0x39, 0x07, + 0xa0, 0x2f, 0xa1, 0x1e, 0x33, 0x57, 0x61, 0xe7, 0x17, 0x48, 0x57, 0x93, 0x2d, 0x16, 0x3d, 0x80, + 0x25, 0x71, 0x8f, 0x20, 0x8c, 0x5c, 0x52, 0x97, 0xd8, 0x02, 0xe1, 0x80, 0x8e, 0x0a, 0x2b, 0x36, + 0x7d, 0x97, 0x8c, 0x45, 0x46, 0x53, 0xea, 0x2f, 0xb1, 0x2e, 0x41, 0x3c, 0xe0, 0x92, 0x31, 0x7a, + 0x02, 0xcd, 0x84, 0xed, 0x8a, 0x1c, 0xe7, 0x05, 0xe2, 0x36, 0xe2, 0xe6, 0xab, 0xfc, 0x32, 0x07, + 0x95, 0xf0, 0xae, 0x37, 0xdc, 0x3d, 0x72, 0xd2, 0x46, 0xf6, 0x19, 0xc0, 0x28, 0x74, 0x22, 0x62, + 0xb5, 0x56, 0xb3, 0x1c, 0x0c, 0x96, 0xe8, 0xd0, 0x0f, 0x60, 0x89, 0xab, 0x85, 0x27, 0x56, 0x4b, + 0x3a, 0x83, 0x08, 0x05, 0xc2, 0x01, 0x85, 0xf2, 0x35, 0x94, 0x44, 0xe6, 0x32, 0x4b, 0x80, 0xf8, + 0x6b, 0x91, 0xfc, 0xe5, 0x5e, 0x8b, 0xfc, 0x7b, 0x0e, 0x5a, 0xc9, 0x24, 0x27, 0xda, 0x8c, 0x59, + 0xf2, 0x6a, 0x32, 0x1d, 0x2a, 0x99, 0xb1, 0xfc, 0x90, 0x3a, 0x7f, 0x89, 0x87, 0xd4, 0x19, 0xc5, + 0x2d, 0xb1, 0x17, 0x14, 0xc5, 0x37, 0xbd, 0xa0, 0x40, 0x1f, 0xc3, 0x92, 0x4e, 0xc6, 0x1a, 0x75, + 0xf2, 0x8b, 0x17, 0x19, 0x52, 0x40, 0xa5, 0xfc, 0x65, 0x0e, 0x0a, 0xd8, 0xd6, 0x50, 0x03, 0xf2, + 0x9a, 0x27, 0xac, 0x34, 0xaf, 0x79, 0xf4, 0xfc, 0xc4, 0x37, 0x58, 0x93, 0x04, 0x01, 0x51, 0x04, + 0xa0, 0x4e, 0x66, 0xaa, 0x31, 0x94, 0xb8, 0xd5, 0xe1, 0x5f, 0xd2, 0x95, 0x45, 0x31, 0x76, 0x8b, + 0x15, 0x5c, 0x1e, 0x2c, 0x5e, 0xfc, 0xe6, 0x53, 0xb9, 0xcb, 0x6f, 0x6e, 0x6c, 0xed, 0x4d, 0xef, + 0x38, 0xf9, 0x93, 0x35, 0x46, 0x18, 0x3d, 0x59, 0x73, 0x6d, 0x2d, 0xe3, 0xc9, 0x1a, 0x25, 0x62, + 0x28, 0xc5, 0x83, 0xc2, 0x0b, 0x77, 0x9c, 0xa9, 0x1d, 0x0d, 0xc8, 0xbb, 0x3c, 0xfb, 0x54, 0xc3, + 0x79, 0x57, 0x67, 0x21, 0x23, 0xcf, 0x7d, 0xbb, 0x3c, 0xf8, 0xaa, 0xe1, 0x32, 0x07, 0x60, 0xf6, + 0x90, 0x5f, 0x64, 0xd6, 0x5d, 0x9f, 0xad, 0x49, 0x0d, 0x97, 0x39, 0x00, 0xfb, 0x22, 0x49, 0xc9, + 0xb3, 0xba, 0x79, 0x43, 0x57, 0x7e, 0x93, 0x83, 0x12, 0xbf, 0x1e, 0x4e, 0xcd, 0xf1, 0x55, 0xe0, + 0x5b, 0xa8, 0x94, 0xf9, 0x2a, 0x73, 0x40, 0x5f, 0xa7, 0x5b, 0x36, 0x8d, 0xf6, 0x88, 0xc5, 0xe3, + 0xe6, 0x02, 0xdf, 0xb2, 0x39, 0x88, 0xc5, 0xcd, 0xf7, 0xa0, 0x25, 0x08, 0x84, 0x4f, 0x16, 0x0a, + 0x52, 0xc1, 0x4d, 0x0e, 0xef, 0x06, 0xe0, 0xd8, 0x8d, 0xd0, 0x62, 0xe2, 0x46, 0xe8, 0x43, 0x40, + 0x74, 0x5f, 0x60, 0xb9, 0x3e, 0xc7, 0x24, 0x2a, 0xbf, 0x6d, 0x2c, 0xf1, 0xe4, 0xce, 0xcc, 0x23, + 0xfb, 0x02, 0x31, 0x60, 0xaf, 0xf5, 0xff, 0x99, 0x1e, 0x47, 0xb4, 0x63, 0x93, 0xf4, 0xad, 0xb1, + 0xfd, 0x3b, 0xb9, 0x18, 0xbc, 0x0b, 0x4d, 0x6b, 0x36, 0x55, 0xa5, 0x1b, 0x3f, 0x71, 0x1a, 0x6b, + 0x58, 0xb3, 0xa9, 0x7c, 0x63, 0x7a, 0x05, 0xca, 0x94, 0x90, 0x15, 0x38, 0x89, 0xc3, 0xbf, 0x35, + 0x9b, 0xb2, 0x4b, 0xf3, 0xdb, 0x50, 0xa3, 0xa8, 0x30, 0x13, 0xc3, 0x8f, 0x5b, 0x55, 0x6b, 0x36, + 0xed, 0x0a, 0x90, 0xf2, 0x13, 0xf6, 0x42, 0x00, 0x1b, 0xc7, 0x74, 0x20, 0x81, 0xb6, 0x05, 0x77, + 0x47, 0xa9, 0x07, 0x52, 0xe1, 0x90, 0xf9, 0xdd, 0x91, 0xf2, 0x05, 0xab, 0xb9, 0x0b, 0x5b, 0x0b, + 0x15, 0xbc, 0x6c, 0xf3, 0xfb, 0xdb, 0x50, 0x0e, 0x66, 0x08, 0x01, 0x94, 0x76, 0xf7, 0x0e, 0x9f, + 0x74, 0xf7, 0x5a, 0x0b, 0xa8, 0x02, 0x8b, 0x3c, 0x46, 0x61, 0x19, 0x9c, 0xee, 0xce, 0xcf, 0xd5, + 0xfe, 0x41, 0x2b, 0x8f, 0xaa, 0xb0, 0x44, 0x7f, 0x1f, 0x3e, 0x1f, 0xb6, 0x0a, 0x68, 0x09, 0x0a, + 0x2f, 0xf0, 0xd3, 0x56, 0xf1, 0xbe, 0x0f, 0x55, 0xe9, 0x0c, 0xc1, 0x52, 0x3e, 0xb8, 0xf7, 0xb4, + 0xff, 0xb2, 0xb5, 0x80, 0x6a, 0x50, 0x3e, 0xe8, 0xf5, 0x77, 0x9f, 0x3d, 0x39, 0xc4, 0xad, 0x1c, + 0x6d, 0x31, 0xec, 0xee, 0x0a, 0x3e, 0x47, 0xea, 0xa0, 0x3b, 0x7c, 0xd6, 0x2a, 0xa0, 0x3a, 0x54, + 0xb6, 0x0f, 0xf7, 0xf7, 0x9f, 0x1f, 0xf4, 0x87, 0xaf, 0x5a, 0x45, 0xb4, 0x0c, 0xf5, 0xde, 0xcb, + 0xa1, 0x1a, 0x81, 0x16, 0x69, 0x0c, 0xb6, 0xd7, 0xc5, 0xbb, 0x3d, 0x09, 0x58, 0xba, 0x7f, 0x0f, + 0x2a, 0xe1, 0x61, 0x81, 0xe5, 0x9d, 0x0f, 0x5e, 0xc9, 0x09, 0x68, 0x80, 0x52, 0xff, 0xe0, 0x45, + 0x0f, 0x0f, 0x5b, 0xf9, 0xfb, 0xf7, 0xa1, 0x95, 0x3c, 0x0a, 0xa0, 0x12, 0xe4, 0x7b, 0x5f, 0xb7, + 0x16, 0xe8, 0xdf, 0xdd, 0x5e, 0x2b, 0x47, 0xff, 0xee, 0xf5, 0x5a, 0xf9, 0xfb, 0x1f, 0x8b, 0xb3, + 0x9e, 0xd8, 0xda, 0xa3, 0xd4, 0x36, 0x9d, 0x87, 0xed, 0xed, 0xde, 0x60, 0xc8, 0x99, 0xe3, 0xde, + 0xcf, 0x7b, 0xdb, 0x94, 0xf9, 0x73, 0x58, 0xc9, 0x08, 0xcd, 0xe8, 0x30, 0x42, 0x69, 0xd5, 0xee, + 0xce, 0x4e, 0x6b, 0x81, 0xc6, 0x80, 0x11, 0x08, 0xf7, 0xf6, 0x0f, 0x5f, 0xd0, 0x8e, 0xd7, 0x60, + 0x59, 0x86, 0x8a, 0x9c, 0xf9, 0xfd, 0x8f, 0xa0, 0x1e, 0x8b, 0xc7, 0xe8, 0x9c, 0xed, 0xf7, 0x76, + 0xd4, 0xfd, 0x43, 0xca, 0xaa, 0x09, 0x55, 0xfa, 0x11, 0x90, 0xe7, 0xee, 0x7f, 0x08, 0x10, 0x39, + 0xfd, 0xb0, 0xca, 0x8a, 0x4e, 0xc2, 0xfe, 0xe0, 0x10, 0x0b, 0x99, 0x7b, 0x2f, 0xd9, 0xef, 0xfc, + 0xc3, 0xff, 0xb8, 0x09, 0xe5, 0x5d, 0xaa, 0x13, 0x5d, 0xc7, 0x40, 0x7b, 0x50, 0x95, 0xde, 0x88, + 0xa0, 0x6b, 0xb1, 0xad, 0x28, 0xf1, 0xf4, 0xa4, 0x73, 0x7d, 0x0e, 0x56, 0x5c, 0xfd, 0x2e, 0xa0, + 0x3e, 0x40, 0xf4, 0x8a, 0x04, 0x5d, 0x95, 0xc9, 0x13, 0x0f, 0x4e, 0x3a, 0xd7, 0xb2, 0x91, 0x21, + 0xab, 0xa7, 0x50, 0x09, 0xdf, 0xce, 0x20, 0xe9, 0x58, 0x97, 0x7c, 0x64, 0xd3, 0xb9, 0x9a, 0x89, + 0x0b, 0xf9, 0xec, 0x41, 0x55, 0x2a, 0xfa, 0x93, 0x07, 0x98, 0xae, 0x22, 0x94, 0x07, 0x98, 0x55, + 0x29, 0xb8, 0x80, 0x9e, 0x43, 0x23, 0x5e, 0xee, 0x87, 0x6e, 0xca, 0x67, 0xe9, 0x8c, 0x2a, 0xc2, + 0xce, 0xad, 0xf9, 0x04, 0xb2, 0x90, 0x52, 0x81, 0xab, 0x2c, 0x64, 0xba, 0xa6, 0x56, 0x16, 0x32, + 0xa3, 0x2a, 0x56, 0x59, 0x40, 0x18, 0xea, 0xb1, 0x3a, 0x3a, 0x74, 0x23, 0xe6, 0x12, 0xd3, 0x1c, + 0x6f, 0xce, 0xc5, 0x87, 0x3c, 0xff, 0x08, 0x96, 0x53, 0xf5, 0x79, 0x48, 0x79, 0x73, 0x9d, 0x60, + 0xe7, 0x7b, 0x17, 0xd2, 0x84, 0xfc, 0x7f, 0x1f, 0x5a, 0xc9, 0x3a, 0x3c, 0x74, 0x5b, 0x6a, 0x9a, + 0x5d, 0xfe, 0xd7, 0x51, 0x2e, 0x22, 0x91, 0x57, 0x2d, 0x5e, 0x95, 0x27, 0xaf, 0x5a, 0x66, 0x89, + 0x9f, 0xbc, 0x6a, 0x73, 0x0a, 0xfa, 0x16, 0xd0, 0x4b, 0x68, 0x26, 0x0a, 0xef, 0x90, 0xbc, 0xd8, + 0x99, 0xd5, 0x7e, 0x9d, 0xdb, 0x17, 0x50, 0x84, 0x9c, 0xbf, 0x80, 0x12, 0x77, 0xec, 0x68, 0x23, + 0xb6, 0xd8, 0xd1, 0xb3, 0x8e, 0x4e, 0x3b, 0x8d, 0x90, 0xd5, 0x49, 0x7a, 0x9a, 0x21, 0xab, 0x53, + 0xfa, 0x7d, 0x88, 0xac, 0x4e, 0x59, 0xef, 0x39, 0x16, 0xd0, 0xcf, 0x60, 0x49, 0x94, 0x16, 0xa3, + 0x76, 0xcc, 0x3e, 0xa4, 0x12, 0xe2, 0xce, 0x95, 0x0c, 0x8c, 0xec, 0x16, 0xa2, 0x42, 0x5e, 0xd9, + 0x2d, 0xa4, 0x4a, 0x91, 0x65, 0xb7, 0x90, 0x51, 0xfb, 0xbb, 0x80, 0x76, 0x00, 0xa2, 0xd2, 0x33, + 0x99, 0x55, 0xaa, 0x20, 0xad, 0x93, 0xfd, 0x8a, 0x47, 0x59, 0xf8, 0x24, 0x87, 0x1e, 0x87, 0xa5, + 0x75, 0xd1, 0x35, 0x9e, 0xb4, 0x51, 0x86, 0xf5, 0xe2, 0x9d, 0x44, 0xd1, 0x2f, 0x6b, 0xfc, 0x14, + 0x2a, 0x61, 0xad, 0xa3, 0xec, 0x99, 0x92, 0x95, 0x96, 0xb2, 0x67, 0x4a, 0x17, 0x47, 0xf2, 0x59, + 0x09, 0x2b, 0x21, 0x63, 0xb3, 0x92, 0x2c, 0x9a, 0x8c, 0xcd, 0x4a, 0xba, 0x78, 0x72, 0x01, 0x3d, + 0x83, 0x4a, 0x58, 0xbd, 0x28, 0x8b, 0x94, 0xac, 0xa9, 0x94, 0x45, 0x4a, 0x97, 0x3b, 0x2e, 0x6c, + 0xe6, 0xa8, 0xe6, 0xf1, 0x1a, 0x42, 0x59, 0xf3, 0x62, 0xe5, 0x8a, 0x9d, 0x76, 0x1a, 0x21, 0x7b, + 0xed, 0xb0, 0x5c, 0x50, 0x16, 0x24, 0x59, 0x85, 0xd8, 0xb9, 0x9a, 0x89, 0x93, 0x75, 0x4e, 0x14, + 0x48, 0xa1, 0x84, 0xa2, 0x47, 0x95, 0x35, 0xb2, 0xce, 0x25, 0xaa, 0xa9, 0x42, 0xad, 0x4d, 0x72, + 0x88, 0x17, 0x4e, 0x25, 0xb4, 0x36, 0xc1, 0x21, 0xd4, 0x5a, 0xc6, 0x24, 0x25, 0xb0, 0xcc, 0xe7, + 0x5a, 0x36, 0x52, 0x66, 0x15, 0xd5, 0x2e, 0xa1, 0x94, 0x5e, 0xcc, 0x61, 0x95, 0x51, 0xee, 0xc4, + 0x6c, 0x5b, 0x2a, 0x60, 0x42, 0x69, 0xcd, 0x90, 0x99, 0x5d, 0x9f, 0x83, 0x95, 0xd7, 0x2b, 0x2c, + 0x3f, 0x92, 0xd7, 0x2b, 0x59, 0xc5, 0x24, 0xaf, 0x57, 0xba, 0x5e, 0x89, 0x6d, 0x39, 0xb1, 0x52, + 0x26, 0x79, 0xcb, 0xc9, 0xaa, 0x8a, 0x92, 0xb7, 0x9c, 0xec, 0x1a, 0xa8, 0xd0, 0x09, 0xda, 0x5a, + 0xd2, 0x09, 0x86, 0xe7, 0xb2, 0xa4, 0x13, 0x8c, 0xce, 0x61, 0x7c, 0xa2, 0xa4, 0xb2, 0x23, 0x94, + 0x9a, 0x57, 0xb9, 0xb4, 0x4a, 0x9e, 0xa8, 0xac, 0x5a, 0xa5, 0x05, 0x61, 0x17, 0xf4, 0xdc, 0x16, + 0xb7, 0x8b, 0xa8, 0x64, 0x28, 0x61, 0x17, 0x72, 0x59, 0x90, 0x64, 0x17, 0x94, 0x43, 0xca, 0x2e, + 0x24, 0x26, 0x57, 0x33, 0x71, 0x89, 0x39, 0x49, 0x88, 0x11, 0x2b, 0xa3, 0x4a, 0xcc, 0x49, 0xbc, + 0x39, 0x66, 0x07, 0x5b, 0xe9, 0x5e, 0xe0, 0x46, 0x8c, 0x38, 0x55, 0x50, 0x23, 0x2f, 0x53, 0x66, + 0x05, 0x12, 0xe7, 0x19, 0xab, 0x0c, 0x92, 0x79, 0x66, 0x95, 0x1c, 0xc9, 0x3c, 0xb3, 0x4b, 0x8a, + 0x58, 0x34, 0x90, 0xac, 0xff, 0x91, 0xa3, 0x81, 0x39, 0x05, 0x47, 0x72, 0x34, 0x30, 0xb7, 0x7c, + 0x88, 0x85, 0x32, 0xa9, 0xe2, 0x1f, 0x39, 0x94, 0x99, 0x57, 0x5d, 0x24, 0x87, 0x32, 0xf3, 0xab, + 0x87, 0x16, 0xd0, 0x21, 0xd4, 0xe4, 0x42, 0x21, 0x14, 0x8f, 0xd7, 0x92, 0x35, 0x31, 0x9d, 0x1b, + 0xf3, 0xd0, 0x32, 0x43, 0xb9, 0xc4, 0x07, 0xc5, 0xa3, 0xd4, 0x8b, 0x18, 0x66, 0x56, 0x06, 0xf1, + 0xc0, 0x25, 0x5e, 0xbc, 0x83, 0x52, 0x51, 0x6a, 0x8a, 0xed, 0xed, 0x0b, 0x28, 0xe4, 0x85, 0x4b, + 0x56, 0xeb, 0xc8, 0x0b, 0x37, 0xa7, 0x2e, 0xa8, 0xa3, 0x5c, 0x44, 0x92, 0x38, 0x12, 0x88, 0xe4, + 0x5a, 0xfc, 0x48, 0x10, 0xab, 0x3d, 0x49, 0x1c, 0x09, 0x12, 0x85, 0x1e, 0x8c, 0x4f, 0x58, 0xdb, + 0x20, 0xf3, 0x49, 0x16, 0xfd, 0xc8, 0x7c, 0xd2, 0x65, 0x39, 0x6c, 0x5d, 0xe4, 0xaa, 0x04, 0x79, + 0x5d, 0x32, 0xea, 0x75, 0xe4, 0x75, 0xc9, 0x2c, 0xa5, 0x11, 0x81, 0xbb, 0x54, 0x66, 0x10, 0x0f, + 0xdc, 0xd3, 0x45, 0x36, 0xf1, 0xc0, 0x3d, 0xab, 0xaa, 0x65, 0x01, 0xe9, 0xac, 0x9a, 0x2d, 0x95, + 0x3d, 0xfc, 0x7e, 0xc6, 0x14, 0xa5, 0x6a, 0x26, 0x3a, 0x77, 0xde, 0x40, 0x25, 0xf7, 0x92, 0x51, + 0x2e, 0x22, 0xf7, 0x32, 0xbf, 0x4e, 0x45, 0xee, 0xe5, 0xa2, 0x9a, 0x93, 0x05, 0x34, 0x0d, 0x6a, + 0xda, 0x52, 0x1d, 0xdd, 0xcd, 0x9e, 0xdb, 0x74, 0x5f, 0x9b, 0x6f, 0x26, 0x0c, 0xbb, 0x73, 0xc2, + 0x42, 0xb6, 0x74, 0xf2, 0x75, 0xce, 0xc4, 0xa7, 0x3b, 0xbc, 0x77, 0x09, 0x4a, 0x39, 0x4e, 0x88, + 0x12, 0x3a, 0xe8, 0x6a, 0x32, 0xc4, 0x97, 0x92, 0x44, 0x9d, 0x6b, 0xd9, 0xc8, 0x80, 0xd5, 0x71, + 0x89, 0xfd, 0x83, 0xa6, 0x4f, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x53, 0xb8, 0xe2, 0xaf, + 0x49, 0x00, 0x00, } diff --git a/vendor/github.com/osrg/gobgp/api/gobgp.proto b/vendor/github.com/osrg/gobgp/api/gobgp.proto index ded9487d..9bee4501 100644 --- a/vendor/github.com/osrg/gobgp/api/gobgp.proto +++ b/vendor/github.com/osrg/gobgp/api/gobgp.proto @@ -553,8 +553,6 @@ message Peer { Timers timers = 7; Transport transport = 8; RouteServer route_server = 9; - GracefulRestart graceful_restart = 10; - repeated AfiSafi afi_safis = 11; } message ApplyPolicy { @@ -588,9 +586,6 @@ message PeerConf { repeated bytes remote_cap = 11; repeated bytes local_cap = 12; string id = 13; - // Note: Regarding to the consistency with OpenConfig mode, list of - // PrefixLimit should be removed from here, and list of PrefixLimit in - // AfiSafi should be used instead. repeated PrefixLimit prefix_limits = 14; string local_address = 15; string neighbor_interface = 16; @@ -694,163 +689,6 @@ message RouteServer { bool route_server_client = 1; } -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; -} - -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 { - uint32 family = 1; - bool enabled = 2; -} - -message AfiSafiState { - uint32 family = 1; - bool enabled = 2; - uint32 total_paths = 3; - uint32 total_prefixes = 4; -} - -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; -} - -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; -} - -message RouteSelectionOptions { - RouteSelectionOptionsConfig config = 1; - RouteSelectionOptionsState state = 2; -} - -message UseMultiplePathsConfig { - bool enabled = 1; -} - -message UseMultiplePathsState { - bool enabled = 1; -} - -message EbgpConfig { - bool allow_multiple_as = 1; - uint32 maximum_paths = 2; -} - -message EbgpState { - bool allow_multiple_as = 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; - ApplyPolicy apply_policy = 3; - // TODO: - // Support the following structures: - // - Ipv4Unicast - // - Ipv6Unicast - // - Ipv4LabelledUnicast - // - Ipv6LabelledUnicast - // - L3vpnIpv4Unicast - // - L3vpnIpv6Unicast - // - L3vpnIpv4Multicast - // - L3vpnIpv6Multicast - // - L2vpnVpls - // - L2vpnEvpn - RouteSelectionOptions route_selection_options = 4; - UseMultiplePaths use_multiple_paths = 5; - PrefixLimit prefix_limits = 6; - RouteTargetMembership route_target_membership = 7; - LongLivedGracefulRestart long_lived_graceful_restart = 8; -} - message Prefix { string ip_prefix = 1; uint32 mask_length_min = 2; diff --git a/vendor/github.com/osrg/gobgp/api/grpc_server.go b/vendor/github.com/osrg/gobgp/api/grpc_server.go index cb83b132..a6306580 100644 --- a/vendor/github.com/osrg/gobgp/api/grpc_server.go +++ b/vendor/github.com/osrg/gobgp/api/grpc_server.go @@ -26,11 +26,11 @@ import ( "sync" "time" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/server" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "golang.org/x/net/context" "google.golang.org/grpc" ) @@ -88,138 +88,44 @@ func (s *Server) Serve() error { return nil } -func NewMpGracefulRestartFromConfigStruct(c *config.MpGracefulRestart) *MpGracefulRestart { - return &MpGracefulRestart{ - Config: &MpGracefulRestartConfig{ - Enabled: c.Config.Enabled, - }, - } -} - -func NewAfiSafiConfigFromConfigStruct(c *config.AfiSafiConfig) *AfiSafiConfig { - return &AfiSafiConfig{ - Family: uint32(bgp.AddressFamilyValueMap[string(c.AfiSafiName)]), - Enabled: c.Enabled, - } -} - -func NewApplyPolicyFromConfigStruct(c *config.ApplyPolicy) *ApplyPolicy { - applyPolicy := &ApplyPolicy{ - ImportPolicy: &PolicyAssignment{ - Type: PolicyType_IMPORT, - Default: RouteAction(c.Config.DefaultImportPolicy.ToInt()), - }, - ExportPolicy: &PolicyAssignment{ - Type: PolicyType_EXPORT, - Default: RouteAction(c.Config.DefaultExportPolicy.ToInt()), - }, - InPolicy: &PolicyAssignment{ - Type: PolicyType_IN, - Default: RouteAction(c.Config.DefaultInPolicy.ToInt()), - }, - } - - for _, pname := range c.Config.ImportPolicyList { - applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &Policy{Name: pname}) - } - for _, pname := range c.Config.ExportPolicyList { - applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &Policy{Name: pname}) - } - for _, pname := range c.Config.InPolicyList { - applyPolicy.InPolicy.Policies = append(applyPolicy.InPolicy.Policies, &Policy{Name: pname}) - } - - return applyPolicy -} - -func NewRouteSelectionOptionsFromConfigStruct(c *config.RouteSelectionOptions) *RouteSelectionOptions { - return &RouteSelectionOptions{ - Config: &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 NewUseMultiplePathsFromConfigStruct(c *config.UseMultiplePaths) *UseMultiplePaths { - return &UseMultiplePaths{ - Config: &UseMultiplePathsConfig{ - Enabled: c.Config.Enabled, - }, - Ebgp: &Ebgp{ - Config: &EbgpConfig{ - AllowMultipleAs: c.Ebgp.Config.AllowMultipleAs, - MaximumPaths: c.Ebgp.Config.MaximumPaths, - }, - }, - Ibgp: &Ibgp{ - Config: &IbgpConfig{ - MaximumPaths: c.Ibgp.Config.MaximumPaths, - }, - }, - } -} - -func NewPrefixLimitFromConfigStruct(c *config.AfiSafi) *PrefixLimit { - family, err := bgp.GetRouteFamily(string(c.Config.AfiSafiName)) - if err != nil || c.PrefixLimit.Config.MaxPrefixes == 0 { - return nil - } - - return &PrefixLimit{ - Family: uint32(family), - MaxPrefixes: c.PrefixLimit.Config.MaxPrefixes, - ShutdownThresholdPct: uint32(c.PrefixLimit.Config.ShutdownThresholdPct), - } -} - -func NewRouteTargetMembershipFromConfigStruct(c *config.RouteTargetMembership) *RouteTargetMembership { - return &RouteTargetMembership{ - Config: &RouteTargetMembershipConfig{ - DeferralTime: uint32(c.Config.DeferralTime), - }, - } -} - -func NewLongLivedGracefulRestartFromConfigStruct(c *config.LongLivedGracefulRestart) *LongLivedGracefulRestart { - return &LongLivedGracefulRestart{ - Config: &LongLivedGracefulRestartConfig{ - Enabled: c.Config.Enabled, - RestartTime: c.Config.RestartTime, - }, - } -} - -func NewAfiSafiFromConfigStruct(c *config.AfiSafi) *AfiSafi { - return &AfiSafi{ - MpGracefulRestart: NewMpGracefulRestartFromConfigStruct(&c.MpGracefulRestart), - Config: NewAfiSafiConfigFromConfigStruct(&c.Config), - ApplyPolicy: NewApplyPolicyFromConfigStruct(&c.ApplyPolicy), - RouteSelectionOptions: NewRouteSelectionOptionsFromConfigStruct(&c.RouteSelectionOptions), - UseMultiplePaths: NewUseMultiplePathsFromConfigStruct(&c.UseMultiplePaths), - PrefixLimits: NewPrefixLimitFromConfigStruct(c), - RouteTargetMembership: NewRouteTargetMembershipFromConfigStruct(&c.RouteTargetMembership), - LongLivedGracefulRestart: NewLongLivedGracefulRestartFromConfigStruct(&c.LongLivedGracefulRestart), - } -} - func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { - families := make([]uint32, 0, len(pconf.AfiSafis)) - prefixLimits := make([]*PrefixLimit, 0, len(pconf.AfiSafis)) - afiSafis := make([]*AfiSafi, 0, len(pconf.AfiSafis)) + var families []uint32 for _, f := range pconf.AfiSafis { if family, ok := bgp.AddressFamilyValueMap[string(f.Config.AfiSafiName)]; ok { families = append(families, uint32(family)) } - if prefixLimit := NewPrefixLimitFromConfigStruct(&f); prefixLimit != nil { - prefixLimits = append(prefixLimits, prefixLimit) - } - if afiSafi := NewAfiSafiFromConfigStruct(&f); afiSafi != nil { - afiSafis = append(afiSafis, afiSafi) + } + applyPolicy := &ApplyPolicy{} + applyPolicy.ImportPolicy = &PolicyAssignment{ + Type: PolicyType_IMPORT, + Default: RouteAction(pconf.ApplyPolicy.Config.DefaultImportPolicy.ToInt()), + } + for _, pname := range pconf.ApplyPolicy.Config.ImportPolicyList { + applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &Policy{Name: pname}) + } + applyPolicy.ExportPolicy = &PolicyAssignment{ + Type: PolicyType_EXPORT, + Default: RouteAction(pconf.ApplyPolicy.Config.DefaultExportPolicy.ToInt()), + } + for _, pname := range pconf.ApplyPolicy.Config.ExportPolicyList { + applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &Policy{Name: pname}) + } + applyPolicy.InPolicy = &PolicyAssignment{ + Type: PolicyType_IN, + Default: RouteAction(pconf.ApplyPolicy.Config.DefaultInPolicy.ToInt()), + } + for _, pname := range pconf.ApplyPolicy.Config.InPolicyList { + applyPolicy.InPolicy.Policies = append(applyPolicy.InPolicy.Policies, &Policy{Name: pname}) + } + prefixLimits := make([]*PrefixLimit, 0, len(pconf.AfiSafis)) + for _, family := range pconf.AfiSafis { + if c := family.PrefixLimit.Config; c.MaxPrefixes > 0 { + k, _ := bgp.GetRouteFamily(string(family.Config.AfiSafiName)) + prefixLimits = append(prefixLimits, &PrefixLimit{ + Family: uint32(k), + MaxPrefixes: c.MaxPrefixes, + ShutdownThresholdPct: uint32(c.ShutdownThresholdPct), + }) } } @@ -230,13 +136,13 @@ func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { localAddress = pconf.Transport.State.LocalAddress } var remoteCap, localCap [][]byte - for _, c := range pconf.State.RemoteCapabilityList { - cBuf, _ := c.Serialize() - remoteCap = append(remoteCap, cBuf) + for _, cap := range pconf.State.RemoteCapabilityList { + c, _ := cap.Serialize() + remoteCap = append(remoteCap, c) } - for _, c := range pconf.State.LocalCapabilityList { - cBuf, _ := c.Serialize() - localCap = append(localCap, cBuf) + for _, cap := range pconf.State.LocalCapabilityList { + c, _ := cap.Serialize() + localCap = append(localCap, c) } var removePrivateAs PeerConf_RemovePrivateAs switch pconf.Config.RemovePrivateAs { @@ -247,7 +153,7 @@ func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { } return &Peer{ Families: families, - ApplyPolicy: NewApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), + ApplyPolicy: applyPolicy, Conf: &PeerConf{ NeighborAddress: pconf.Config.NeighborAddress, Id: s.RemoteRouterId, @@ -291,12 +197,11 @@ func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { TOTAL: s.Messages.Sent.Total, }, }, - Received: s.AdjTable.Received, - Accepted: s.AdjTable.Accepted, - Advertised: s.AdjTable.Advertised, - PeerAs: s.PeerAs, - PeerType: uint32(s.PeerType.ToInt()), - NeighborAddress: pconf.State.NeighborAddress, + Received: s.AdjTable.Received, + Accepted: s.AdjTable.Accepted, + Advertised: s.AdjTable.Advertised, + PeerAs: s.PeerAs, + PeerType: uint32(s.PeerType.ToInt()), }, Timers: &Timers{ Config: &TimersConfig{ @@ -318,19 +223,10 @@ func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer { RouteServer: &RouteServer{ RouteServerClient: pconf.RouteServer.Config.RouteServerClient, }, - GracefulRestart: &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, - }, Transport: &Transport{ RemotePort: uint32(pconf.Transport.Config.RemotePort), LocalAddress: pconf.Transport.Config.LocalAddress, }, - AfiSafis: afiSafis, } } @@ -955,114 +851,10 @@ func (s *Server) DeleteVrf(ctx context.Context, arg *DeleteVrfRequest) (*DeleteV return &DeleteVrfResponse{}, s.bgpServer.DeleteVrf(arg.Vrf.Name) } -func ReadMpGracefulRestartFromAPIStruct(c *config.MpGracefulRestart, a *MpGracefulRestart) { - if c == nil || a == nil { - return - } - if a.Config != nil { - c.Config.Enabled = a.Config.Enabled - } -} - -func ReadAfiSafiConfigFromAPIStruct(c *config.AfiSafiConfig, a *AfiSafiConfig) { - if c == nil || a == nil { - return - } - c.Enabled = a.Enabled -} - -func ReadPrefixLimitFromAPIStruct(c *config.PrefixLimit, a *PrefixLimit) { - if c == nil || a == nil { - return - } - c.Config.MaxPrefixes = a.MaxPrefixes - c.Config.ShutdownThresholdPct = config.Percentage(a.ShutdownThresholdPct) -} - -func ReadApplyPolicyFromAPIStruct(c *config.ApplyPolicy, a *ApplyPolicy) { - if c == nil || a == nil { - return - } - if a.ImportPolicy != nil { - c.Config.DefaultImportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ImportPolicy.Default)] - for _, p := range a.ImportPolicy.Policies { - c.Config.ImportPolicyList = append(c.Config.ImportPolicyList, p.Name) - } - } - if a.ExportPolicy != nil { - c.Config.DefaultExportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ExportPolicy.Default)] - for _, p := range a.ExportPolicy.Policies { - c.Config.ExportPolicyList = append(c.Config.ExportPolicyList, p.Name) - } - } - if a.InPolicy != nil { - c.Config.DefaultInPolicy = config.IntToDefaultPolicyTypeMap[int(a.InPolicy.Default)] - for _, p := range a.InPolicy.Policies { - c.Config.InPolicyList = append(c.Config.InPolicyList, p.Name) - } - } -} - -func ReadRouteSelectionOptionsFromAPIStruct(c *config.RouteSelectionOptions, a *RouteSelectionOptions) { - if c == nil || a == nil { - return - } - if a.Config != nil { - c.Config.AlwaysCompareMed = a.Config.AlwaysCompareMed - c.Config.IgnoreAsPathLength = a.Config.IgnoreAsPathLength - c.Config.ExternalCompareRouterId = a.Config.ExternalCompareRouterId - c.Config.AdvertiseInactiveRoutes = a.Config.AdvertiseInactiveRoutes - c.Config.EnableAigp = a.Config.EnableAigp - c.Config.IgnoreNextHopIgpMetric = a.Config.IgnoreNextHopIgpMetric - } -} - -func ReadUseMultiplePathsFromAPIStruct(c *config.UseMultiplePaths, a *UseMultiplePaths) { - if c == nil || a == nil { - return - } - if a.Config != nil { - c.Config.Enabled = a.Config.Enabled - } - if a.Ebgp != nil && a.Ebgp.Config != nil { - c.Ebgp = config.Ebgp{ - Config: config.EbgpConfig{ - AllowMultipleAs: a.Ebgp.Config.AllowMultipleAs, - MaximumPaths: a.Ebgp.Config.MaximumPaths, - }, - } - } - if a.Ibgp != nil && a.Ibgp.Config != nil { - c.Ibgp = config.Ibgp{ - Config: config.IbgpConfig{ - MaximumPaths: a.Ibgp.Config.MaximumPaths, - }, - } - } -} - -func ReadRouteTargetMembershipFromAPIStruct(c *config.RouteTargetMembership, a *RouteTargetMembership) { - if c == nil || a == nil { - return - } - if a.Config != nil { - c.Config.DeferralTime = uint16(a.Config.DeferralTime) - } -} - -func ReadLongLivedGracefulRestartFromAPIStruct(c *config.LongLivedGracefulRestart, a *LongLivedGracefulRestart) { - if c == nil || a == nil { - return - } - if a.Config != nil { - c.Config.Enabled = a.Config.Enabled - c.Config.RestartTime = a.Config.RestartTime - } -} - func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { pconf := &config.Neighbor{} if a.Conf != nil { + pconf.Config.NeighborAddress = a.Conf.NeighborAddress pconf.Config.PeerAs = a.Conf.PeerAs pconf.Config.LocalAs = a.Conf.LocalAs pconf.Config.AuthPassword = a.Conf.AuthPassword @@ -1085,11 +877,11 @@ func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { f := func(bufs [][]byte) ([]bgp.ParameterCapabilityInterface, error) { var caps []bgp.ParameterCapabilityInterface for _, buf := range bufs { - c, err := bgp.DecodeCapability(buf) + cap, err := bgp.DecodeCapability(buf) if err != nil { return nil, err } - caps = append(caps, c) + caps = append(caps, cap) } return caps, nil } @@ -1107,31 +899,22 @@ func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { pconf.State.RemoteRouterId = a.Conf.Id - for _, family := range a.Families { - afiSafi := config.AfiSafi{ + for _, f := range a.Families { + family := bgp.RouteFamily(f) + pconf.AfiSafis = append(pconf.AfiSafis, config.AfiSafi{ Config: config.AfiSafiConfig{ - AfiSafiName: config.AfiSafiType(bgp.RouteFamily(family).String()), + AfiSafiName: config.AfiSafiType(family.String()), Enabled: true, }, - } - for _, pl := range a.Conf.PrefixLimits { - if family == pl.Family { - ReadPrefixLimitFromAPIStruct(&afiSafi.PrefixLimit, pl) + }) + } + for _, pl := range a.Conf.PrefixLimits { + for i, f := range pconf.AfiSafis { + if f.Config.AfiSafiName == config.AfiSafiType(bgp.RouteFamily(pl.Family).String()) { + pconf.AfiSafis[i].PrefixLimit.Config.MaxPrefixes = pl.MaxPrefixes + pconf.AfiSafis[i].PrefixLimit.Config.ShutdownThresholdPct = config.Percentage(pl.ShutdownThresholdPct) } } - for _, a := range a.AfiSafis { - if a.Config != nil && family == a.Config.Family { - ReadMpGracefulRestartFromAPIStruct(&afiSafi.MpGracefulRestart, a.MpGracefulRestart) - ReadAfiSafiConfigFromAPIStruct(&afiSafi.Config, a.Config) - ReadApplyPolicyFromAPIStruct(&afiSafi.ApplyPolicy, a.ApplyPolicy) - ReadRouteSelectionOptionsFromAPIStruct(&afiSafi.RouteSelectionOptions, a.RouteSelectionOptions) - ReadUseMultiplePathsFromAPIStruct(&afiSafi.UseMultiplePaths, a.UseMultiplePaths) - ReadPrefixLimitFromAPIStruct(&afiSafi.PrefixLimit, a.PrefixLimits) - ReadRouteTargetMembershipFromAPIStruct(&afiSafi.RouteTargetMembership, a.RouteTargetMembership) - ReadLongLivedGracefulRestartFromAPIStruct(&afiSafi.LongLivedGracefulRestart, a.LongLivedGracefulRestart) - } - } - pconf.AfiSafis = append(pconf.AfiSafis, afiSafi) } } @@ -1156,15 +939,26 @@ func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { if a.RouteServer != nil { pconf.RouteServer.Config.RouteServerClient = a.RouteServer.RouteServerClient } - if a.GracefulRestart != nil { - pconf.GracefulRestart.Config.Enabled = a.GracefulRestart.Enabled - pconf.GracefulRestart.Config.RestartTime = uint16(a.GracefulRestart.RestartTime) - pconf.GracefulRestart.Config.HelperOnly = a.GracefulRestart.HelperOnly - pconf.GracefulRestart.Config.DeferralTime = uint16(a.GracefulRestart.DeferralTime) - pconf.GracefulRestart.Config.NotificationEnabled = a.GracefulRestart.NotificationEnabled - pconf.GracefulRestart.Config.LongLivedEnabled = a.GracefulRestart.LonglivedEnabled + if a.ApplyPolicy != nil { + if a.ApplyPolicy.ImportPolicy != nil { + pconf.ApplyPolicy.Config.DefaultImportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ApplyPolicy.ImportPolicy.Default)] + for _, p := range a.ApplyPolicy.ImportPolicy.Policies { + pconf.ApplyPolicy.Config.ImportPolicyList = append(pconf.ApplyPolicy.Config.ImportPolicyList, p.Name) + } + } + if a.ApplyPolicy.ExportPolicy != nil { + pconf.ApplyPolicy.Config.DefaultExportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ApplyPolicy.ExportPolicy.Default)] + for _, p := range a.ApplyPolicy.ExportPolicy.Policies { + pconf.ApplyPolicy.Config.ExportPolicyList = append(pconf.ApplyPolicy.Config.ExportPolicyList, p.Name) + } + } + if a.ApplyPolicy.InPolicy != nil { + pconf.ApplyPolicy.Config.DefaultInPolicy = config.IntToDefaultPolicyTypeMap[int(a.ApplyPolicy.InPolicy.Default)] + for _, p := range a.ApplyPolicy.InPolicy.Policies { + pconf.ApplyPolicy.Config.InPolicyList = append(pconf.ApplyPolicy.Config.InPolicyList, p.Name) + } + } } - ReadApplyPolicyFromAPIStruct(&pconf.ApplyPolicy, a.ApplyPolicy) if a.Transport != nil { pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode @@ -1183,7 +977,6 @@ func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) { pconf.State.AdjTable.Advertised = a.Info.Advertised pconf.State.PeerAs = a.Info.PeerAs pconf.State.PeerType = config.IntToPeerTypeMap[int(a.Info.PeerType)] - pconf.State.NeighborAddress = a.Info.NeighborAddress if a.Info.Messages != nil { if a.Info.Messages.Sent != nil { diff --git a/vendor/github.com/osrg/gobgp/client/client.go b/vendor/github.com/osrg/gobgp/client/client.go index b9faf6ba..4a94ac4a 100644 --- a/vendor/github.com/osrg/gobgp/client/client.go +++ b/vendor/github.com/osrg/gobgp/client/client.go @@ -136,14 +136,14 @@ func (cli *Client) getNeighbor(name string, afi int, vrf string, enableAdvertise neighbors := make([]*config.Neighbor, 0, len(ret.Peers)) for _, p := range ret.Peers { - if name != "" && name != p.Info.NeighborAddress && name != p.Conf.NeighborInterface { + if name != "" && name != p.Conf.NeighborAddress && name != p.Conf.NeighborInterface { continue } if vrf != "" && name != p.Conf.Vrf { continue } if afi > 0 { - v6 := net.ParseIP(p.Info.NeighborAddress).To4() == nil + v6 := net.ParseIP(p.Conf.NeighborAddress).To4() == nil if afi == bgp.AFI_IP && v6 || afi == bgp.AFI_IP6 && !v6 { continue } diff --git a/vendor/github.com/osrg/gobgp/config/bgp_configs.go b/vendor/github.com/osrg/gobgp/config/bgp_configs.go index f170e97c..45515d00 100644 --- a/vendor/github.com/osrg/gobgp/config/bgp_configs.go +++ b/vendor/github.com/osrg/gobgp/config/bgp_configs.go @@ -965,54 +965,6 @@ func (v RpkiValidationResultType) Validate() error { return nil } -//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 @@ -1219,9 +1171,6 @@ type BmpServerConfig struct { RouteMonitoringPolicy BmpRouteMonitoringPolicyType `mapstructure:"route-monitoring-policy" json:"route-monitoring-policy,omitempty"` // original -> gobgp:statistics-timeout StatisticsTimeout uint16 `mapstructure:"statistics-timeout" json:"statistics-timeout,omitempty"` - // original -> gobgp:route-mirroring-enabled - //gobgp:route-mirroring-enabled's original type is boolean - RouteMirroringEnabled bool `mapstructure:"route-mirroring-enabled" json:"route-mirroring-enabled,omitempty"` } func (lhs *BmpServerConfig) Equal(rhs *BmpServerConfig) bool { @@ -1240,9 +1189,6 @@ func (lhs *BmpServerConfig) Equal(rhs *BmpServerConfig) bool { if lhs.StatisticsTimeout != rhs.StatisticsTimeout { return false } - if lhs.RouteMirroringEnabled != rhs.RouteMirroringEnabled { - return false - } return true } @@ -1565,8 +1511,6 @@ type PeerGroup struct { UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` // original -> gobgp:route-server RouteServer RouteServer `mapstructure:"route-server" json:"route-server,omitempty"` - // original -> gobgp:ttl-security - TtlSecurity TtlSecurity `mapstructure:"ttl-security" json:"ttl-security,omitempty"` } func (lhs *PeerGroup) Equal(rhs *PeerGroup) bool { @@ -1628,58 +1572,6 @@ func (lhs *PeerGroup) Equal(rhs *PeerGroup) bool { if !lhs.RouteServer.Equal(&(rhs.RouteServer)) { return false } - if !lhs.TtlSecurity.Equal(&(rhs.TtlSecurity)) { - return false - } - return true -} - -//struct for container gobgp:state -type TtlSecurityState struct { - // original -> gobgp:enabled - //gobgp:enabled's original type is boolean - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` - // original -> gobgp:ttl-min - TtlMin uint8 `mapstructure:"ttl-min" json:"ttl-min,omitempty"` -} - -//struct for container gobgp:config -type TtlSecurityConfig struct { - // original -> gobgp:enabled - //gobgp:enabled's original type is boolean - Enabled bool `mapstructure:"enabled" json:"enabled,omitempty"` - // original -> gobgp:ttl-min - 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 -type TtlSecurity struct { - // original -> gobgp:ttl-security-config - Config TtlSecurityConfig `mapstructure:"config" json:"config,omitempty"` - // original -> gobgp:ttl-security-state - 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 } @@ -2073,8 +1965,6 @@ type TransportConfig struct { // 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 uint8 `mapstructure:"ttl" json:"ttl,omitempty"` } func (lhs *TransportConfig) Equal(rhs *TransportConfig) bool { @@ -2096,9 +1986,6 @@ func (lhs *TransportConfig) Equal(rhs *TransportConfig) bool { if lhs.RemotePort != rhs.RemotePort { return false } - if lhs.Ttl != rhs.Ttl { - return false - } return true } @@ -2275,10 +2162,6 @@ type Received struct { Keepalive uint64 `mapstructure:"keepalive" json:"keepalive,omitempty"` // original -> gobgp:DYNAMIC-CAP DynamicCap uint64 `mapstructure:"dynamic-cap" json:"dynamic-cap,omitempty"` - // original -> gobgp:WITHDRAW-UPDATE - WithdrawUpdate uint32 `mapstructure:"withdraw-update" json:"withdraw-update,omitempty"` - // original -> gobgp:WITHDRAW-PREFIX - WithdrawPrefix uint32 `mapstructure:"withdraw-prefix" json:"withdraw-prefix,omitempty"` // original -> gobgp:DISCARDED Discarded uint64 `mapstructure:"discarded" json:"discarded,omitempty"` // original -> gobgp:TOTAL @@ -2307,12 +2190,6 @@ func (lhs *Received) Equal(rhs *Received) bool { 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 } @@ -2336,10 +2213,6 @@ type Sent struct { Keepalive uint64 `mapstructure:"keepalive" json:"keepalive,omitempty"` // original -> gobgp:DYNAMIC-CAP DynamicCap uint64 `mapstructure:"dynamic-cap" json:"dynamic-cap,omitempty"` - // original -> gobgp:WITHDRAW-UPDATE - WithdrawUpdate uint32 `mapstructure:"withdraw-update" json:"withdraw-update,omitempty"` - // original -> gobgp:WITHDRAW-PREFIX - WithdrawPrefix uint32 `mapstructure:"withdraw-prefix" json:"withdraw-prefix,omitempty"` // original -> gobgp:DISCARDED Discarded uint64 `mapstructure:"discarded" json:"discarded,omitempty"` // original -> gobgp:TOTAL @@ -2368,12 +2241,6 @@ func (lhs *Sent) Equal(rhs *Sent) bool { 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 } @@ -2580,8 +2447,6 @@ type Neighbor struct { UseMultiplePaths UseMultiplePaths `mapstructure:"use-multiple-paths" json:"use-multiple-paths,omitempty"` // original -> gobgp:route-server RouteServer RouteServer `mapstructure:"route-server" json:"route-server,omitempty"` - // original -> gobgp:ttl-security - TtlSecurity TtlSecurity `mapstructure:"ttl-security" json:"ttl-security,omitempty"` } func (lhs *Neighbor) Equal(rhs *Neighbor) bool { @@ -2643,9 +2508,6 @@ func (lhs *Neighbor) Equal(rhs *Neighbor) bool { if !lhs.RouteServer.Equal(&(rhs.RouteServer)) { return false } - if !lhs.TtlSecurity.Equal(&(rhs.TtlSecurity)) { - return false - } return true } @@ -3890,8 +3752,6 @@ type Bgp struct { 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 { @@ -3987,22 +3847,6 @@ func (lhs *Bgp) Equal(rhs *Bgp) bool { 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 } diff --git a/vendor/github.com/osrg/gobgp/config/default.go b/vendor/github.com/osrg/gobgp/config/default.go index 81ffe00f..7587fad8 100644 --- a/vendor/github.com/osrg/gobgp/config/default.go +++ b/vendor/github.com/osrg/gobgp/config/default.go @@ -7,7 +7,6 @@ import ( "github.com/osrg/gobgp/packet/rtr" "github.com/spf13/viper" "net" - "reflect" ) const ( @@ -16,20 +15,6 @@ const ( 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{}, 0) - } - configuredFields[addr] = n -} - func defaultAfiSafi(typ AfiSafiType, enable bool) AfiSafi { return AfiSafi{ Config: AfiSafiConfig{ @@ -130,10 +115,6 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui } } - if n.State.NeighborAddress == "" { - n.State.NeighborAddress = n.Config.NeighborAddress - } - n.State.PeerAs = n.Config.PeerAs n.AsPathOptions.State.AllowOwnAs = n.AsPathOptions.Config.AllowOwnAs @@ -158,14 +139,14 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui if err != nil { return err } - n.State.NeighborAddress = addr + n.Config.NeighborAddress = addr } if n.Transport.Config.LocalAddress == "" { - if n.State.NeighborAddress == "" { + if n.Config.NeighborAddress == "" { return fmt.Errorf("no neighbor address/interface specified") } - ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress) + ipAddr, err := net.ResolveIPAddr("ip", n.Config.NeighborAddress) if err != nil { return err } @@ -188,8 +169,8 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui 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, err := net.ResolveIPAddr("ip", n.Config.NeighborAddress); err != nil { + return fmt.Errorf("invalid neighbor address: %s", n.Config.NeighborAddress) } else if ipAddr.IP.To4() != nil { n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true)} } else { @@ -209,7 +190,6 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui if !vv.IsSet("afi-safi.config") { af.Config.Enabled = true } - af.MpGracefulRestart.State.Enabled = af.MpGracefulRestart.Config.Enabled n.AfiSafis[i] = af } } @@ -232,11 +212,6 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, asn ui n.GracefulRestart.Config.DeferralTime = uint16(360) } } - - if n.EbgpMultihop.Config.Enabled && n.TtlSecurity.Config.Enabled { - return fmt.Errorf("ebgp-multihop and ttl-security are mututally exclusive") - } - return nil } @@ -279,45 +254,6 @@ func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) return nil } -func validatePeerGroupConfig(n *Neighbor, b *BgpConfigSet) error { - name := n.Config.PeerGroup - if name == "" { - return nil - } - - pg, err := getPeerGroup(name, b) - if err != nil { - return err - } - - if pg.Config.PeerAs != 0 && n.Config.PeerAs != 0 { - return fmt.Errorf("Cannot configure remote-as for members. PeerGroup AS %d.", pg.Config.PeerAs) - } - return nil -} - -func getPeerGroup(n string, b *BgpConfigSet) (*PeerGroup, error) { - if n == "" { - return nil, fmt.Errorf("peer-group name is not configured") - } - for _, pg := range b.PeerGroups { - if n == pg.Config.PeerGroupName { - return &pg, nil - } - } - return nil, fmt.Errorf("No such peer-group: %s", n) -} - -func validateDynamicNeighborConfig(d *DynamicNeighborConfig, b *BgpConfigSet) error { - if _, err := getPeerGroup(d.PeerGroup, b); err != nil { - return err - } - if _, _, err := net.ParseCIDR(d.Prefix); err != nil { - return fmt.Errorf("Invalid Dynamic Neighbor prefix %s", d.Prefix) - } - return nil -} - func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { if v == nil { v = viper.New() @@ -357,10 +293,6 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { } for idx, n := range b.Neighbors { - if err := validatePeerGroupConfig(&n, b); err != nil { - return err - } - vv := viper.New() if len(list) > idx { vv.Set("neighbor", list[idx]) @@ -369,16 +301,6 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { return err } b.Neighbors[idx] = n - - if n.Config.PeerGroup != "" { - RegisterConfiguredFields(vv.Get("neighbor.config.neighbor-address").(string), list[idx]) - } - } - - for _, d := range b.DynamicNeighbors { - if err := validateDynamicNeighborConfig(&d.Config, b); err != nil { - return err - } } for idx, r := range b.RpkiServers { @@ -405,57 +327,3 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { return nil } - -func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error { - v := viper.New() - - val, ok := configuredFields[c.State.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 = 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/config/serve.go b/vendor/github.com/osrg/gobgp/config/serve.go index 73e2c7bb..eeb7cb4d 100644 --- a/vendor/github.com/osrg/gobgp/config/serve.go +++ b/vendor/github.com/osrg/gobgp/config/serve.go @@ -1,7 +1,7 @@ package config import ( - log "github.com/sirupsen/logrus" + log "github.com/Sirupsen/logrus" "github.com/spf13/viper" "os" "os/signal" @@ -19,7 +19,6 @@ type BgpConfigSet struct { Collector Collector `mapstructure:"collector"` DefinedSets DefinedSets `mapstructure:"defined-sets"` PolicyDefinitions []PolicyDefinition `mapstructure:"policy-definitions"` - DynamicNeighbors []DynamicNeighbor `mapstructure:"dynamic-neighbors"` } func ReadConfigfileServe(path, format string, configCh chan *BgpConfigSet) { @@ -77,16 +76,7 @@ func ReadConfigfileServe(path, format string, configCh chan *BgpConfigSet) { 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 { + if nb.Config.NeighborAddress == n.Config.NeighborAddress { return i } } @@ -100,34 +90,8 @@ func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy { } } -func UpdatePeerGroupConfig(curC, newC *BgpConfigSet) ([]PeerGroup, []PeerGroup, []PeerGroup) { - addedPg := []PeerGroup{} - deletedPg := []PeerGroup{} - updatedPg := []PeerGroup{} +func UpdateConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor, bool) { - 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]) { - log.WithFields(log.Fields{ - "Topic": "Config", - }).Debugf("Current peer-group config:%s", curC.PeerGroups[idx]) - log.WithFields(log.Fields{ - "Topic": "Config", - }).Debugf("New peer-group config:%s", 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(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor) { added := []Neighbor{} deleted := []Neighbor{} updated := []Neighbor{} @@ -151,7 +115,8 @@ func UpdateNeighborConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []N deleted = append(deleted, n) } } - return added, deleted, updated + + return added, deleted, updated, CheckPolicyDifference(ConfigSetToRoutingPolicy(curC), ConfigSetToRoutingPolicy(newC)) } func CheckPolicyDifference(currentPolicy *RoutingPolicy, newPolicy *RoutingPolicy) bool { diff --git a/vendor/github.com/osrg/gobgp/config/util.go b/vendor/github.com/osrg/gobgp/config/util.go index 8ecf56d5..36999411 100644 --- a/vendor/github.com/osrg/gobgp/config/util.go +++ b/vendor/github.com/osrg/gobgp/config/util.go @@ -140,14 +140,3 @@ func ParseMaskLength(prefix, mask string) (int, int, error) { } return min, max, nil } - -func ExtractNeighborAddress(c *Neighbor) (string, error) { - addr := c.State.NeighborAddress - if addr == "" { - addr = c.Config.NeighborAddress - if addr == "" { - return "", fmt.Errorf("NeighborAddress is not configured") - } - } - return addr, nil -} diff --git a/vendor/github.com/osrg/gobgp/docs/sources/bmp.md b/vendor/github.com/osrg/gobgp/docs/sources/bmp.md index 22f6a193..e6f6e2bb 100644 --- a/vendor/github.com/osrg/gobgp/docs/sources/bmp.md +++ b/vendor/github.com/osrg/gobgp/docs/sources/bmp.md @@ -64,17 +64,6 @@ Please note the range of this interval is 15 though 65535 seconds. statistics-timeout = 3600 ``` -To enable route mirroring feature, specify `true` for `route-mirroring-enabled` option. -Please note this option is mainly for debugging purpose. - -```toml -[[bmp-servers]] - [bmp-servers.config] - address = "127.0.0.1" - port=11019 - route-mirroring-enabled = true -``` - ## Verification Let's check if BMP works with a bmp server. GoBGP also supports BMP server (currently, just shows received BMP messages in the json format). diff --git a/vendor/github.com/osrg/gobgp/docs/sources/configuration.md b/vendor/github.com/osrg/gobgp/docs/sources/configuration.md index 71e654fb..7403834c 100644 --- a/vendor/github.com/osrg/gobgp/docs/sources/configuration.md +++ b/vendor/github.com/osrg/gobgp/docs/sources/configuration.md @@ -52,8 +52,6 @@ # override global.config.as value local-as = 1000 remove-private-as = "all" - # To enable peer group setting, uncomment the following - #peer-group = "my-peer-group" [neighbors.as-path-options.config] allow-own-as = 1 replace-peer-as = true @@ -65,7 +63,6 @@ passive-mode = true local-address = "192.168.10.1" remote-port = 2016 - ttl = 64 # default value on Linux [neighbors.ebgp-multihop.config] enabled = true multihop-ttl = 100 @@ -132,25 +129,6 @@ default-in-policy = "reject-route" [neighbors.route-server.config] route-server-client = true - # To enable TTL Security, uncomment the following. - # Please note that this feature is mututally exclusive with - # "neighbors.ebgp-multihop.config". - #[neighbors.ttl-security.config] - # enabled = true - # ttl-min = 255 # 255 means directly connected - -[[peer-groups]] - [peer-groups.config] - peer-group-name = "my-peer-group" - peer-as = 65000 - [[peer-groups.afi-safis]] - [peer-groups.afi-safis.config] - afi-safi-name = "ipv4-unicast" - -[[dynamic-neighbors]] - [dynamic-neighbors.config] - prefix = "20.0.0.0/24" - peer-group = "my-peer-group" [[defined-sets.prefix-sets]] prefix-set-name = "ps0" diff --git a/vendor/github.com/osrg/gobgp/docs/sources/getting-started.md b/vendor/github.com/osrg/gobgp/docs/sources/getting-started.md index cdd8ba83..b556592b 100644 --- a/vendor/github.com/osrg/gobgp/docs/sources/getting-started.md +++ b/vendor/github.com/osrg/gobgp/docs/sources/getting-started.md @@ -86,7 +86,7 @@ neighbors: ``` ```bash -$ sudo -E gobgpd -t yaml -f gobgpd.yml +$ sudo -E gobgpd -t yaml gobgpd.yml {"level":"info","msg":"Peer 10.0.255.1 is added","time":"2015-04-06T20:32:28+09:00"} {"level":"info","msg":"Peer 10.0.255.2 is added","time":"2015-04-06T20:32:28+09:00"} ``` diff --git a/vendor/github.com/osrg/gobgp/docs/sources/grpc-client.md b/vendor/github.com/osrg/gobgp/docs/sources/grpc-client.md index bc91c3f0..ad1bc163 100644 --- a/vendor/github.com/osrg/gobgp/docs/sources/grpc-client.md +++ b/vendor/github.com/osrg/gobgp/docs/sources/grpc-client.md @@ -3,24 +3,72 @@ This page explains how to managing GoBGP with your favorite Language. You can use any language supported by [gRPC](http://www.grpc.io/) (10 languages are supported now). This page gives an example in Python, -Ruby, C++, Node.js, and Java. It assumes that you use Ubuntu 16.04 (64bit). +Ruby, C++, Node.js, and Java. It assumes that you use Ubuntu 14.04 (64bit). ## Contents -- [Prerequisite](#prerequisite) - [Python](#python) - [Ruby](#ruby) - [C++](#cpp) - [Node.js](#nodejs) - [Java](#java) -## Prerequisite -We assumes that you have finished installing `protoc` [protocol buffer](https://github.com/google/protobuf) compiler to generate stub server and client code and "protobuf runtime" for your favorite language. - -Please refer to [the official docs of gRPC](http://www.grpc.io/docs/) for details. - ## Python +We need to install ProtocolBuffers and gRPC libraries. + +### Install ProtocolBuffers: +```bash +$ sudo apt-get update +$ sudo apt-get install -y build-essential autoconf git libtool unzip +$ mkdir ~/work +$ cd ~/work +$ wget https://github.com/google/protobuf/archive/v3.0.0-beta-1.tar.gz +$ tar xvzf v3.0.0-beta-1.tar.gz +$ cd protobuf-3.0.0-beta-1 +$ ./autogen.sh +$ ./configure +$ make +$ sudo make install +$ vi ~/.bashrc + export LD_LIBRARY_PATH=/usr/local/lib +``` + +please check the version. + ```bash + $ protoc --version + libprotoc 3.0.0 + ``` + +### Install gRPC: +```bash +$ sudo apt-get update +$ sudo apt-get install -y python-all-dev python-virtualenv +$ cd ~/work +$ git clone https://github.com/grpc/grpc.git +$ cd grpc +$ git checkout -b release-0_11_1 release-0_11_1 +$ git submodule update --init +$ make +$ sudo make install +``` + +### Install Python Libraries: + +Install python libraries for protobuf and gRPC. +Please use virtualenv if you want to keep your environment clean. +In this example we create venv directory at $HOME/venv. + +```bash +$ virtualenv ~/venv +$ source ~/venv/bin/activate +$ cd ~/work/protobuf-3.0.0-beta-1/python +$ python setup.py install +$ cd ~/work/grpc/src/python/grpcio/ +$ python setup.py install +$ deactivate +``` + ### Generating Stub Code We need to generate stub code GoBGP at first. @@ -32,23 +80,93 @@ $ protoc -I $GOBGP_API --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`wh ### Get Neighbor -['tools/grpc/python/get_neighbor.py'](https://github.com/osrg/gobgp/blob/master/tools/grpc/python/get_neighbor.py) shows an example for getting neighbor's information. +Here is an example for getting neighbor's information and we assumed that it's created in 'get_neighbor.py' under '$GOPATH/src/github.com/osrg/gobgp/tools/grpc/python'. +```python +import gobgp_pb2 +import sys + +from grpc.beta import implementations + +_TIMEOUT_SECONDS = 10 + + +def run(gobgpd_addr, neighbor_addr): + channel = implementations.insecure_channel(gobgpd_addr, 50051) + with gobgp_pb2.beta_create_GobgpApi_stub(channel) as stub: + peer = stub.GetNeighbor(gobgp_pb2.Arguments(rf=4, name=neighbor_addr), _TIMEOUT_SECONDS) + print("BGP neighbor is %s, remote AS %d" % (peer.conf.neighbor_address, peer.conf.peer_as)) + print(" BGP version 4, remote router ID %s" % (peer.conf.id)) + print(" BGP state = %s, up for %s" % (peer.info.bgp_state, peer.timers.state.uptime)) + print(" BGP OutQ = %d, Flops = %d" % (peer.info.out_q, peer.info.flops)) + print(" Hold time is %d, keepalive interval is %d seconds" % (peer.timers.state.negotiated_hold_time, peer.timers.state.keepalive_interval)) + print(" Configured hold time is %d, keepalive interval is %d seconds" % (peer.timers.config.hold_time, peer.timers.config.keepalive_interval)) + + +if __name__ == '__main__': + gobgp = sys.argv[1] + neighbor = sys.argv[2] + run(gobgp, neighbor) +``` + +We need to import gobgp_pb2 and call 'beta_create_GobgpApi_stub' in your code. + Let's run this script. ```bash -$ python get_neighbor.py 172.18.0.2 -BGP neighbor is 10.0.0.2, remote AS 65002 - BGP version 4, remote router ID - BGP state = active, up for 0 +$ source ~/venv/bin/activate +(venv)$ python get_neighbor.py 10.0.255.1 10.0.0.1 +BGP neighbor is 10.0.0.1, remote AS 65001 + BGP version 4, remote router ID 192.168.0.1 + BGP state = BGP_FSM_ESTABLISHED, up for 9042 BGP OutQ = 0, Flops = 0 - Hold time is 0, keepalive interval is 0 seconds - Configured hold time is 90, keepalive interval is 30 seconds + Hold time is 30, keepalive interval is 10 seconds + Configured hold time is 30, keepalive interval is 10 seconds + ``` We got the neighbor information successfully. ## Ruby +### Install ProtoBuffers: + +```bash +$ sudo apt-get update +$ sudo apt-get install -y build-essential curl git m4 ruby autoconf libtool unzip +$ mkdir ~/work +$ cd ~/work +$ wget https://github.com/google/protobuf/archive/v3.0.0-beta-1.tar.gz +$ tar xvzf v3.0.0-beta-1.tar.gz +$ cd protobuf-3.0.0-beta-1 +$ ./autogen.sh +$ ./configure +$ make +$ sudo make install +$ vi ~/.bashrc + export LD_LIBRARY_PATH=/usr/local/lib +``` + +### Installing gRPC and Ruby Libraries + +```bash +$ command curl -sSL https://rvm.io/mpapis.asc | gpg --import - +$ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2 +$ source $HOME/.rvm/scripts/rvm +$ rvm install 2.1 +$ gem install bundler +$ cd ~/work/ +$ git clone https://github.com/grpc/grpc.git +$ cd grpc +$ git checkout -b release-0_11_1 release-0_11_1 +$ git submodule update --init +$ $ make +$ $ sudo make install +$ cd src/ruby/ +$ gem build grpc.gemspec +$ bundle install +$ gem install -l grpc-0.11.0.gem +``` + ### Generating Stub Code We need to generate stub code GoBGP at first. @@ -60,67 +178,195 @@ $ protoc -I $GOBGP_API --ruby_out=. --grpc_out=. --plugin=protoc-gen-grpc=`whic ### Get Neighbor -['tools/grpc/ruby/get_neighbor.py'](https://github.com/osrg/gobgp/blob/master/tools/grpc/ruby/get_neighbor.rb) shows an example for getting neighbor's information. +Here is an example for getting neighbor's information. +```ruby +require 'gobgp' +require 'gobgp_services' + +host = 'localhost' +host = ARGV[0] if ARGV.length > 0 + +stub = Gobgpapi::GobgpApi::Stub.new("#{host}:50051") +arg = Gobgpapi::Arguments.new() +stub.get_neighbors(arg).each do |n| + puts "BGP neighbor is #{n.conf.neighbor_address}, remote AS #{n.conf.peer_as}" + puts "\tBGP version 4, remote route ID #{n.conf.id}" + puts "\tBGP state = #{n.info.bgp_state}, up for #{n.timers.state.uptime}" + puts "\tBGP OutQ = #{n.info.out_q}, Flops = #{n.info.flops}" + puts "\tHold time is #{n.timers.state.hold_time}, keepalive interval is #{n.timers.state.keepalive_interval} seconds" + puts "\tConfigured hold time is #{n.timers.config.hold_time}" +end +``` + Let's run this script. ```bash -$ ruby -I . ./get_neighbors.rb 172.18.0.2 -BGP neighbor is 10.0.0.2, remote AS 65002 - BGP version 4, remote route ID - BGP state = active, up for 0 - BGP OutQ = 0, Flops = 0 - Hold time is 0, keepalive interval is 0 seconds - Configured hold time is 90 +$ruby -I . ./get_neighbors.rb +BGP neighbor is 192.168.10.2, remote AS 65001 + BGP version 4, remote route ID + BGP state = BGP_FSM_ACTIVE, up for 0 + BGP OutQ = 0, Flops = 0 + Hold time is 0, keepalive interval is 0 seconds + Configured hold time is 90 +BGP neighbor is 192.168.10.3, remote AS 65001 + BGP version 4, remote route ID + BGP state = BGP_FSM_ACTIVE, up for 0 + BGP OutQ = 0, Flops = 0 + Hold time is 0, keepalive interval is 0 seconds + Configured hold time is 90 ``` ## C++ +For gRPC we need so much dependencies, please make coffee and be ready! + +### Install ProtoBuffers: +```bash +apt-get update +apt-get install -y gcc make autoconf automake git libtool g++ curl + +cd /usr/src +wget https://github.com/google/protobuf/archive/v3.0.0-alpha-4.tar.gz +tar -xf v3.0.0-alpha-4.tar.gz +cd protobuf-3.0.0-alpha-4/ +./autogen.sh +./configure --prefix=/opt/protobuf_3.0.0_alpha4 +make -j 4 +make install +``` + +### Install gRPC: +```bash +apt-get update +apt-get install -y gcc make autoconf automake git libtool g++ python-all-dev python-virtualenv + +cd /usr/src/ +git clone https://github.com/grpc/grpc.git +cd grpc +# We are using specific commit because gRPC is under heavy development right now +git checkout e5cdbea1530a99a95fd3d032e7d69a19c61a0d16 +git submodule update --init +make -j 4 +make install prefix=/opt/grpc +``` + We use .so compilation with golang, please use only 1.5 or newer version of Go Lang. -['tools/grpc/cpp/gobgp_api_client.cc'](https://github.com/osrg/gobgp/blob/master/tools/grpc/cpp/gobgp_api_client.cc) shows an example for getting neighbor's information. - -We provide ['tools/grpc/cpp/build.sh'](https://github.com/osrg/gobgp/blob/master/tools/grpc/cpp/build.sh) to build this sample code. -This script also generates stub codes and builds GoBGP shared library. - -Let's build the sample code: +Clone this repository and build API example: ```bash -$ cd $GOPATH/src/github.com/osrg/gobgp/tools/grpc/cpp -$ bash build.sh +export PATH="$PATH:/opt//grpc/bin:/opt/protobuf_3.0.0_alpha4/bin/" + +cd /usr/src +git clone https://github.com/osrg/gobgp.git +cd gobgp/gobgp/lib +go build -buildmode=c-shared -o libgobgp.so *.go +cp libgobgp.h /usr/src/gobgp/tools/grpc/cpp +cp libgobgp.so /usr/src/gobgp/tools/grpc/cpp +cp /usr/src/gobgp/api/gobgp.proto /usr/src/gobgp/tools/grpc/cpp/gobgp_api_client.proto +cd /usr/src/gobgp/tools/grpc/cpp +make ``` ### Let's run it: ```bash -$ ./gobgp_api_client 172.18.0.2 -BGP neighbor is: 10.0.0.2, remote AS: 1 - BGP version: 4, remote route ID - BGP state = active, up for 0 - BGP OutQ = 0, Flops = 0 - Hold time is 0, keepalive interval is 0seconds - Configured hold time is 90 -BGP neighbor is: 10.0.0.3, remote AS: 1 - BGP version: 4, remote route ID - BGP state = active, up for 0 - BGP OutQ = 0, Flops = 0 - Hold time is 0, keepalive interval is 0seconds - Configured hold time is 90 +LD_LIBRARY_PATH=".:/opt/grpc/lib:/opt/protobuf_3.0.0_alpha4/lib" ./gobgp_api_client + +List of announced prefixes for route family: 65537 + +Prefix: 10.10.20.0/22 +NLRI: {"nlri":{"prefix":"10.10.20.0/22"},"attrs":[{"type":1,"value":0},{"type":3,"nexthop":"0.0.0.0"}]} + + +List of announced prefixes for route family: 65669 + +Prefix: [destination:10.0.0.0/24][protocol: tcp][source:20.0.0.0/24] +NLRI: {"nlri":{"value":[{"type":1,"value":{"prefix":"10.0.0.0/24"}},{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"20.0.0.0/24"}}]},"attrs":[{"type":1,"value":0},{"type":14,"nexthop":"0.0.0.0","afi":1,"safi":133,"value":[{"value":[{"type":1,"value":{"prefix":"10.0.0.0/24"}},{"type":3,"value":[{"op":129,"value":6}]},{"type":2,"value":{"prefix":"20.0.0.0/24"}}]}]},{"type":16,"value":[{"type":128,"subtype":8,"value":"10:10"}]}]} ``` ## Node.js +Build from source code because there is no official gRPC package for Ubuntu 14.04. +(Debian Linux and Mac OSX are much easier. See [the document](https://github.com/grpc/grpc/tree/release-0_11/src/node)) + + +### Install Protocol Buffers: + +Install protobuf v3.0.0-beta before gRPC. gRPC installation process will try to do it automatically but fail. (Probably because it tries another version of protobuf) + +See [installation document](https://github.com/grpc/grpc/blob/master/INSTALL). + +```bash +$ [sudo] apt-get install unzip autoconf libtool build-essential + +$ wget https://github.com/google/protobuf/archive/v3.0.0-beta-4.tar.gz +$ tar zxvf v3.0.0-beta-4.tar.gz +$ cd protobuf-3.0.0-beta-4/ +$ ./autogen.sh +$ ./configure +$ make +$ [sudo] make install +``` + +### Install gRPC: + +```bash +$ [sudo] apt-get install git + +$ git clone https://github.com/grpc/grpc.git +$ cd grpc +$ git submodule update --init +$ make +$ [sudo] make install +``` + +### Install Node.js gRPC library: + +Let's say Node.js is already installed, + +```bash +npm install grpc +``` + ### Example Copy protocol definition. ```bash -$ cd $GOPATH/src/github.com/osrg/gobgp/tools/grpc/nodejs -$ ln -s $GOPATH/src/github.com/osrg/gobgp/api/gobgp.proto +cp $GOPATH/src/github.com/osrg/gobgp/api/gobgp.proto . +``` + +Here is an example to show neighbor information. + +```javascript +var grpc = require('grpc'); +var api = grpc.load('gobgp.proto').gobgpapi; +var stub = new api.GobgpApi('localhost:50051', grpc.credentials.createInsecure()); + +stub.getNeighbor({}, function(err, neighbor) { + neighbor.peers.forEach(function(peer) { + if(peer.info.bgp_state == 'BGP_FSM_ESTABLISHED') { + var date = new Date(Number(peer.timers.state.uptime)*1000); + var holdtime = peer.timers.state.negotiated_hold_time; + var keepalive = peer.timers.state.keepalive_interval; + } + + console.log('BGP neighbor:', peer.conf.neighbor_address, + ', remote AS:', peer.conf.peer_as); + console.log("\tBGP version 4, remote router ID:", peer.conf.id); + console.log("\tBGP state:", peer.info.bgp_state, + ', uptime:', date); + console.log("\tBGP OutQ:", peer.info.out_q, + ', Flops:', peer.info.flops); + console.log("\tHold time:", holdtime, + ', keepalive interval:', keepalive, 'seconds'); + console.log("\tConfigured hold time:", peer.timers.config.hold_time); + }); +}); ``` -['tools/grpc/nodejs/get_neighbor.js'](https://github.com/osrg/gobgp/blob/master/tools/grpc/nodejs/get_neighbors.js) shows an example to show neighbor information. Let's run this: ``` -$ node get_neighbors.js BGP neighbor: 10.0.255.1 , remote AS: 65001 BGP version 4, remote router ID: 10.0.255.1 BGP state: BGP_FSM_ESTABLISHED , uptime: Wed Jul 20 2016 05:37:22 GMT+0900 (JST) @@ -136,13 +382,7 @@ BGP neighbor: 10.0.255.2 , remote AS: 65002 ``` ## Java - -At the time of this writing, versions of each plugins and tools are as following: -* ProtocolBuffer: 3.3.0 -* grpc-java: 1.4.0 -* java: 1.8.0_131 - -In proceeding with the following procedure, please substitute versions to the latest. +We can make a client in Java using [grpc-java](https://github.com/grpc/grpc-java). ### Install JDK: We need to install JDK and we use Oracle JDK8 in this example. @@ -151,18 +391,41 @@ $ sudo add-apt-repository ppa:webupd8team/java $ sudo apt-get update $ sudo apt-get install oracle-java8-installer $ java -version -java version "1.8.0_131" -Java(TM) SE Runtime Environment (build 1.8.0_131-b11) -Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode) +java version "1.8.0_72" +Java(TM) SE Runtime Environment (build 1.8.0_72-b15) +Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode) $ echo "export JAVA_HOME=/usr/lib/jvm/java-8-oracle" >> ~/.bashrc $ source ~/.bashrc ``` + +### Install ProtocolBuffers: +We use v3.0.0 beta2. +```bash +$ sudo apt-get install -y build-essential autoconf git libtool unzip +$ mkdir ~/work +$ cd ~/work +$ wget https://github.com/google/protobuf/archive/v3.0.0-beta-2.tar.gz +$ tar xvzf v3.0.0-beta-2.tar.gz +$ cd protobuf-3.0.0-beta-2 +$ ./autogen.sh +$ ./configure +$ make +$ sudo make install +$ echo "export LD_LIBRARY_PATH=/usr/local/lib" >> ~/.bashrc +$ source ~/.bashrc +``` + +Please check the version. + ```bash + $ protoc --version + libprotoc 3.0.0 + ``` + ### Create protobuf library for Java: -We assume you've cloned gRPC repository in your home directory. ```bash $ sudo apt-get install maven -$ cd ~/grpc/third_party/protobuf/java +$ cd ~/work/protobuf-3.0.0-beta-2/java $ mvn package ... [INFO] @@ -174,20 +437,22 @@ $ mvn package [INFO] Finished at: Mon Feb 08 11:51:51 JST 2016 [INFO] Final Memory: 31M/228M [INFO] ------------------------------------------------------------------------ -$ ls ./core/target/proto* -./core/target/protobuf-java-3.3.0.jar +$ ls ./target/proto* +./target/protobuf-java-3.0.0-beta-2.jar ``` -### Clone grpc-java and get plugins +### Clone grpc-java and build protoc plugin and other dependencies: ```bash $ cd ~/work $ git clone https://github.com/grpc/grpc-java.git $ cd ./grpc-java -$ git checkout -b v1.4.0 v1.4.0 +$ git checkout -b v0.12.0 v0.12.0 $ cd ./all $ ../gradlew build $ ls ../compiler/build/binaries/java_pluginExecutable/ protoc-gen-grpc-java +$ ls ./build/libs/grpc-all-0.12.0* +./build/libs/grpc-all-0.12.0-javadoc.jar ./build/libs/grpc-all-0.12.0-sources.jar ./build/libs/grpc-all-0.12.0.jar ``` ### Generate stub classes: @@ -197,50 +462,94 @@ $ mkdir -p java/src $ cd java $ GOBGP_API=$GOPATH/src/github.com/osrg/gobgp/api $ protoc --java_out=./src --proto_path="$GOBGP_API" $GOBGP_API/gobgp.proto -$ protoc --plugin=protoc-gen-grpc-java=$HOME/work/grpc-java/compiler/build/exe/java_plugin/protoc-gen-grpc-java --grpc-java_out=./src --proto_path="$GOBGP_API" $GOBGP_API/gobgp.proto +$ protoc --plugin=protoc-gen-grpc-java=$HOME/work/grpc-java/compiler/build/binaries/java_pluginExecutable/protoc-gen-grpc-java --grpc-java_out=./src --proto_path="$GOBGP_API" $GOBGP_API/gobgp.proto $ ls ./src/gobgpapi/ Gobgp.java GobgpApiGrpc.java ``` -### Build sample client: +### Create your own client and build it: +```bash +$ cd ~/go/src/github.com/osrg/gobgp/tools/grpc/java +$ mkdir -p src/gobgp/example +$ cd src/gobgp/example +$ vi GobgpSampleClient.java +``` -['tools/grpc/java/src/gobgp/example/GobgpSampleClient.java'](https://github.com/osrg/gobgp/blob/master/tools/grpc/java/src/gobgp/example/GobgpSampleClient.java) is an example to show neighbor information. +```java +package gobgp.example; + +import gobgpapi.Gobgp; +import gobgpapi.GobgpApiGrpc; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; + +import java.util.Iterator; + +public class GobgpSampleClient { + + private final GobgpApiGrpc.GobgpApiBlockingStub blockingStub; + + public GobgpSampleClient(String host, int port) { + ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build(); + this.blockingStub = GobgpApiGrpc.newBlockingStub(channel); + } + + public void getNeighbors(){ + + Gobgp.Arguments request = Gobgp.Arguments.newBuilder().build(); + + for(Iterator iterator = this.blockingStub.getNeighbors(request); iterator.hasNext(); ) { + Gobgp.Peer p = iterator.next(); + Gobgp.PeerConf conf = p.getConf(); + Gobgp.PeerState state = p.getInfo(); + Gobgp.Timers timer = p.getTimers(); + + System.out.printf("BGP neighbor is %s, remote AS %d\n", conf.getNeighborAddress(), conf.getPeerAs()); + System.out.printf("\tBGP version 4, remote router ID %s\n", conf.getId()); + System.out.printf("\tBGP state = %s, up for %d\n", state.getBgpState(), timer.getState().getUptime()); + System.out.printf("\tBGP OutQ = %d, Flops = %d\n", state.getOutQ(), state.getFlops()); + System.out.printf("\tHold time is %d, keepalive interval is %d seconds\n", + timer.getState().getHoldTime(), timer.getState().getKeepaliveInterval()); + System.out.printf("\tConfigured hold time is %d\n", timer.getConfig().getHoldTime()); + + } + } + + public static void main(String args[]){ + new GobgpSampleClient(args[0], 8080).getNeighbors(); + } + +} + +``` Let's build and run it. However we need to download and copy some dependencies beforehand. ```bash $ cd $GOPATH/src/github.com/osrg/gobgp/tools/grpc/java $ mkdir lib $ cd lib -$ wget http://central.maven.org/maven2/com/google/guava/guava/22.0/guava-22.0.jar -$ wget http://central.maven.org/maven2/com/squareup/okhttp/okhttp/2.5.0/okhttp-2.7.5.jar -$ wget http://central.maven.org/maven2/com/squareup/okio/okio/1.13.0/okio-1.13.0.jar -$ wget http://central.maven.org/maven2/com/google/instrumentation/instrumentation-api/0.4.3/instrumentation-api-0.4.3.jar -$ cp ~/grpc/third_party/protobuf/java/core/target/protobuf-java-3.3.0.jar ./ -$ cp ~/work/grpc-java/stub/build/libs/grpc-stub-1.4.0.jar ./ -$ cp ~/work/grpc-java/core/build/libs/grpc-core-1.4.0.jar ./ -$ cp ~/work/grpc-java/protobuf/build/libs/grpc-protobuf-1.4.0.jar ./ -$ cp ~/work/grpc-java/protobuf-lite/build/libs/grpc-protobuf-lite-1.4.0.jar ./ -$ cp ~/work/grpc-java/context/build/libs/grpc-context-1.4.0.jar ./ -$ cp ~/work/grpc-java/okhttp/build/libs/grpc-okhttp-1.4.0.jar ./ +$ wget http://central.maven.org/maven2/com/google/guava/guava/18.0/guava-18.0.jar +$ wget http://central.maven.org/maven2/com/squareup/okhttp/okhttp/2.5.0/okhttp-2.5.0.jar +$ wget http://central.maven.org/maven2/com/squareup/okio/okio/1.6.0/okio-1.6.0.jar +$ cp ~/work/protobuf-3.0.0-beta-2/java/target/protobuf-java-3.0.0-beta-2.jar ./ +$ cp ~/work/grpc-java/all/build/libs/grpc-all-0.12.0.jar ./ ``` We are ready to build and run. ```bash $ cd $GOPATH/src/github.com/osrg/gobgp/tools/grpc/java $ mkdir classes -$ CLASSPATH=./lib/protobuf-java-3.3.0.jar:./lib/guava-22.0.jar:./lib/grpc-okhttp-1.4.0.jar:./lib/okio-1.13.0.jar:./lib/grpc-stub-1.4.0.jar:./lib/grpc-core-1.4.0.jar:./lib/grpc-protobuf-1.4.0.jar:./lib/okhttp-2.7.5.jar:./lib/instrumentation-api-0.4.3.jar:./lib/grpc-context-1.4.0.jar:./lib/grpc-protobuf-lite-1.4.0.jar:./classes/ +$ CLASSPATH=./lib/protobuf-java-3.0.0-beta-2.jar:./lib/grpc-all-0.12.0.jar:./lib/guava-18.0.jar:./lib/okhttp-2.5.0.jar:./lib/okio-1.6.0.jar:./classes $ javac -classpath $CLASSPATH -d ./classes ./src/gobgpapi/*.java $ javac -classpath $CLASSPATH -d ./classes ./src/gobgp/example/GobgpSampleClient.java $ java -cp $CLASSPATH gobgp.example.GobgpSampleClient localhost -BGP neighbor is 10.0.0.2, remote AS 1 - BGP version 4, remote router ID - BGP state = active, up for 0 - BGP OutQ = 0, Flops = 0 - Hold time is 0, keepalive interval is 0 seconds - Configured hold time is 90 -BGP neighbor is 10.0.0.3, remote AS 1 - BGP version 4, remote router ID - BGP state = active, up for 0 +Feb 08, 2016 2:39:29 PM io.grpc.internal.TransportSet$1 run +INFO: Created transport io.grpc.okhttp.OkHttpClientTransport@ba4d54(localhost/127.0.0.1:8080) for localhost/127.0.0.1:8080 +Feb 08, 2016 2:39:29 PM io.grpc.internal.TransportSet$TransportListener transportReady +INFO: Transport io.grpc.okhttp.OkHttpClientTransport@ba4d54(localhost/127.0.0.1:8080) for localhost/127.0.0.1:8080 is ready +BGP neighbor is 10.0.255.1, remote AS 65001 + BGP version 4, remote router ID + BGP state = BGP_FSM_ACTIVE, up for 0 BGP OutQ = 0, Flops = 0 Hold time is 0, keepalive interval is 0 seconds Configured hold time is 90 diff --git a/vendor/github.com/osrg/gobgp/docs/sources/lib.md b/vendor/github.com/osrg/gobgp/docs/sources/lib.md index 0e5b7e9f..e6bbd958 100644 --- a/vendor/github.com/osrg/gobgp/docs/sources/lib.md +++ b/vendor/github.com/osrg/gobgp/docs/sources/lib.md @@ -12,7 +12,7 @@ package main import ( "fmt" - log "github.com/sirupsen/logrus" + log "github.com/Sirupsen/logrus" api "github.com/osrg/gobgp/api" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" diff --git a/vendor/github.com/osrg/gobgp/gobgp/cmd/common.go b/vendor/github.com/osrg/gobgp/gobgp/cmd/common.go index 124c2b99..a104c567 100644 --- a/vendor/github.com/osrg/gobgp/gobgp/cmd/common.go +++ b/vendor/github.com/osrg/gobgp/gobgp/cmd/common.go @@ -178,8 +178,8 @@ func (n neighbors) Swap(i, j int) { } func (n neighbors) Less(i, j int) bool { - p1 := n[i].State.NeighborAddress - p2 := n[j].State.NeighborAddress + p1 := n[i].Config.NeighborAddress + p2 := n[j].Config.NeighborAddress p1Isv4 := !strings.Contains(p1, ":") p2Isv4 := !strings.Contains(p2, ":") if p1Isv4 != p2Isv4 { diff --git a/vendor/github.com/osrg/gobgp/gobgp/cmd/monitor.go b/vendor/github.com/osrg/gobgp/gobgp/cmd/monitor.go index 9d2d841f..661b6c24 100644 --- a/vendor/github.com/osrg/gobgp/gobgp/cmd/monitor.go +++ b/vendor/github.com/osrg/gobgp/gobgp/cmd/monitor.go @@ -89,7 +89,7 @@ func NewMonitorCmd() *cobra.Command { j, _ := json.Marshal(s) fmt.Println(string(j)) } else { - addr := s.State.NeighborAddress + addr := s.Config.NeighborAddress if s.Config.NeighborInterface != "" { addr = fmt.Sprintf("%s(%s)", addr, s.Config.NeighborInterface) } diff --git a/vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go b/vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go index f89e801f..680c51fa 100644 --- a/vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go +++ b/vendor/github.com/osrg/gobgp/gobgp/cmd/mrt.go @@ -80,8 +80,6 @@ func injectMrt(filename string, count int, skip int, onlyBest bool) error { peers = msg.Body.(*mrt.PeerIndexTable).Peers continue case mrt.RIB_IPV4_UNICAST, mrt.RIB_IPV6_UNICAST: - case mrt.GEO_PEER_TABLE: - fmt.Printf("WARNING: Skipping GEO_PEER_TABLE: %s", msg.Body.(*mrt.GeoPeerTable)) default: exitWithError(fmt.Errorf("unsupported subType: %v", subType)) } diff --git a/vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go b/vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go index ffd835fc..261e3d58 100644 --- a/vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go +++ b/vendor/github.com/osrg/gobgp/gobgp/cmd/neighbor.go @@ -77,7 +77,7 @@ func showNeighbors(vrf string) error { if globalOpts.Quiet { for _, p := range m { - fmt.Println(p.State.NeighborAddress) + fmt.Println(p.Config.NeighborAddress) } return nil } @@ -92,7 +92,7 @@ func showNeighbors(vrf string) error { for _, n := range m { if i := len(n.Config.NeighborInterface); i > maxaddrlen { maxaddrlen = i - } else if j := len(n.State.NeighborAddress); j > maxaddrlen { + } else if j := len(n.Config.NeighborAddress); j > maxaddrlen { maxaddrlen = j } if l := len(getASN(n)); l > maxaslen { @@ -142,7 +142,7 @@ func showNeighbors(vrf string) error { } for i, n := range m { - neigh := n.State.NeighborAddress + neigh := n.Config.NeighborAddress if n.Config.NeighborInterface != "" { neigh = n.Config.NeighborInterface } @@ -163,7 +163,7 @@ func showNeighbor(args []string) error { return nil } - fmt.Printf("BGP neighbor is %s, remote AS %s", p.State.NeighborAddress, getASN(p)) + fmt.Printf("BGP neighbor is %s, remote AS %s", p.Config.NeighborAddress, getASN(p)) if p.RouteReflector.Config.RouteReflectorClient { fmt.Printf(", route-reflector-client\n") @@ -854,7 +854,6 @@ func modNeighbor(cmdType string, args []string) error { peer.Config.NeighborInterface = m["interface"][0] } else { peer.Config.NeighborAddress = m[""][0] - peer.State.NeighborAddress = m[""][0] } if len(m["vrf"]) == 1 { peer.Config.Vrf = m["vrf"][0] @@ -953,7 +952,7 @@ func NewNeighborCmd() *cobra.Command { if err != nil { exitWithError(err) } - addr = peer.State.NeighborAddress + addr = peer.Config.NeighborAddress } err := f(cmd.Use, addr, args[:len(args)-1]) if err != nil { @@ -984,7 +983,7 @@ func NewNeighborCmd() *cobra.Command { if err != nil { exitWithError(err) } - remoteIP := peer.State.NeighborAddress + remoteIP := peer.Config.NeighborAddress for _, v := range []string{CMD_IN, CMD_IMPORT, CMD_EXPORT} { if err := showNeighborPolicy(remoteIP, v, 4); err != nil { exitWithError(err) @@ -1001,7 +1000,7 @@ func NewNeighborCmd() *cobra.Command { if err != nil { exitWithError(err) } - remoteIP := peer.State.NeighborAddress + remoteIP := peer.Config.NeighborAddress err = showNeighborPolicy(remoteIP, cmd.Use, 0) if err != nil { exitWithError(err) @@ -1017,7 +1016,7 @@ func NewNeighborCmd() *cobra.Command { if err != nil { exitWithError(err) } - remoteIP := peer.State.NeighborAddress + remoteIP := peer.Config.NeighborAddress args = args[:len(args)-1] if err = modNeighborPolicy(remoteIP, cmd.Use, subcmd.Use, args); err != nil { exitWithError(err) diff --git a/vendor/github.com/osrg/gobgp/gobgpd/main.go b/vendor/github.com/osrg/gobgp/gobgpd/main.go index caf1793f..91e98f6c 100644 --- a/vendor/github.com/osrg/gobgp/gobgpd/main.go +++ b/vendor/github.com/osrg/gobgp/gobgpd/main.go @@ -24,6 +24,7 @@ import ( "runtime" "syscall" + log "github.com/Sirupsen/logrus" "github.com/jessevdk/go-flags" p "github.com/kr/pretty" api "github.com/osrg/gobgp/api" @@ -31,7 +32,6 @@ import ( "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/server" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) @@ -149,7 +149,6 @@ func main() { select { case newConfig := <-configCh: var added, deleted, updated []config.Neighbor - var addedPg, deletedPg, updatedPg []config.PeerGroup var updatePolicy bool if c == nil { @@ -191,7 +190,6 @@ func main() { } added = newConfig.Neighbors - addedPg = newConfig.PeerGroups if opts.GracefulRestart { for i, n := range added { if n.GracefulRestart.Config.Enabled { @@ -201,10 +199,7 @@ func main() { } } else { - addedPg, deletedPg, updatedPg = config.UpdatePeerGroupConfig(c, newConfig) - added, deleted, updated = config.UpdateNeighborConfig(c, newConfig) - updatePolicy = config.CheckPolicyDifference(config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig)) - + added, deleted, updated, updatePolicy = config.UpdateConfig(c, newConfig) if updatePolicy { log.Info("Policy config is updated") p := config.ConfigSetToRoutingPolicy(newConfig) @@ -246,46 +241,21 @@ func main() { } c = newConfig } - for i, pg := range addedPg { - log.Infof("PeerGroup %s is added", pg.Config.PeerGroupName) - if err := bgpServer.AddPeerGroup(&addedPg[i]); err != nil { - log.Warn(err) - } - } - for i, pg := range deletedPg { - log.Infof("PeerGroup %s is deleted", pg.Config.PeerGroupName) - if err := bgpServer.DeletePeerGroup(&deletedPg[i]); err != nil { - log.Warn(err) - } - } - for i, pg := range updatedPg { - log.Infof("PeerGroup %s is updated", pg.Config.PeerGroupName) - u, err := bgpServer.UpdatePeerGroup(&updatedPg[i]) - if err != nil { - log.Warn(err) - } - updatePolicy = updatePolicy || u - } - for _, dn := range newConfig.DynamicNeighbors { - log.Infof("Dynamic Neighbor %s is added to PeerGroup %s", dn.Config.Prefix, dn.Config.PeerGroup) - if err := bgpServer.AddDynamicNeighbor(&dn); err != nil { - log.Warn(err) - } - } + for i, p := range added { - log.Infof("Peer %v is added", p.State.NeighborAddress) + log.Infof("Peer %v is added", p.Config.NeighborAddress) if err := bgpServer.AddNeighbor(&added[i]); err != nil { log.Warn(err) } } for i, p := range deleted { - log.Infof("Peer %v is deleted", p.State.NeighborAddress) + log.Infof("Peer %v is deleted", p.Config.NeighborAddress) if err := bgpServer.DeleteNeighbor(&deleted[i]); err != nil { log.Warn(err) } } for i, p := range updated { - log.Infof("Peer %v is updated", p.State.NeighborAddress) + log.Infof("Peer %v is updated", p.Config.NeighborAddress) u, err := bgpServer.UpdateNeighbor(&updated[i]) if err != nil { log.Warn(err) diff --git a/vendor/github.com/osrg/gobgp/gobgpd/util.go b/vendor/github.com/osrg/gobgp/gobgpd/util.go index 25e9b888..577363d3 100644 --- a/vendor/github.com/osrg/gobgp/gobgpd/util.go +++ b/vendor/github.com/osrg/gobgp/gobgpd/util.go @@ -26,8 +26,8 @@ import ( "strings" "syscall" - log "github.com/sirupsen/logrus" - "github.com/sirupsen/logrus/hooks/syslog" + log "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus/hooks/syslog" ) func init() { diff --git a/vendor/github.com/osrg/gobgp/gobmpd/main.go b/vendor/github.com/osrg/gobgp/gobmpd/main.go index f875f847..a91d3752 100644 --- a/vendor/github.com/osrg/gobgp/gobmpd/main.go +++ b/vendor/github.com/osrg/gobgp/gobmpd/main.go @@ -19,8 +19,8 @@ import ( "bufio" "encoding/json" "fmt" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bmp" - log "github.com/sirupsen/logrus" "net" "os" "strconv" diff --git a/vendor/github.com/osrg/gobgp/packet/bgp/bgp.go b/vendor/github.com/osrg/gobgp/packet/bgp/bgp.go index a32ce069..034a2bcb 100644 --- a/vendor/github.com/osrg/gobgp/packet/bgp/bgp.go +++ b/vendor/github.com/osrg/gobgp/packet/bgp/bgp.go @@ -590,31 +590,10 @@ func (m BGPAddPathMode) String() string { } } -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 + RouteFamily RouteFamily + Mode BGPAddPathMode } func (c *CapAddPath) DecodeFromBytes(data []byte) error { @@ -623,46 +602,40 @@ func (c *CapAddPath) DecodeFromBytes(data []byte) error { if len(data) < 4 { return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_CAPABILITY, nil, "Not all CapabilityAddPath bytes available") } - c.Tuples = []*CapAddPathTuple{} - for len(data) >= 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:] - } + c.RouteFamily = AfiSafiToRouteFamily(binary.BigEndian.Uint16(data[:2]), data[2]) + c.Mode = BGPAddPathMode(data[3]) 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) - } + buf := make([]byte, 4) + afi, safi := RouteFamilyToAfiSafi(c.RouteFamily) + binary.BigEndian.PutUint16(buf, afi) + buf[2] = safi + buf[3] = byte(c.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 BGPCapabilityCode `json:"code"` + Value RouteFamily `json:"value"` + Mode BGPAddPathMode `json:"mode"` }{ - Code: c.Code(), - Tuples: c.Tuples, + Code: c.Code(), + Value: c.RouteFamily, + Mode: c.Mode, }) } -func NewCapAddPath(tuples []*CapAddPathTuple) *CapAddPath { +func NewCapAddPath(rf RouteFamily, mode BGPAddPathMode) *CapAddPath { return &CapAddPath{ DefaultParameterCapability: DefaultParameterCapability{ CapCode: BGP_CAP_ADD_PATH, }, - Tuples: tuples, + RouteFamily: rf, + Mode: mode, } } diff --git a/vendor/github.com/osrg/gobgp/packet/bgp/helper.go b/vendor/github.com/osrg/gobgp/packet/bgp/helper.go index d97095f9..1a06db1e 100644 --- a/vendor/github.com/osrg/gobgp/packet/bgp/helper.go +++ b/vendor/github.com/osrg/gobgp/packet/bgp/helper.go @@ -31,7 +31,7 @@ func NewTestBGPOpenMessage() *BGPMessage { p4 := NewOptionParameterCapability( []ParameterCapabilityInterface{NewCapFourOctetASNumber(100000)}) p5 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapAddPath([]*CapAddPathTuple{NewCapAddPathTuple(RF_IPv4_UC, BGP_ADD_PATH_BOTH)})}) + []ParameterCapabilityInterface{NewCapAddPath(RF_IPv4_UC, BGP_ADD_PATH_BOTH)}) return NewBGPOpenMessage(11033, 303, "100.4.10.3", []OptionParameterInterface{p1, p2, p3, p4, p5}) } diff --git a/vendor/github.com/osrg/gobgp/packet/bmp/bmp.go b/vendor/github.com/osrg/gobgp/packet/bmp/bmp.go index 6537e12c..342c8e97 100644 --- a/vendor/github.com/osrg/gobgp/packet/bmp/bmp.go +++ b/vendor/github.com/osrg/gobgp/packet/bmp/bmp.go @@ -802,159 +802,6 @@ const ( BMP_ROUTE_MIRRORING_INFO_MSG_LOST ) -type BMPRouteMirrTLVInterface interface { - ParseValue([]byte) error - Serialize() ([]byte, error) -} - -type BMPRouteMirrTLV struct { - Type uint16 - Length uint16 -} - -type BMPRouteMirrTLVBGPMsg struct { - BMPRouteMirrTLV - Value *bgp.BGPMessage -} - -func NewBMPRouteMirrTLVBGPMsg(t uint16, v *bgp.BGPMessage) *BMPRouteMirrTLVBGPMsg { - return &BMPRouteMirrTLVBGPMsg{ - BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t}, - Value: v, - } -} - -func (s *BMPRouteMirrTLVBGPMsg) ParseValue(data []byte) error { - v, err := bgp.ParseBGPMessage(data) - if err != nil { - return err - } - s.Value = v - return nil -} - -func (s *BMPRouteMirrTLVBGPMsg) Serialize() ([]byte, error) { - m, err := s.Value.Serialize() - if err != nil { - return nil, err - } - s.Length = uint16(len(m)) - buf := make([]byte, 4) - binary.BigEndian.PutUint16(buf[0:2], s.Type) - binary.BigEndian.PutUint16(buf[2:4], s.Length) - buf = append(buf, m...) - return buf, nil -} - -type BMPRouteMirrTLV16 struct { - BMPRouteMirrTLV - Value uint16 -} - -func NewBMPRouteMirrTLV16(t uint16, v uint16) *BMPRouteMirrTLV16 { - return &BMPRouteMirrTLV16{ - BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t}, - Value: v, - } -} - -func (s *BMPRouteMirrTLV16) ParseValue(data []byte) error { - s.Value = binary.BigEndian.Uint16(data[:2]) - return nil -} - -func (s *BMPRouteMirrTLV16) Serialize() ([]byte, error) { - s.Length = 2 - buf := make([]byte, 6) - binary.BigEndian.PutUint16(buf[0:2], s.Type) - binary.BigEndian.PutUint16(buf[2:4], s.Length) - binary.BigEndian.PutUint16(buf[4:6], s.Value) - return buf, nil -} - -type BMPRouteMirrTLVUnknown struct { - BMPRouteMirrTLV - Value []byte -} - -func NewBMPRouteMirrTLVUnknown(t uint16, v []byte) *BMPRouteMirrTLVUnknown { - return &BMPRouteMirrTLVUnknown{ - BMPRouteMirrTLV: BMPRouteMirrTLV{Type: t}, - Value: v, - } -} - -func (s *BMPRouteMirrTLVUnknown) ParseValue(data []byte) error { - s.Value = data[:s.Length] - return nil -} - -func (s *BMPRouteMirrTLVUnknown) Serialize() ([]byte, error) { - s.Length = uint16(len([]byte(s.Value))) - buf := make([]byte, 4) - binary.BigEndian.PutUint16(buf[0:2], s.Type) - binary.BigEndian.PutUint16(buf[2:4], s.Length) - buf = append(buf, s.Value...) - return buf, nil -} - -type BMPRouteMirroring struct { - Info []BMPRouteMirrTLVInterface -} - -func NewBMPRouteMirroring(p BMPPeerHeader, info []BMPRouteMirrTLVInterface) *BMPMessage { - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_ROUTE_MIRRORING, - }, - PeerHeader: p, - Body: &BMPRouteMirroring{ - Info: info, - }, - } -} - -func (body *BMPRouteMirroring) ParseBody(msg *BMPMessage, data []byte) error { - for len(data) >= 4 { - tl := BMPRouteMirrTLV{ - Type: binary.BigEndian.Uint16(data[0:2]), - Length: binary.BigEndian.Uint16(data[2:4]), - } - data = data[4:] - if len(data) < int(tl.Length) { - return fmt.Errorf("value lengh is not enough: %d bytes (%d bytes expected)", len(data), tl.Length) - } - var tlv BMPRouteMirrTLVInterface - switch tl.Type { - case BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG: - tlv = &BMPRouteMirrTLVBGPMsg{BMPRouteMirrTLV: tl} - case BMP_ROUTE_MIRRORING_TLV_TYPE_INFO: - tlv = &BMPRouteMirrTLV16{BMPRouteMirrTLV: tl} - default: - tlv = &BMPRouteMirrTLVUnknown{BMPRouteMirrTLV: tl} - } - if err := tlv.ParseValue(data); err != nil { - return err - } - body.Info = append(body.Info, tlv) - data = data[tl.Length:] - } - return nil -} - -func (body *BMPRouteMirroring) Serialize() ([]byte, error) { - buf := make([]byte, 0) - for _, tlv := range body.Info { - b, err := tlv.Serialize() - if err != nil { - return buf, err - } - buf = append(buf, b...) - } - return buf, nil -} - type BMPBody interface { // Sigh, some body messages need a BMPHeader to parse the body // data so we need to pass BMPHeader (avoid DecodeFromBytes @@ -1037,10 +884,6 @@ func ParseBMPMessage(data []byte) (msg *BMPMessage, err error) { msg.Body = &BMPInitiation{} case BMP_MSG_TERMINATION: msg.Body = &BMPTermination{} - case BMP_MSG_ROUTE_MIRRORING: - msg.Body = &BMPRouteMirroring{} - default: - return nil, fmt.Errorf("unsupported BMP message type: %d", msg.Header.Type) } if msg.Header.Type != BMP_MSG_INITIATION && msg.Header.Type != BMP_MSG_TERMINATION { diff --git a/vendor/github.com/osrg/gobgp/packet/bmp/bmp_test.go b/vendor/github.com/osrg/gobgp/packet/bmp/bmp_test.go index ecae38bc..061e870c 100644 --- a/vendor/github.com/osrg/gobgp/packet/bmp/bmp_test.go +++ b/vendor/github.com/osrg/gobgp/packet/bmp/bmp_test.go @@ -92,20 +92,6 @@ func Test_StatisticsReport(t *testing.T) { verify(t, s0) } -func Test_RouteMirroring(t *testing.T) { - p0 := NewBMPPeerHeader(0, 0, 1000, "10.0.0.1", 70000, "10.0.0.2", 1) - s0 := NewBMPRouteMirroring( - *p0, - []BMPRouteMirrTLVInterface{ - NewBMPRouteMirrTLV16(BMP_ROUTE_MIRRORING_TLV_TYPE_INFO, BMP_ROUTE_MIRRORING_INFO_MSG_LOST), - NewBMPRouteMirrTLVUnknown(0xff, []byte{0x01, 0x02, 0x03, 0x04}), - // RFC7854: BGP Message TLV MUST occur last in the list of TLVs - NewBMPRouteMirrTLVBGPMsg(BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG, bgp.NewTestBGPOpenMessage()), - }, - ) - verify(t, s0) -} - func Test_BogusHeader(t *testing.T) { h, err := ParseBMPMessage(make([]byte, 10)) assert.Nil(t, h) diff --git a/vendor/github.com/osrg/gobgp/packet/mrt/mrt.go b/vendor/github.com/osrg/gobgp/packet/mrt/mrt.go index 559455d1..38be0e95 100644 --- a/vendor/github.com/osrg/gobgp/packet/mrt/mrt.go +++ b/vendor/github.com/osrg/gobgp/packet/mrt/mrt.go @@ -67,7 +67,6 @@ const ( RIB_IPV6_UNICAST MRTSubTypeTableDumpv2 = 4 RIB_IPV6_MULTICAST MRTSubTypeTableDumpv2 = 5 RIB_GENERIC MRTSubTypeTableDumpv2 = 6 - GEO_PEER_TABLE MRTSubTypeTableDumpv2 = 7 // RFC6397 RIB_IPV4_UNICAST_ADDPATH MRTSubTypeTableDumpv2 = 8 // RFC8050 RIB_IPV4_MULTICAST_ADDPATH MRTSubTypeTableDumpv2 = 9 // RFC8050 RIB_IPV6_UNICAST_ADDPATH MRTSubTypeTableDumpv2 = 10 // RFC8050 @@ -543,115 +542,6 @@ func (u *Rib) String() string { return fmt.Sprintf("RIB: Seq [%d] Prefix [%s] Entries [%s]", u.SequenceNumber, u.Prefix, u.Entries) } -type GeoPeer struct { - Type uint8 - BgpId net.IP - Latitude float32 - Longitude float32 -} - -func (p *GeoPeer) DecodeFromBytes(data []byte) ([]byte, error) { - if len(data) < 13 { - return nil, fmt.Errorf("not all GeoPeer bytes are available") - } - // Peer IP Address and Peer AS should not be included - p.Type = uint8(data[0]) - if p.Type != uint8(0) { - return nil, fmt.Errorf("unsupported peer type for GeoPeer: %d", p.Type) - } - p.BgpId = net.IP(data[1:5]) - p.Latitude = math.Float32frombits(binary.BigEndian.Uint32(data[5:9])) - p.Longitude = math.Float32frombits(binary.BigEndian.Uint32(data[9:13])) - return data[13:], nil -} - -func (p *GeoPeer) Serialize() ([]byte, error) { - buf := make([]byte, 13) - buf[0] = uint8(0) // Peer IP Address and Peer AS should not be included - bgpId := p.BgpId.To4() - if bgpId == nil { - return nil, fmt.Errorf("invalid BgpId: %s", p.BgpId) - } - copy(buf[1:5], bgpId) - binary.BigEndian.PutUint32(buf[5:9], math.Float32bits(p.Latitude)) - binary.BigEndian.PutUint32(buf[9:13], math.Float32bits(p.Longitude)) - return buf, nil -} - -func NewGeoPeer(bgpid string, latitude float32, longitude float32) *GeoPeer { - return &GeoPeer{ - Type: 0, // Peer IP Address and Peer AS should not be included - BgpId: net.ParseIP(bgpid).To4(), - Latitude: latitude, - Longitude: longitude, - } -} - -func (p *GeoPeer) String() string { - return fmt.Sprintf("PEER ENTRY: ID [%s] Latitude [%f] Longitude [%f]", p.BgpId, p.Latitude, p.Longitude) -} - -type GeoPeerTable struct { - CollectorBgpId net.IP - CollectorLatitude float32 - CollectorLongitude float32 - Peers []*GeoPeer -} - -func (t *GeoPeerTable) DecodeFromBytes(data []byte) error { - if len(data) < 14 { - return fmt.Errorf("not all GeoPeerTable bytes are available") - } - t.CollectorBgpId = net.IP(data[0:4]) - t.CollectorLatitude = math.Float32frombits(binary.BigEndian.Uint32(data[4:8])) - t.CollectorLongitude = math.Float32frombits(binary.BigEndian.Uint32(data[8:12])) - peerCount := binary.BigEndian.Uint16(data[12:14]) - data = data[14:] - t.Peers = make([]*GeoPeer, 0, peerCount) - var err error - for i := 0; i < int(peerCount); i++ { - p := &GeoPeer{} - if data, err = p.DecodeFromBytes(data); err != nil { - return err - } - t.Peers = append(t.Peers, p) - } - return nil -} - -func (t *GeoPeerTable) Serialize() ([]byte, error) { - buf := make([]byte, 14) - collectorBgpId := t.CollectorBgpId.To4() - if collectorBgpId == nil { - return nil, fmt.Errorf("invalid CollectorBgpId: %s", t.CollectorBgpId) - } - copy(buf[0:4], collectorBgpId) - binary.BigEndian.PutUint32(buf[4:8], math.Float32bits(t.CollectorLatitude)) - binary.BigEndian.PutUint32(buf[8:12], math.Float32bits(t.CollectorLongitude)) - binary.BigEndian.PutUint16(buf[12:14], uint16(len(t.Peers))) - for _, peer := range t.Peers { - pbuf, err := peer.Serialize() - if err != nil { - return nil, err - } - buf = append(buf, pbuf...) - } - return buf, nil -} - -func NewGeoPeerTable(bgpid string, latitude float32, longitude float32, peers []*GeoPeer) *GeoPeerTable { - return &GeoPeerTable{ - CollectorBgpId: net.ParseIP(bgpid).To4(), - CollectorLatitude: latitude, - CollectorLongitude: longitude, - Peers: peers, - } -} - -func (t *GeoPeerTable) String() string { - return fmt.Sprintf("GEO_PEER_TABLE: CollectorBgpId [%s] CollectorLatitude [%f] CollectorLongitude [%f] Peers [%s]", t.CollectorBgpId, t.CollectorLatitude, t.CollectorLongitude, t.Peers) -} - type BGP4MPHeader struct { PeerAS uint32 LocalAS uint32 @@ -922,8 +812,6 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) { case RIB_IPV6_MULTICAST: rf = bgp.RF_IPv6_MC case RIB_GENERIC: - case GEO_PEER_TABLE: - msg.Body = &GeoPeerTable{} case RIB_IPV4_UNICAST_ADDPATH: rf = bgp.RF_IPv4_UC isAddPath = true @@ -942,7 +830,7 @@ func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) { return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v\n", subType) } - if msg.Body == nil { + if subType != PEER_INDEX_TABLE { msg.Body = &Rib{ RouteFamily: rf, isAddPath: isAddPath, diff --git a/vendor/github.com/osrg/gobgp/packet/mrt/mrt_test.go b/vendor/github.com/osrg/gobgp/packet/mrt/mrt_test.go index e2e601a5..1b5978b0 100644 --- a/vendor/github.com/osrg/gobgp/packet/mrt/mrt_test.go +++ b/vendor/github.com/osrg/gobgp/packet/mrt/mrt_test.go @@ -227,22 +227,6 @@ func TestMrtRibWithAddPath(t *testing.T) { assert.Equal(t, reflect.DeepEqual(r1, r2), true) } -func TestMrtGeoPeerTable(t *testing.T) { - p1 := NewGeoPeer("192.168.0.1", 28.031157, 86.899684) - p2 := NewGeoPeer("192.168.0.1", 35.360556, 138.727778) - pt1 := NewGeoPeerTable("192.168.0.1", 12.345678, 98.765432, []*GeoPeer{p1, p2}) - b1, err := pt1.Serialize() - if err != nil { - t.Fatal(err) - } - pt2 := &GeoPeerTable{} - err = pt2.DecodeFromBytes(b1) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, reflect.DeepEqual(pt1, pt2), true) -} - func TestMrtBgp4mpStateChange(t *testing.T) { c1 := NewBGP4MPStateChange(65000, 65001, 1, "192.168.0.1", "192.168.0.2", false, ACTIVE, ESTABLISHED) b1, err := c1.Serialize() diff --git a/vendor/github.com/osrg/gobgp/server/bmp.go b/vendor/github.com/osrg/gobgp/server/bmp.go index 1e12e372..e7dc3ea2 100644 --- a/vendor/github.com/osrg/gobgp/server/bmp.go +++ b/vendor/github.com/osrg/gobgp/server/bmp.go @@ -17,11 +17,11 @@ package server import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/packet/bmp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "net" "strconv" "time" @@ -127,9 +127,6 @@ func (b *bmpClient) loop() { if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL { ops = append(ops, WatchBestPath(true)) } - if b.c.RouteMirroringEnabled { - ops = append(ops, WatchMessage(false)) - } w := b.s.Watch(ops...) defer w.Stop() @@ -212,15 +209,6 @@ func (b *bmpClient) loop() { return false } } - case *WatchEventMessage: - info := &table.PeerInfo{ - Address: msg.PeerAddress, - AS: msg.PeerAS, - ID: msg.PeerID, - } - if err := write(bmpPeerRouteMirroring(bmp.BMP_PEER_TYPE_GLOBAL, 0, info, msg.Timestamp.Unix(), msg.Message)); err != nil { - return false - } } case <-tickerCh: neighborList := b.s.GetNeighbor("", true) @@ -289,26 +277,12 @@ func bmpPeerRoute(t uint8, policy bool, pd uint64, peeri *table.PeerInfo, timest func bmpPeerStats(peerType uint8, peerDist uint64, timestamp int64, neighConf *config.Neighbor) *bmp.BMPMessage { var peerFlags uint8 = 0 - ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, neighConf.State.NeighborAddress, neighConf.State.PeerAs, neighConf.State.RemoteRouterId, float64(timestamp)) + ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, neighConf.Config.NeighborAddress, neighConf.State.PeerAs, neighConf.State.RemoteRouterId, float64(timestamp)) return bmp.NewBMPStatisticsReport( *ph, []bmp.BMPStatsTLVInterface{ bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_ADJ_RIB_IN, uint64(neighConf.State.AdjTable.Accepted)), bmp.NewBMPStatsTLV64(bmp.BMP_STAT_TYPE_LOC_RIB, uint64(neighConf.State.AdjTable.Advertised+neighConf.State.AdjTable.Filtered)), - bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, neighConf.State.Messages.Received.WithdrawUpdate), - bmp.NewBMPStatsTLV32(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, neighConf.State.Messages.Received.WithdrawPrefix), - }, - ) -} - -func bmpPeerRouteMirroring(peerType uint8, peerDist uint64, peerInfo *table.PeerInfo, timestamp int64, msg *bgp.BGPMessage) *bmp.BMPMessage { - var peerFlags uint8 = 0 - ph := bmp.NewBMPPeerHeader(peerType, peerFlags, peerDist, peerInfo.Address.String(), peerInfo.AS, peerInfo.ID.String(), float64(timestamp)) - return bmp.NewBMPRouteMirroring( - *ph, - []bmp.BMPRouteMirrTLVInterface{ - // RFC7854: BGP Message TLV MUST occur last in the list of TLVs - bmp.NewBMPRouteMirrTLVBGPMsg(bmp.BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG, msg), }, ) } diff --git a/vendor/github.com/osrg/gobgp/server/collector.go b/vendor/github.com/osrg/gobgp/server/collector.go index 50fb72e9..59f945be 100644 --- a/vendor/github.com/osrg/gobgp/server/collector.go +++ b/vendor/github.com/osrg/gobgp/server/collector.go @@ -17,10 +17,10 @@ package server import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/influxdata/influxdb/client/v2" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "time" ) diff --git a/vendor/github.com/osrg/gobgp/server/fsm.go b/vendor/github.com/osrg/gobgp/server/fsm.go index afd04b3e..e1b85cd0 100644 --- a/vendor/github.com/osrg/gobgp/server/fsm.go +++ b/vendor/github.com/osrg/gobgp/server/fsm.go @@ -17,12 +17,11 @@ package server import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - "github.com/osrg/gobgp/packet/bmp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "gopkg.in/tomb.v2" "io" "math/rand" @@ -183,18 +182,6 @@ func (fsm *FSM) bgpMessageStateUpdate(MessageType uint8, isIn bool) { } } -func (fsm *FSM) bmpStatsUpdate(statType uint16, increment int) { - stats := &fsm.pConf.State.Messages.Received - switch statType { - // TODO - // Support other stat types. - case bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE: - stats.WithdrawUpdate += uint32(increment) - case bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX: - stats.WithdrawPrefix += uint32(increment) - } -} - func NewFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingPolicy) *FSM { adminState := ADMIN_STATE_UP if pConf.Config.AdminDown { @@ -227,7 +214,7 @@ func NewFSM(gConf *config.Global, pConf *config.Neighbor, policy *table.RoutingP func (fsm *FSM) StateChange(nextState bgp.FSMState) { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "old": fsm.state.String(), "new": nextState.String(), "reason": fsm.reason, @@ -298,12 +285,12 @@ func (fsm *FSM) sendNotificationFromErrorMsg(e *bgp.MessageError) error { fsm.h.conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "Data": e, }).Warn("sent notification") return nil } - return fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.State.NeighborAddress) + return fmt.Errorf("can't send notification to %s since TCP connection is not established", fsm.pConf.Config.NeighborAddress) } func (fsm *FSM) sendNotification(code, subType uint8, data []byte, msg string) error { @@ -323,7 +310,7 @@ func (fsm *FSM) connectLoop() error { timer.Stop() connect := func() { - addr := fsm.pConf.State.NeighborAddress + addr := fsm.pConf.Config.NeighborAddress port := int(bgp.BGP_PORT) if fsm.pConf.Transport.Config.RemotePort != 0 { port = int(fsm.pConf.Transport.Config.RemotePort) @@ -342,7 +329,7 @@ func (fsm *FSM) connectLoop() error { if e != nil { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, }).Warnf("failed to resolve ltcpaddr: %s", e) return } @@ -358,13 +345,13 @@ func (fsm *FSM) connectLoop() error { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, }).Warn("active conn is closed to avoid being blocked") } } else { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, }).Debugf("failed to connect: %s", err) } @@ -378,7 +365,7 @@ func (fsm *FSM) connectLoop() error { case <-fsm.t.Dying(): log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, }).Debug("stop connect loop") return nil case <-timer.C: @@ -429,7 +416,7 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) { if fsm.pConf.GracefulRestart.State.PeerRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("graceful restart timer expired") return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED @@ -441,7 +428,7 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("Closed an accepted connection") case <-idleHoldTimer.C: @@ -449,7 +436,7 @@ func (h *FSMHandler) idle() (bgp.FSMState, FsmStateReason) { if fsm.adminState == ADMIN_STATE_UP { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "Duration": fsm.idleHoldTime, }).Debug("IdleHoldTimer expired") fsm.idleHoldTime = HOLDTIME_IDLE @@ -487,38 +474,13 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) { break } fsm.conn = conn - ttl := 0 - ttlMin := 0 - if fsm.pConf.TtlSecurity.Config.Enabled { - ttl = 255 - ttlMin = int(fsm.pConf.TtlSecurity.Config.TtlMin) - } else if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { + if fsm.pConf.Config.PeerAs != 0 && fsm.pConf.Config.PeerType == config.PEER_TYPE_EXTERNAL { + ttl := 1 if fsm.pConf.EbgpMultihop.Config.Enabled { ttl = int(fsm.pConf.EbgpMultihop.Config.MultihopTtl) - } else if fsm.pConf.Transport.Config.Ttl != 0 { - ttl = int(fsm.pConf.Transport.Config.Ttl) - } else { - ttl = 1 } - } else if fsm.pConf.Transport.Config.Ttl != 0 { - ttl = int(fsm.pConf.Transport.Config.Ttl) - } - if ttl != 0 { - if err := SetTcpTTLSockopts(conn.(*net.TCPConn), ttl); err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": fsm.pConf.Config.NeighborAddress, - "State": fsm.state.String(), - }).Warnf("cannot set TTL(=%d) for peer: %s", ttl, err) - } - } - if ttlMin != 0 { - if err := SetTcpMinTTLSockopts(conn.(*net.TCPConn), ttlMin); err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": fsm.pConf.Config.NeighborAddress, - "State": fsm.state.String(), - }).Warnf("cannot set minimal TTL(=%d) for peer: %s", ttl, err) + if ttl != 0 { + SetTcpTTLSockopts(conn.(*net.TCPConn), ttl) } } // we don't implement delayed open timer so move to opensent right @@ -528,7 +490,7 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) { if fsm.pConf.GracefulRestart.State.PeerRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("graceful restart timer expired") return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED @@ -544,7 +506,7 @@ func (h *FSMHandler) active() (bgp.FSMState, FsmStateReason) { case ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "AdminState": stateOp.State.String(), }).Panic("code logic bug") @@ -683,13 +645,13 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { h.fsm.bgpMessageStateUpdate(0, true) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": h.fsm.pConf.State.NeighborAddress, + "Key": h.fsm.pConf.Config.NeighborAddress, "State": h.fsm.state.String(), "error": err, }).Warn("malformed BGP Header") fmsg := &FsmMsg{ MsgType: FSM_MSG_BGP_MESSAGE, - MsgSrc: h.fsm.pConf.State.NeighborAddress, + MsgSrc: h.fsm.pConf.Config.NeighborAddress, MsgData: err, Version: h.fsm.version, } @@ -712,14 +674,14 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { } fmsg := &FsmMsg{ MsgType: FSM_MSG_BGP_MESSAGE, - MsgSrc: h.fsm.pConf.State.NeighborAddress, + MsgSrc: h.fsm.pConf.Config.NeighborAddress, timestamp: now, Version: h.fsm.version, } if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": h.fsm.pConf.State.NeighborAddress, + "Key": h.fsm.pConf.Config.NeighborAddress, "State": h.fsm.state.String(), "error": err, }).Warn("malformed BGP message") @@ -742,7 +704,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": h.fsm.pConf.State.NeighborAddress, + "Key": h.fsm.pConf.Config.NeighborAddress, "State": h.fsm.state.String(), "error": err, }).Warn("malformed BGP update message") @@ -750,17 +712,6 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { return fmsg, err } - if routes := len(body.WithdrawnRoutes); routes > 0 { - h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1) - h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes) - } else if attr := getPathAttrFromBGPUpdate(body, bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI); attr != nil { - mpUnreach := attr.(*bgp.PathAttributeMpUnreachNLRI) - if routes = len(mpUnreach.Value); routes > 0 { - h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_UPDATE, 1) - h.fsm.bmpStatsUpdate(bmp.BMP_STAT_TYPE_WITHDRAW_PREFIX, routes) - } - } - table.UpdatePathAttrs4ByteAs(body) if err = table.UpdatePathAggregator4ByteAs(body); err != nil { fmsg.MsgData = err @@ -777,7 +728,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { } fmsg.PathList = table.ProcessMessage(m, h.fsm.peerInfo, fmsg.timestamp) - id := h.fsm.pConf.State.NeighborAddress + id := h.fsm.pConf.Config.NeighborAddress for _, path := range fmsg.PathList { if path.IsEOR() { continue @@ -804,7 +755,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { communication, rest := decodeAdministrativeCommunication(body.Data) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": h.fsm.pConf.State.NeighborAddress, + "Key": h.fsm.pConf.Config.NeighborAddress, "Code": body.ErrorCode, "Subcode": body.ErrorSubcode, "Communicated-Reason": communication, @@ -813,7 +764,7 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { } else { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": h.fsm.pConf.State.NeighborAddress, + "Key": h.fsm.pConf.Config.NeighborAddress, "Code": body.ErrorCode, "Subcode": body.ErrorSubcode, "Data": body.Data, @@ -905,17 +856,16 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("Closed an accepted connection") case <-fsm.gracefulRestartTimer.C: if fsm.pConf.GracefulRestart.State.PeerRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("graceful restart timer expired") - h.conn.Close() return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED } case i, ok := <-h.msgCh.Out(): @@ -944,7 +894,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { fsm.pConf.State.PeerType = typ log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Infof("skiped asn negotiation: peer-as: %d, peer-type: %s", peerAs, typ) } else { @@ -999,7 +949,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { if fsm.pConf.GracefulRestart.State.PeerRestarting && cap.Flags&0x08 == 0 { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("restart flag is not set") // send notification? @@ -1043,7 +993,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { default: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Data": e.MsgData, }).Panic("unknown msg type") @@ -1065,7 +1015,7 @@ func (h *FSMHandler) opensent() (bgp.FSMState, FsmStateReason) { case ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "AdminState": stateOp.State.String(), }).Panic("code logic bug") @@ -1116,17 +1066,16 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("Closed an accepted connection") case <-fsm.gracefulRestartTimer.C: if fsm.pConf.GracefulRestart.State.PeerRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("graceful restart timer expired") - h.conn.Close() return bgp.BGP_FSM_IDLE, FSM_RESTART_TIMER_EXPIRED } case <-ticker.C: @@ -1155,7 +1104,7 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) { default: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Data": e.MsgData, }).Panic("unknown msg type") @@ -1177,7 +1126,7 @@ func (h *FSMHandler) openconfirm() (bgp.FSMState, FsmStateReason) { case ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "AdminState": stateOp.State.String(), }).Panic("code logic bug") @@ -1195,7 +1144,7 @@ func (h *FSMHandler) sendMessageloop() error { if fsm.twoByteAsTrans && m.Header.Type == bgp.BGP_MSG_UPDATE { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Data": m, }).Debug("update for 2byte AS peer") @@ -1206,7 +1155,7 @@ func (h *FSMHandler) sendMessageloop() error { if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Data": err, }).Warn("failed to serialize") @@ -1222,7 +1171,7 @@ func (h *FSMHandler) sendMessageloop() error { if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Data": err, }).Warn("failed to send") @@ -1239,7 +1188,7 @@ func (h *FSMHandler) sendMessageloop() error { communication, rest := decodeAdministrativeCommunication(body.Data) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Code": body.ErrorCode, "Subcode": body.ErrorSubcode, @@ -1249,7 +1198,7 @@ func (h *FSMHandler) sendMessageloop() error { } else { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Code": body.ErrorCode, "Subcode": body.ErrorSubcode, @@ -1263,7 +1212,7 @@ func (h *FSMHandler) sendMessageloop() error { update := m.Body.(*bgp.BGPUpdate) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "nlri": update.NLRI, "withdrawals": update.WithdrawnRoutes, @@ -1272,7 +1221,7 @@ func (h *FSMHandler) sendMessageloop() error { default: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "data": m, }).Debug("sent") @@ -1348,7 +1297,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) { conn.Close() log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("Closed an accepted connection") case err := <-h.errorCh: @@ -1358,7 +1307,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) { err = FSM_GRACEFUL_RESTART log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Info("peer graceful restart") fsm.gracefulRestartTimer.Reset(time.Duration(fsm.pConf.GracefulRestart.State.PeerRestartTime) * time.Second) @@ -1367,7 +1316,7 @@ func (h *FSMHandler) established() (bgp.FSMState, FsmStateReason) { case <-holdTimer.C: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("hold timer expired") m := bgp.NewBGPNotificationMessage(bgp.BGP_ERROR_HOLD_TIMER_EXPIRED, 0, nil) @@ -1424,7 +1373,7 @@ func (h *FSMHandler) loop() error { if nextState == bgp.BGP_FSM_ESTABLISHED && oldState == bgp.BGP_FSM_OPENCONFIRM { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Info("Peer Up") } @@ -1438,14 +1387,14 @@ func (h *FSMHandler) loop() error { } log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "Reason": reason, }).Info("Peer Down") } e := time.AfterFunc(time.Second*120, func() { - log.WithFields(log.Fields{"Topic": "Peer"}).Fatalf("failed to free the fsm.h.t for %s %s %s", fsm.pConf.State.NeighborAddress, oldState, nextState) + log.WithFields(log.Fields{"Topic": "Peer"}).Fatalf("failed to free the fsm.h.t for %s %s %s", fsm.pConf.Config.NeighborAddress, oldState, nextState) }) h.t.Wait() e.Stop() @@ -1454,7 +1403,7 @@ func (h *FSMHandler) loop() error { if nextState >= bgp.BGP_FSM_IDLE { e := &FsmMsg{ MsgType: FSM_MSG_STATE_CHANGE, - MsgSrc: fsm.pConf.State.NeighborAddress, + MsgSrc: fsm.pConf.Config.NeighborAddress, MsgData: nextState, Version: h.fsm.version, } @@ -1468,7 +1417,7 @@ func (h *FSMHandler) changeAdminState(s AdminState) error { if fsm.adminState != s { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), "AdminState": s.String(), }).Debug("admin state changed") @@ -1480,19 +1429,19 @@ func (h *FSMHandler) changeAdminState(s AdminState) error { case ADMIN_STATE_UP: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Info("Administrative start") case ADMIN_STATE_DOWN: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Info("Administrative shutdown") case ADMIN_STATE_PFX_CT: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Info("Administrative shutdown(Prefix limit reached)") } @@ -1500,7 +1449,7 @@ func (h *FSMHandler) changeAdminState(s AdminState) error { } else { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": fsm.pConf.State.NeighborAddress, + "Key": fsm.pConf.Config.NeighborAddress, "State": fsm.state.String(), }).Warn("cannot change to the same state") diff --git a/vendor/github.com/osrg/gobgp/server/fsm_test.go b/vendor/github.com/osrg/gobgp/server/fsm_test.go index 55318ac3..e8ad2ad8 100644 --- a/vendor/github.com/osrg/gobgp/server/fsm_test.go +++ b/vendor/github.com/osrg/gobgp/server/fsm_test.go @@ -23,11 +23,11 @@ import ( "testing" "time" + log "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) diff --git a/vendor/github.com/osrg/gobgp/server/mrt.go b/vendor/github.com/osrg/gobgp/server/mrt.go index e2cfa6fc..6c66745d 100644 --- a/vendor/github.com/osrg/gobgp/server/mrt.go +++ b/vendor/github.com/osrg/gobgp/server/mrt.go @@ -21,11 +21,11 @@ import ( "os" "time" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/packet/mrt" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" ) const ( @@ -109,7 +109,7 @@ func (m *mrtWriter) loop() error { t := uint32(time.Now().Unix()) peers := make([]*mrt.Peer, 0, len(m.Neighbor)) for _, pconf := range m.Neighbor { - peers = append(peers, mrt.NewPeer(pconf.State.RemoteRouterId, pconf.State.NeighborAddress, pconf.Config.PeerAs, true)) + peers = append(peers, mrt.NewPeer(pconf.State.RemoteRouterId, pconf.Config.NeighborAddress, pconf.Config.PeerAs, true)) } if bm, err := mrt.NewMRTMessage(t, mrt.TABLE_DUMPv2, mrt.PEER_INDEX_TABLE, mrt.NewPeerIndexTable(m.RouterId, "", peers)); err != nil { break @@ -119,7 +119,7 @@ func (m *mrtWriter) loop() error { idx := func(p *table.Path) uint16 { for i, pconf := range m.Neighbor { - if p.GetSource().Address.String() == pconf.State.NeighborAddress { + if p.GetSource().Address.String() == pconf.Config.NeighborAddress { return uint16(i) } } diff --git a/vendor/github.com/osrg/gobgp/server/peer.go b/vendor/github.com/osrg/gobgp/server/peer.go index e51efc93..6ead5fbe 100644 --- a/vendor/github.com/osrg/gobgp/server/peer.go +++ b/vendor/github.com/osrg/gobgp/server/peer.go @@ -17,11 +17,11 @@ package server import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "net" "time" ) @@ -31,65 +31,6 @@ const ( MIN_CONNECT_RETRY = 10 ) -type PeerGroup struct { - Conf *config.PeerGroup - members map[string]config.Neighbor - dynamicNeighbors map[string]*config.DynamicNeighbor -} - -func NewPeerGroup(c *config.PeerGroup) *PeerGroup { - return &PeerGroup{ - Conf: c, - members: make(map[string]config.Neighbor, 0), - dynamicNeighbors: make(map[string]*config.DynamicNeighbor, 0), - } -} - -func (pg *PeerGroup) AddMember(c config.Neighbor) { - pg.members[c.State.NeighborAddress] = c -} - -func (pg *PeerGroup) DeleteMember(c config.Neighbor) { - delete(pg.members, c.State.NeighborAddress) -} - -func (pg *PeerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) { - pg.dynamicNeighbors[c.Config.Prefix] = c -} - -func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *Peer { - conf := config.Neighbor{ - Config: config.NeighborConfig{ - PeerGroup: pg.Config.PeerGroupName, - }, - State: config.NeighborState{ - NeighborAddress: neighborAddress, - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - PassiveMode: true, - }, - }, - } - if err := config.OverwriteNeighborConfigWithPeerGroup(&conf, pg); err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": neighborAddress, - }).Debugf("Can't overwrite neighbor config: %s", err) - return nil - } - if err := config.SetDefaultNeighborConfigValues(&conf, g.Config.As); err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": neighborAddress, - }).Debugf("Can't set default config: %s", err) - return nil - } - peer := NewPeer(g, &conf, loc, policy) - peer.fsm.state = bgp.BGP_FSM_ACTIVE - return peer -} - type Peer struct { tableId string fsm *FSM @@ -110,7 +51,7 @@ func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, p prefixLimitWarned: make(map[bgp.RouteFamily]bool), } if peer.isRouteServerClient() { - peer.tableId = conf.State.NeighborAddress + peer.tableId = conf.Config.NeighborAddress } else { peer.tableId = table.GLOBAL_RIB_NAME } @@ -120,7 +61,7 @@ func NewPeer(g *config.Global, conf *config.Neighbor, loc *table.TableManager, p } func (peer *Peer) ID() string { - return peer.fsm.pConf.State.NeighborAddress + return peer.fsm.pConf.Config.NeighborAddress } func (peer *Peer) TableID() string { @@ -143,10 +84,6 @@ func (peer *Peer) isGracefulRestartEnabled() bool { return peer.fsm.pConf.GracefulRestart.State.Enabled } -func (peer *Peer) isDynamicNeighbor() bool { - return peer.fsm.pConf.Config.NeighborAddress == "" && peer.fsm.pConf.Config.NeighborInterface == "" -} - func (peer *Peer) recvedAllEOR() bool { for _, a := range peer.fsm.pConf.AfiSafis { if s := a.MpGracefulRestart.State; s.Enabled && !s.EndOfRibReceived { @@ -403,7 +340,7 @@ func (peer *Peer) processOutgoingPaths(paths, olds []*table.Path) []*table.Path if peer.fsm.pConf.GracefulRestart.State.LocalRestarting { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug("now syncing, suppress sending updates") return nil } @@ -521,7 +458,7 @@ func (peer *Peer) handleUpdate(e *FsmMsg) ([]*table.Path, []bgp.RouteFamily, *bg update := m.Body.(*bgp.BGPUpdate) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, "nlri": update.NLRI, "withdrawals": update.WithdrawnRoutes, "attributes": update.PathAttributes, @@ -628,42 +565,3 @@ func (peer *Peer) ToConfig(getAdvertised bool) *config.Neighbor { func (peer *Peer) DropAll(rfList []bgp.RouteFamily) { peer.adjRibIn.Drop(rfList) } - -func (peer *Peer) stopFSM() error { - failed := false - addr := peer.fsm.pConf.State.NeighborAddress - t1 := time.AfterFunc(time.Minute*5, func() { - log.WithFields(log.Fields{ - "Topic": "Peer", - }).Warnf("Failed to free the fsm.h.t for %s", addr) - failed = true - }) - peer.fsm.h.t.Kill(nil) - peer.fsm.h.t.Wait() - t1.Stop() - if !failed { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": addr, - }).Debug("freed fsm.h.t") - cleanInfiniteChannel(peer.outgoing) - } - failed = false - t2 := time.AfterFunc(time.Minute*5, func() { - log.WithFields(log.Fields{ - "Topic": "Peer", - }).Warnf("Failed to free the fsm.t for %s", addr) - failed = true - }) - peer.fsm.t.Kill(nil) - peer.fsm.t.Wait() - t2.Stop() - if !failed { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": addr, - }).Debug("freed fsm.t") - return nil - } - return fmt.Errorf("Failed to free FSM for %s", addr) -} diff --git a/vendor/github.com/osrg/gobgp/server/rpki.go b/vendor/github.com/osrg/gobgp/server/rpki.go index a93decb8..5c8c3db9 100644 --- a/vendor/github.com/osrg/gobgp/server/rpki.go +++ b/vendor/github.com/osrg/gobgp/server/rpki.go @@ -24,12 +24,12 @@ import ( "strconv" "time" + log "github.com/Sirupsen/logrus" "github.com/armon/go-radix" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/packet/rtr" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "golang.org/x/net/context" ) diff --git a/vendor/github.com/osrg/gobgp/server/server.go b/vendor/github.com/osrg/gobgp/server/server.go index 1ecbedf0..0bd9c0d9 100644 --- a/vendor/github.com/osrg/gobgp/server/server.go +++ b/vendor/github.com/osrg/gobgp/server/server.go @@ -23,11 +23,11 @@ import ( "strconv" "time" + log "github.com/Sirupsen/logrus" "github.com/eapache/channels" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" ) type TCPListener struct { @@ -92,29 +92,27 @@ type BgpServer struct { fsmStateCh chan *FsmMsg acceptCh chan *net.TCPConn - mgmtCh chan *mgmtOp - policy *table.RoutingPolicy - listeners []*TCPListener - neighborMap map[string]*Peer - peerGroupMap map[string]*PeerGroup - globalRib *table.TableManager - roaManager *roaManager - shutdown bool - watcherMap map[WatchEventType][]*Watcher - zclient *zebraClient - bmpManager *bmpClientManager - mrtManager *mrtManager + mgmtCh chan *mgmtOp + policy *table.RoutingPolicy + listeners []*TCPListener + neighborMap map[string]*Peer + globalRib *table.TableManager + roaManager *roaManager + shutdown bool + watcherMap map[WatchEventType][]*Watcher + zclient *zebraClient + bmpManager *bmpClientManager + mrtManager *mrtManager } func NewBgpServer() *BgpServer { roaManager, _ := NewROAManager(0) s := &BgpServer{ - neighborMap: make(map[string]*Peer), - peerGroupMap: make(map[string]*PeerGroup), - policy: table.NewRoutingPolicy(), - roaManager: roaManager, - mgmtCh: make(chan *mgmtOp, 1), - watcherMap: make(map[WatchEventType][]*Watcher), + neighborMap: make(map[string]*Peer), + policy: table.NewRoutingPolicy(), + roaManager: roaManager, + mgmtCh: make(chan *mgmtOp, 1), + watcherMap: make(map[WatchEventType][]*Watcher), } s.bmpManager = newBmpClientManager(s) s.mrtManager = newMrtManager(s) @@ -236,24 +234,6 @@ func (server *BgpServer) Serve() { "Topic": "Peer", }).Debugf("Accepted a new passive connection from:%s", remoteAddr) peer.PassConn(conn) - } else if pg := server.matchLongestDynamicNeighborPrefix(remoteAddr); pg != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - }).Debugf("Accepted a new dynamic neighbor from:%s", remoteAddr) - peer := newDynamicPeer(&server.bgpConfig.Global, remoteAddr, pg.Conf, server.globalRib, server.policy) - if peer == nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": remoteAddr, - }).Infof("Can't create new Dynamic Peer") - conn.Close() - return - } - server.policy.Reset(nil, map[string]config.ApplyPolicy{peer.ID(): peer.fsm.pConf.ApplyPolicy}) - server.neighborMap[remoteAddr] = peer - peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh) - server.broadcastPeerState(peer, bgp.BGP_FSM_ACTIVE) - peer.PassConn(conn) } else { log.WithFields(log.Fields{ "Topic": "Peer", @@ -298,24 +278,6 @@ func (server *BgpServer) Serve() { } } -func (server *BgpServer) matchLongestDynamicNeighborPrefix(a string) *PeerGroup { - ipAddr := net.ParseIP(a) - longestMask := net.CIDRMask(0, 32).String() - var longestPG *PeerGroup - for _, pg := range server.peerGroupMap { - for _, d := range pg.dynamicNeighbors { - _, netAddr, _ := net.ParseCIDR(d.Config.Prefix) - if netAddr.Contains(ipAddr) { - if netAddr.Mask.String() > longestMask { - longestMask = netAddr.Mask.String() - longestPG = pg - } - } - } - } - return longestPG -} - func sendFsmOutgoingMsg(peer *Peer, paths []*table.Path, notification *bgp.BGPMessage, stayIdle bool) { peer.outgoing.In() <- &FsmOutgoingMsg{ Paths: paths, @@ -570,33 +532,6 @@ func (server *BgpServer) broadcastPeerState(peer *Peer, oldState bgp.FSMState) { } } -func (server *BgpServer) notifyMessageWatcher(peer *Peer, timestamp time.Time, msg *bgp.BGPMessage, isSent bool) { - // validation should be done in the caller of this function - _, y := peer.fsm.capMap[bgp.BGP_CAP_FOUR_OCTET_AS_NUMBER] - l, _ := peer.fsm.LocalHostPort() - ev := &WatchEventMessage{ - Message: msg, - PeerAS: peer.fsm.peerInfo.AS, - LocalAS: peer.fsm.peerInfo.LocalAS, - PeerAddress: peer.fsm.peerInfo.Address, - LocalAddress: net.ParseIP(l), - PeerID: peer.fsm.peerInfo.ID, - FourBytesAs: y, - Timestamp: timestamp, - IsSent: isSent, - } - if !isSent { - server.notifyWatcher(WATCH_EVENT_TYPE_RECV_MSG, ev) - } -} - -func (server *BgpServer) notifyRecvMessageWatcher(peer *Peer, timestamp time.Time, msg *bgp.BGPMessage) { - if peer == nil || !server.isWatched(WATCH_EVENT_TYPE_RECV_MSG) { - return - } - server.notifyMessageWatcher(peer, timestamp, msg, false) -} - func (server *BgpServer) RSimportPaths(peer *Peer, pathList []*table.Path) []*table.Path { moded := make([]*table.Path, 0, len(pathList)/2) for _, before := range pathList { @@ -757,11 +692,6 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { peer.fsm.pConf.State.PeerAs = 0 peer.fsm.peerInfo.AS = 0 } - if peer.isDynamicNeighbor() { - peer.stopPeerRestarting() - go peer.stopFSM() - delete(server.neighborMap, peer.fsm.pConf.State.NeighborAddress) - } } else if peer.fsm.pConf.GracefulRestart.State.PeerRestarting && nextState == bgp.BGP_FSM_IDLE { if peer.fsm.pConf.GracefulRestart.State.LongLivedEnabled { llgr, no_llgr := peer.llgrFamilies() @@ -842,7 +772,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { deferralExpiredFunc := func(family bgp.RouteFamily) func() { return func() { server.mgmtOperation(func() error { - server.softResetOut(peer.fsm.pConf.State.NeighborAddress, family, true) + server.softResetOut(peer.fsm.pConf.Config.NeighborAddress, family, true) return nil }, false) } @@ -905,7 +835,6 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { // clear counter if peer.fsm.adminState == ADMIN_STATE_DOWN { peer.fsm.pConf.State = config.NeighborState{} - peer.fsm.pConf.State.NeighborAddress = peer.fsm.pConf.Config.NeighborAddress peer.fsm.pConf.Timers.State = config.TimersState{} } peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh) @@ -924,7 +853,6 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { sendFsmOutgoingMsg(peer, nil, bgp.NewBGPNotificationMessage(m.TypeCode, m.SubTypeCode, m.Data), false) return case *bgp.BGPMessage: - server.notifyRecvMessageWatcher(peer, e.timestamp, m) if peer.fsm.state != bgp.BGP_FSM_ESTABLISHED || e.timestamp.Unix() < peer.fsm.pConf.Timers.State.Uptime { return } @@ -1012,7 +940,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { pathList := peer.adjRibIn.DropStale(peer.configuredRFlist()) log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debugf("withdraw %d stale routes", len(pathList)) server.propagateUpdate(peer, pathList) } @@ -1042,7 +970,7 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *FsmMsg) { default: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, "Data": e.MsgData, }).Panic("unknown msg type") } @@ -1103,7 +1031,7 @@ func (s *BgpServer) UpdatePolicy(policy config.RoutingPolicy) error { for _, peer := range s.neighborMap { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Info("call set policy") ap[peer.ID()] = peer.fsm.pConf.ApplyPolicy } @@ -1647,42 +1575,17 @@ func (s *BgpServer) GetNeighbor(address string, getAdvertised bool) (l []*config return l } -func (server *BgpServer) addPeerGroup(c *config.PeerGroup) error { - name := c.Config.PeerGroupName - if _, y := server.peerGroupMap[name]; y { - return fmt.Errorf("Can't overwrite the existing peer-group: %s", name) - } - - log.WithFields(log.Fields{ - "Topic": "Peer", - "Name": name, - }).Info("Add a peer group configuration") - - server.peerGroupMap[c.Config.PeerGroupName] = NewPeerGroup(c) - - return nil -} - func (server *BgpServer) addNeighbor(c *config.Neighbor) error { - addr, err := config.ExtractNeighborAddress(c) - if err != nil { - return err - } - - if _, y := server.neighborMap[addr]; y { - return fmt.Errorf("Can't overwrite the existing peer: %s", addr) - } - - if c.Config.PeerGroup != "" { - if err := config.OverwriteNeighborConfigWithPeerGroup(c, server.peerGroupMap[c.Config.PeerGroup].Conf); err != nil { - return err - } - } if err := config.SetDefaultNeighborConfigValues(c, server.bgpConfig.Global.Config.As); err != nil { return err } + addr := c.Config.NeighborAddress + if _, y := server.neighborMap[addr]; y { + return fmt.Errorf("Can't overwrite the existing peer: %s", addr) + } + if vrf := c.Config.Vrf; vrf != "" { if c.RouteServer.Config.RouteServerClient { return fmt.Errorf("route server client can't be enslaved to VRF") @@ -1737,62 +1640,19 @@ func (server *BgpServer) addNeighbor(c *config.Neighbor) error { } } server.neighborMap[addr] = peer - if name := c.Config.PeerGroup; name != "" { - server.peerGroupMap[name].AddMember(*c) - } peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh) server.broadcastPeerState(peer, bgp.BGP_FSM_IDLE) return nil } -func (s *BgpServer) AddPeerGroup(c *config.PeerGroup) error { - return s.mgmtOperation(func() error { - return s.addPeerGroup(c) - }, true) -} - func (s *BgpServer) AddNeighbor(c *config.Neighbor) error { return s.mgmtOperation(func() error { return s.addNeighbor(c) }, true) } -func (s *BgpServer) AddDynamicNeighbor(c *config.DynamicNeighbor) error { - return s.mgmtOperation(func() error { - s.peerGroupMap[c.Config.PeerGroup].AddDynamicNeighbor(c) - return nil - }, true) -} - -func (server *BgpServer) deletePeerGroup(pg *config.PeerGroup) error { - name := pg.Config.PeerGroupName - - if _, y := server.peerGroupMap[name]; !y { - return fmt.Errorf("Can't delete a peer-group %s which does not exist", name) - } - - log.WithFields(log.Fields{ - "Topic": "Peer", - "Name": name, - }).Info("Delete a peer group configuration") - - delete(server.peerGroupMap, name) - return nil -} - func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) error { - if c.Config.PeerGroup != "" { - _, y := server.peerGroupMap[c.Config.PeerGroup] - if y { - server.peerGroupMap[c.Config.PeerGroup].DeleteMember(*c) - } - } - - addr, err := config.ExtractNeighborAddress(c) - if err != nil { - return err - } - + addr := c.Config.NeighborAddress if intf := c.Config.NeighborInterface; intf != "" { var err error addr, err = config.GetIPv6LinkLocalNeighborAddress(intf) @@ -1814,151 +1674,130 @@ func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) n.fsm.sendNotification(code, subcode, nil, "") n.stopPeerRestarting() - go n.stopFSM() + go func(addr string) { + failed := false + t1 := time.AfterFunc(time.Minute*5, func() { + log.WithFields(log.Fields{ + "Topic": "Peer", + }).Warnf("Failed to free the fsm.h.t for %s", addr) + failed = true + }) + n.fsm.h.t.Kill(nil) + n.fsm.h.t.Wait() + t1.Stop() + if !failed { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Debug("freed fsm.h.t") + cleanInfiniteChannel(n.outgoing) + } + failed = false + t2 := time.AfterFunc(time.Minute*5, func() { + log.WithFields(log.Fields{ + "Topic": "Peer", + }).Warnf("Failed to free the fsm.t for %s", addr) + failed = true + }) + n.fsm.t.Kill(nil) + n.fsm.t.Wait() + t2.Stop() + if !failed { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Debug("freed fsm.t") + } + }(addr) delete(server.neighborMap, addr) server.dropPeerAllRoutes(n, n.configuredRFlist()) return nil } -func (s *BgpServer) DeletePeerGroup(c *config.PeerGroup) error { - return s.mgmtOperation(func() error { - name := c.Config.PeerGroupName - for _, n := range s.neighborMap { - if n.fsm.pConf.Config.PeerGroup == name { - return fmt.Errorf("failed to delete peer-group %s: neighbor %s is in use", name, n.ID()) - } - } - return s.deletePeerGroup(c) - }, true) -} - func (s *BgpServer) DeleteNeighbor(c *config.Neighbor) error { return s.mgmtOperation(func() error { return s.deleteNeighbor(c, bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_PEER_DECONFIGURED) }, true) } -func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) { - name := pg.Config.PeerGroupName - - _, ok := s.peerGroupMap[name] - if !ok { - return false, fmt.Errorf("Peer-group %s doesn't exist.", name) - } - s.peerGroupMap[name].Conf = pg - - for _, n := range s.peerGroupMap[name].members { - c := n - u, err := s.updateNeighbor(&c) - if err != nil { - return needsSoftResetIn, err - } - needsSoftResetIn = needsSoftResetIn || u - } - return needsSoftResetIn, nil -} - -func (s *BgpServer) UpdatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) { +func (s *BgpServer) UpdateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) { err = s.mgmtOperation(func() error { - needsSoftResetIn, err = s.updatePeerGroup(pg) - return err - }, true) - return needsSoftResetIn, err -} - -func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) { - if c.Config.PeerGroup != "" { - if err := config.OverwriteNeighborConfigWithPeerGroup(c, s.peerGroupMap[c.Config.PeerGroup].Conf); err != nil { - return needsSoftResetIn, err + addr := c.Config.NeighborAddress + peer, ok := s.neighborMap[addr] + if !ok { + return fmt.Errorf("Neighbor that has %v doesn't exist.", addr) } - } - addr, err := config.ExtractNeighborAddress(c) - if err != nil { - return needsSoftResetIn, err - } + if !peer.fsm.pConf.ApplyPolicy.Equal(&c.ApplyPolicy) { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Info("Update ApplyPolicy") + s.policy.Reset(nil, map[string]config.ApplyPolicy{peer.ID(): c.ApplyPolicy}) + peer.fsm.pConf.ApplyPolicy = c.ApplyPolicy + needsSoftResetIn = true + } + original := peer.fsm.pConf - peer, ok := s.neighborMap[addr] - if !ok { - return needsSoftResetIn, fmt.Errorf("Neighbor that has %v doesn't exist.", addr) - } - - if !peer.fsm.pConf.ApplyPolicy.Equal(&c.ApplyPolicy) { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": addr, - }).Info("Update ApplyPolicy") - s.policy.Reset(nil, map[string]config.ApplyPolicy{peer.ID(): c.ApplyPolicy}) - peer.fsm.pConf.ApplyPolicy = c.ApplyPolicy - needsSoftResetIn = true - } - original := peer.fsm.pConf - - if !original.AsPathOptions.Config.Equal(&c.AsPathOptions.Config) { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - }).Info("Update aspath options") - peer.fsm.pConf.AsPathOptions = c.AsPathOptions - needsSoftResetIn = true - } - - if !original.Config.Equal(&c.Config) || !original.Transport.Config.Equal(&c.Transport.Config) || config.CheckAfiSafisChange(original.AfiSafis, c.AfiSafis) { - sub := uint8(bgp.BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE) - if original.Config.AdminDown != c.Config.AdminDown { - sub = bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN - state := "Admin Down" - if c.Config.AdminDown == false { - state = "Admin Up" - } + if !original.AsPathOptions.Config.Equal(&c.AsPathOptions.Config) { log.WithFields(log.Fields{ "Topic": "Peer", "Key": peer.ID(), - "State": state, - }).Info("Update admin-state configuration") - } else if original.Config.PeerAs != c.Config.PeerAs { - sub = bgp.BGP_ERROR_SUB_PEER_DECONFIGURED + }).Info("Update aspath options") + peer.fsm.pConf.AsPathOptions = c.AsPathOptions + needsSoftResetIn = true } - if err = s.deleteNeighbor(peer.fsm.pConf, bgp.BGP_ERROR_CEASE, sub); err != nil { + + if !original.Config.Equal(&c.Config) || !original.Transport.Config.Equal(&c.Transport.Config) || config.CheckAfiSafisChange(original.AfiSafis, c.AfiSafis) { + sub := uint8(bgp.BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE) + if original.Config.AdminDown != c.Config.AdminDown { + sub = bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN + state := "Admin Down" + if c.Config.AdminDown == false { + state = "Admin Up" + } + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": peer.ID(), + "State": state, + }).Info("Update admin-state configuration") + } else if original.Config.PeerAs != c.Config.PeerAs { + sub = bgp.BGP_ERROR_SUB_PEER_DECONFIGURED + } + if err = s.deleteNeighbor(peer.fsm.pConf, bgp.BGP_ERROR_CEASE, sub); err != nil { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Error(err) + return err + } + err = s.addNeighbor(c) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Peer", + "Key": addr, + }).Error(err) + } + return err + } + + if !original.Timers.Config.Equal(&c.Timers.Config) { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": addr, - }).Error(err) - return needsSoftResetIn, err + "Key": peer.ID(), + }).Info("Update timer configuration") + peer.fsm.pConf.Timers.Config = c.Timers.Config } - err = s.addNeighbor(c) + + err = peer.updatePrefixLimitConfig(c.AfiSafis) if err != nil { log.WithFields(log.Fields{ "Topic": "Peer", "Key": addr, }).Error(err) + // rollback to original state + peer.fsm.pConf = original } - return needsSoftResetIn, err - } - - if !original.Timers.Config.Equal(&c.Timers.Config) { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": peer.ID(), - }).Info("Update timer configuration") - peer.fsm.pConf.Timers.Config = c.Timers.Config - } - - err = peer.updatePrefixLimitConfig(c.AfiSafis) - if err != nil { - log.WithFields(log.Fields{ - "Topic": "Peer", - "Key": addr, - }).Error(err) - // rollback to original state - peer.fsm.pConf = original - } - return needsSoftResetIn, err -} - -func (s *BgpServer) UpdateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) { - err = s.mgmtOperation(func() error { - needsSoftResetIn, err = s.updateNeighbor(c) return err }, true) return needsSoftResetIn, err @@ -2025,10 +1864,10 @@ func (s *BgpServer) setAdminState(addr, communication string, enable bool) error case peer.fsm.adminStateCh <- *stateOp: log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.fsm.pConf.State.NeighborAddress, + "Key": peer.fsm.pConf.Config.NeighborAddress, }).Debug(message) default: - log.Warning("previous request is still remaining. : ", peer.fsm.pConf.State.NeighborAddress) + log.Warning("previous request is still remaining. : ", peer.fsm.pConf.Config.NeighborAddress) } } if enable { @@ -2291,7 +2130,6 @@ const ( WATCH_EVENT_TYPE_POST_UPDATE WatchEventType = "postupdate" WATCH_EVENT_TYPE_PEER_STATE WatchEventType = "peerstate" WATCH_EVENT_TYPE_TABLE WatchEventType = "table" - WATCH_EVENT_TYPE_RECV_MSG WatchEventType = "receivedmessage" ) type WatchEvent interface { @@ -2342,18 +2180,6 @@ type WatchEventBestPath struct { MultiPathList [][]*table.Path } -type WatchEventMessage struct { - Message *bgp.BGPMessage - PeerAS uint32 - LocalAS uint32 - PeerAddress net.IP - LocalAddress net.IP - PeerID net.IP - FourBytesAs bool - Timestamp time.Time - IsSent bool -} - type watchOptions struct { bestpath bool preUpdate bool @@ -2364,8 +2190,6 @@ type watchOptions struct { initPostUpdate bool initPeerState bool tableName string - recvMessage bool - sentMessage bool } type WatchOption func(*watchOptions) @@ -2412,19 +2236,6 @@ func WatchTableName(name string) WatchOption { } } -func WatchMessage(isSent bool) WatchOption { - return func(o *watchOptions) { - if isSent { - log.WithFields(log.Fields{ - "Topic": "Server", - }).Warn("watch event for sent messages is not implemented yet") - // o.sentMessage = true - } else { - o.recvMessage = true - } - } -} - type Watcher struct { opts watchOptions realCh chan WatchEvent @@ -2648,9 +2459,6 @@ func (s *BgpServer) Watch(opts ...WatchOption) (w *Watcher) { } } } - if w.opts.recvMessage { - register(WATCH_EVENT_TYPE_RECV_MSG, w) - } go w.loop() return nil diff --git a/vendor/github.com/osrg/gobgp/server/server_test.go b/vendor/github.com/osrg/gobgp/server/server_test.go index e5deb975..9caf8a62 100644 --- a/vendor/github.com/osrg/gobgp/server/server_test.go +++ b/vendor/github.com/osrg/gobgp/server/server_test.go @@ -16,10 +16,10 @@ package server import ( + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "net" "runtime" @@ -31,17 +31,13 @@ func TestModPolicyAssign(t *testing.T) { assert := assert.New(t) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ + s.Start(&config.Global{ Config: config.GlobalConfig{ As: 1, RouterId: "1.1.1.1", - Port: -1, }, }) - assert.Nil(err) - defer s.Stop() - - err = s.AddPolicy(&table.Policy{Name: "p1"}, false) + err := s.AddPolicy(&table.Policy{Name: "p1"}, false) assert.Nil(err) err = s.AddPolicy(&table.Policy{Name: "p2"}, false) @@ -66,16 +62,13 @@ func TestMonitor(test *testing.T) { assert := assert.New(test) s := NewBgpServer() go s.Serve() - err := s.Start(&config.Global{ + s.Start(&config.Global{ Config: config.GlobalConfig{ As: 1, RouterId: "1.1.1.1", Port: 10179, }, }) - assert.Nil(err) - defer s.Stop() - n := &config.Neighbor{ Config: config.NeighborConfig{ NeighborAddress: "127.0.0.1", @@ -87,21 +80,18 @@ func TestMonitor(test *testing.T) { }, }, } - err = s.AddNeighbor(n) - assert.Nil(err) - + if err := s.AddNeighbor(n); err != nil { + log.Fatal(err) + } t := NewBgpServer() go t.Serve() - err = t.Start(&config.Global{ + t.Start(&config.Global{ Config: config.GlobalConfig{ As: 2, RouterId: "2.2.2.2", Port: -1, }, }) - assert.Nil(err) - defer t.Stop() - m := &config.Neighbor{ Config: config.NeighborConfig{ NeighborAddress: "127.0.0.1", @@ -113,8 +103,9 @@ func TestMonitor(test *testing.T) { }, }, } - err = t.AddNeighbor(m) - assert.Nil(err) + if err := t.AddNeighbor(m); err != nil { + log.Fatal(err) + } for { time.Sleep(time.Second) @@ -168,10 +159,6 @@ func TestNumGoroutineWithAddDeleteNeighbor(t *testing.T) { }, }) assert.Nil(err) - defer s.Stop() - - // wait a few seconds to avoid taking effect from other test cases. - time.Sleep(time.Second * 5) num := runtime.NumGoroutine() @@ -356,261 +343,3 @@ func TestFilterpathWithRejectPolicy(t *testing.T) { } } - -func TestPeerGroup(test *testing.T) { - assert := assert.New(test) - log.SetLevel(log.DebugLevel) - s := NewBgpServer() - go s.Serve() - err := s.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, - }, - }) - assert.Nil(err) - defer s.Stop() - - g := &config.PeerGroup{ - Config: config.PeerGroupConfig{ - PeerAs: 2, - PeerGroupName: "g", - }, - } - err = s.AddPeerGroup(g) - assert.Nil(err) - - n := &config.Neighbor{ - Config: config.NeighborConfig{ - NeighborAddress: "127.0.0.1", - PeerGroup: "g", - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - PassiveMode: true, - }, - }, - } - configured := map[string]interface{}{ - "config": map[string]interface{}{ - "neigbor-address": "127.0.0.1", - "peer-group": "g", - }, - "transport": map[string]interface{}{ - "config": map[string]interface{}{ - "passive-mode": true, - }, - }, - } - config.RegisterConfiguredFields("127.0.0.1", configured) - err = s.AddNeighbor(n) - assert.Nil(err) - - t := NewBgpServer() - go t.Serve() - err = t.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, - }, - }) - assert.Nil(err) - defer t.Stop() - - m := &config.Neighbor{ - Config: config.NeighborConfig{ - NeighborAddress: "127.0.0.1", - PeerAs: 1, - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - RemotePort: 10179, - }, - }, - } - err = t.AddNeighbor(m) - assert.Nil(err) - - for { - time.Sleep(time.Second) - if t.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { - break - } - } -} - -func TestDynamicNeighbor(t *testing.T) { - assert := assert.New(t) - log.SetLevel(log.DebugLevel) - s1 := NewBgpServer() - go s1.Serve() - err := s1.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, - }, - }) - assert.Nil(err) - defer s1.Stop() - - g := &config.PeerGroup{ - Config: config.PeerGroupConfig{ - PeerAs: 2, - PeerGroupName: "g", - }, - } - err = s1.AddPeerGroup(g) - assert.Nil(err) - - d := &config.DynamicNeighbor{ - Config: config.DynamicNeighborConfig{ - Prefix: "127.0.0.0/24", - PeerGroup: "g", - }, - } - err = s1.AddDynamicNeighbor(d) - assert.Nil(err) - - s2 := NewBgpServer() - go s2.Serve() - err = s2.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, - }, - }) - assert.Nil(err) - defer s2.Stop() - - m := &config.Neighbor{ - Config: config.NeighborConfig{ - NeighborAddress: "127.0.0.1", - PeerAs: 1, - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - RemotePort: 10179, - }, - }, - } - err = s2.AddNeighbor(m) - - assert.Nil(err) - - for { - time.Sleep(time.Second) - if s2.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { - break - } - } -} - -func TestGracefulRestartTimerExpired(t *testing.T) { - assert := assert.New(t) - s1 := NewBgpServer() - go s1.Serve() - err := s1.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 1, - RouterId: "1.1.1.1", - Port: 10179, - }, - }) - assert.Nil(err) - defer s1.Stop() - - n := &config.Neighbor{ - Config: config.NeighborConfig{ - NeighborAddress: "127.0.0.1", - PeerAs: 2, - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - PassiveMode: true, - }, - }, - GracefulRestart: config.GracefulRestart{ - Config: config.GracefulRestartConfig{ - Enabled: true, - RestartTime: 10, - }, - }, - } - err = s1.AddNeighbor(n) - assert.Nil(err) - - s2 := NewBgpServer() - go s2.Serve() - err = s2.Start(&config.Global{ - Config: config.GlobalConfig{ - As: 2, - RouterId: "2.2.2.2", - Port: -1, - }, - }) - assert.Nil(err) - defer s2.Stop() - - m := &config.Neighbor{ - Config: config.NeighborConfig{ - NeighborAddress: "127.0.0.1", - PeerAs: 1, - }, - Transport: config.Transport{ - Config: config.TransportConfig{ - RemotePort: 10179, - }, - }, - GracefulRestart: config.GracefulRestart{ - Config: config.GracefulRestartConfig{ - Enabled: true, - RestartTime: 10, - }, - }, - } - err = s2.AddNeighbor(m) - assert.Nil(err) - - // Waiting for BGP session established. - for { - time.Sleep(time.Second) - if s2.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED { - break - } - } - - // Force TCP session disconnected in order to cause Graceful Restart at s1 - // side. - for _, n := range s2.neighborMap { - n.fsm.conn.Close() - } - s2.Stop() - - time.Sleep(5 * time.Second) - - // Create dummy session which does NOT send BGP OPEN message in order to - // cause Graceful Restart timer expired. - var conn net.Conn - for { - time.Sleep(time.Second) - var err error - conn, err = net.Dial("tcp", "127.0.0.1:10179") - if err != nil { - log.Warn("net.Dial:", err) - } - break - } - defer conn.Close() - - // Waiting for Graceful Restart timer expired and moving on to IDLE state. - for { - time.Sleep(time.Second) - if s1.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_IDLE { - break - } - } -} diff --git a/vendor/github.com/osrg/gobgp/server/sockopt.go b/vendor/github.com/osrg/gobgp/server/sockopt.go index 2f6a8bb6..34d9ed5e 100644 --- a/vendor/github.com/osrg/gobgp/server/sockopt.go +++ b/vendor/github.com/osrg/gobgp/server/sockopt.go @@ -29,10 +29,6 @@ func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { return fmt.Errorf("setting ttl is not supported") } -func SetTcpMinTTLSockopts(conn *net.TCPConn, ttl int) error { - return fmt.Errorf("setting min ttl is not supported") -} - func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { return nil, fmt.Errorf("md5 active connection unsupported") } diff --git a/vendor/github.com/osrg/gobgp/server/sockopt_bsd.go b/vendor/github.com/osrg/gobgp/server/sockopt_bsd.go index a9f9d61f..62514edb 100644 --- a/vendor/github.com/osrg/gobgp/server/sockopt_bsd.go +++ b/vendor/github.com/osrg/gobgp/server/sockopt_bsd.go @@ -25,8 +25,7 @@ import ( ) const ( - TCP_MD5SIG = 0x10 // TCP MD5 Signature (RFC2385) - IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082) + TCP_MD5SIG = 0x10 ) func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error { @@ -50,7 +49,13 @@ func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error return nil } -func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { +func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { + level := syscall.IPPROTO_IP + name := syscall.IP_TTL + if strings.Contains(conn.RemoteAddr().String(), "[") { + level = syscall.IPPROTO_IPV6 + name = syscall.IPV6_UNICAST_HOPS + } fi, err := conn.File() defer fi.Close() if err != nil { @@ -59,27 +64,7 @@ func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { if conn, err := net.FileConn(fi); err == nil { defer conn.Close() } - return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, value)) -} - -func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_TTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = syscall.IPV6_UNICAST_HOPS - } - return setTcpSockoptInt(conn, level, name, ttl) -} - -func SetTcpMinTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_MINTTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = IPV6_MINHOPCOUNT - } - return setTcpSockoptInt(conn, level, name, ttl) + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, ttl)) } func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { diff --git a/vendor/github.com/osrg/gobgp/server/sockopt_linux.go b/vendor/github.com/osrg/gobgp/server/sockopt_linux.go index 0dc4cd5f..1db559b5 100644 --- a/vendor/github.com/osrg/gobgp/server/sockopt_linux.go +++ b/vendor/github.com/osrg/gobgp/server/sockopt_linux.go @@ -26,8 +26,7 @@ import ( ) const ( - TCP_MD5SIG = 14 // TCP MD5 Signature (RFC2385) - IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082) + TCP_MD5SIG = 14 ) type tcpmd5sig struct { @@ -75,7 +74,13 @@ func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error return nil } -func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { +func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { + level := syscall.IPPROTO_IP + name := syscall.IP_TTL + if strings.Contains(conn.RemoteAddr().String(), "[") { + level = syscall.IPPROTO_IPV6 + name = syscall.IPV6_UNICAST_HOPS + } fi, err := conn.File() defer fi.Close() if err != nil { @@ -84,27 +89,7 @@ func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { if conn, err := net.FileConn(fi); err == nil { defer conn.Close() } - return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, value)) -} - -func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_TTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = syscall.IPV6_UNICAST_HOPS - } - return setTcpSockoptInt(conn, level, name, ttl) -} - -func SetTcpMinTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_MINTTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = IPV6_MINHOPCOUNT - } - return setTcpSockoptInt(conn, level, name, ttl) + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, ttl)) } func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { diff --git a/vendor/github.com/osrg/gobgp/server/sockopt_openbsd.go b/vendor/github.com/osrg/gobgp/server/sockopt_openbsd.go index 6dd26e59..16ed2c3d 100644 --- a/vendor/github.com/osrg/gobgp/server/sockopt_openbsd.go +++ b/vendor/github.com/osrg/gobgp/server/sockopt_openbsd.go @@ -19,7 +19,7 @@ package server import ( "encoding/binary" "fmt" - log "github.com/sirupsen/logrus" + log "github.com/Sirupsen/logrus" "net" "os" "strings" @@ -348,8 +348,7 @@ func saDelete(address string) error { } const ( - TCP_MD5SIG = 0x4 // TCP MD5 Signature (RFC2385) - IPV6_MINHOPCOUNT = 73 // Generalized TTL Security Mechanism (RFC5082) + TCP_MD5SIG = 0x4 ) func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error { @@ -374,7 +373,13 @@ func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error return saDelete(address) } -func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { +func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { + level := syscall.IPPROTO_IP + name := syscall.IP_TTL + if strings.Contains(conn.RemoteAddr().String(), "[") { + level = syscall.IPPROTO_IPV6 + name = syscall.IPV6_UNICAST_HOPS + } fi, err := conn.File() defer fi.Close() if err != nil { @@ -383,27 +388,7 @@ func setTcpSockoptInt(conn *net.TCPConn, level int, name int, value int) error { if conn, err := net.FileConn(fi); err == nil { defer conn.Close() } - return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, value)) -} - -func SetTcpTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_TTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = syscall.IPV6_UNICAST_HOPS - } - return setTcpSockoptInt(conn, level, name, ttl) -} - -func SetTcpMinTTLSockopts(conn *net.TCPConn, ttl int) error { - level := syscall.IPPROTO_IP - name := syscall.IP_MINTTL - if strings.Contains(conn.RemoteAddr().String(), "[") { - level = syscall.IPPROTO_IPV6 - name = IPV6_MINHOPCOUNT - } - return setTcpSockoptInt(conn, level, name, ttl) + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(int(fi.Fd()), level, name, ttl)) } func DialTCPTimeoutWithMD5Sig(host string, port int, localAddr, key string, msec int) (*net.TCPConn, error) { diff --git a/vendor/github.com/osrg/gobgp/server/zclient.go b/vendor/github.com/osrg/gobgp/server/zclient.go index 85d238c8..d432b96d 100644 --- a/vendor/github.com/osrg/gobgp/server/zclient.go +++ b/vendor/github.com/osrg/gobgp/server/zclient.go @@ -17,10 +17,10 @@ package server import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" "github.com/osrg/gobgp/zebra" - log "github.com/sirupsen/logrus" "net" "strconv" "strings" diff --git a/vendor/github.com/osrg/gobgp/table/destination.go b/vendor/github.com/osrg/gobgp/table/destination.go index af74f8fd..9664fdbc 100644 --- a/vendor/github.com/osrg/gobgp/table/destination.go +++ b/vendor/github.com/osrg/gobgp/table/destination.go @@ -23,9 +23,9 @@ import ( "net" "sort" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" ) var SelectionOptions config.RouteSelectionOptionsConfig @@ -127,7 +127,7 @@ func (i *PeerInfo) String() string { func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo { id := net.ParseIP(string(p.RouteReflector.Config.RouteReflectorClusterId)).To4() // exclude zone info - naddr, _ := net.ResolveIPAddr("ip", p.State.NeighborAddress) + naddr, _ := net.ResolveIPAddr("ip", p.Config.NeighborAddress) return &PeerInfo{ AS: p.Config.PeerAs, LocalAS: g.Config.As, diff --git a/vendor/github.com/osrg/gobgp/table/message.go b/vendor/github.com/osrg/gobgp/table/message.go index 30a75d24..af4affa6 100644 --- a/vendor/github.com/osrg/gobgp/table/message.go +++ b/vendor/github.com/osrg/gobgp/table/message.go @@ -17,8 +17,8 @@ package table import ( "bytes" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" "hash/fnv" "reflect" ) diff --git a/vendor/github.com/osrg/gobgp/table/path.go b/vendor/github.com/osrg/gobgp/table/path.go index b97ca40c..b2984fe4 100644 --- a/vendor/github.com/osrg/gobgp/table/path.go +++ b/vendor/github.com/osrg/gobgp/table/path.go @@ -24,10 +24,10 @@ import ( "sort" "time" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/satori/go.uuid" - log "github.com/sirupsen/logrus" ) const ( @@ -258,7 +258,7 @@ func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInf } else { log.WithFields(log.Fields{ "Topic": "Peer", - "Key": peer.State.NeighborAddress, + "Key": peer.Config.NeighborAddress, }).Warnf("invalid peer type: %d", peer.State.PeerType) } return path diff --git a/vendor/github.com/osrg/gobgp/table/policy.go b/vendor/github.com/osrg/gobgp/table/policy.go index a73fa57a..2cca91a9 100644 --- a/vendor/github.com/osrg/gobgp/table/policy.go +++ b/vendor/github.com/osrg/gobgp/table/policy.go @@ -26,10 +26,10 @@ import ( "strings" "sync" + log "github.com/Sirupsen/logrus" "github.com/armon/go-radix" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" ) type PolicyOptions struct { diff --git a/vendor/github.com/osrg/gobgp/table/policy_test.go b/vendor/github.com/osrg/gobgp/table/policy_test.go index c55eb1c8..a846dabe 100644 --- a/vendor/github.com/osrg/gobgp/table/policy_test.go +++ b/vendor/github.com/osrg/gobgp/table/policy_test.go @@ -24,9 +24,9 @@ import ( "testing" "time" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) diff --git a/vendor/github.com/osrg/gobgp/table/table.go b/vendor/github.com/osrg/gobgp/table/table.go index c1ed3a29..6e90faf7 100644 --- a/vendor/github.com/osrg/gobgp/table/table.go +++ b/vendor/github.com/osrg/gobgp/table/table.go @@ -20,9 +20,9 @@ import ( "net" "sort" + log "github.com/Sirupsen/logrus" "github.com/armon/go-radix" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" ) type LookupOption uint8 diff --git a/vendor/github.com/osrg/gobgp/table/table_manager.go b/vendor/github.com/osrg/gobgp/table/table_manager.go index e41c2798..3060dda0 100644 --- a/vendor/github.com/osrg/gobgp/table/table_manager.go +++ b/vendor/github.com/osrg/gobgp/table/table_manager.go @@ -18,8 +18,8 @@ package table import ( "bytes" "fmt" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" "net" "time" ) diff --git a/vendor/github.com/osrg/gobgp/table/table_manager_test.go b/vendor/github.com/osrg/gobgp/table/table_manager_test.go index 2a8ed2f6..21d15026 100644 --- a/vendor/github.com/osrg/gobgp/table/table_manager_test.go +++ b/vendor/github.com/osrg/gobgp/table/table_manager_test.go @@ -17,8 +17,8 @@ package table import ( _ "fmt" + log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bgp" - log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "net" "os" diff --git a/vendor/github.com/osrg/gobgp/test/lib/base.py b/vendor/github.com/osrg/gobgp/test/lib/base.py index 0421e9d7..907050bc 100644 --- a/vendor/github.com/osrg/gobgp/test/lib/base.py +++ b/vendor/github.com/osrg/gobgp/test/lib/base.py @@ -103,7 +103,7 @@ def make_gobgp_ctn(tag='gobgp', local_gobgp_path='', from_image='osrg/quagga'): c = CmdBuffer() c << 'FROM {0}'.format(from_image) - c << 'RUN go get -d github.com/osrg/gobgp/...; exit 0' + c << 'RUN go get -d github.com/osrg/gobgp/...' c << 'RUN rm -rf /go/src/github.com/osrg/gobgp' c << 'ADD gobgp /go/src/github.com/osrg/gobgp/' c << 'RUN go get github.com/osrg/gobgp/...' diff --git a/vendor/github.com/osrg/gobgp/test/scenario_test/graceful_restart_test.py b/vendor/github.com/osrg/gobgp/test/scenario_test/graceful_restart_test.py index 60e10437..4f3c1563 100644 --- a/vendor/github.com/osrg/gobgp/test/scenario_test/graceful_restart_test.py +++ b/vendor/github.com/osrg/gobgp/test/scenario_test/graceful_restart_test.py @@ -26,7 +26,6 @@ from lib.noseplugin import OptionParser, parser_option from lib import base from lib.base import ( - BGP_FSM_IDLE, BGP_FSM_ACTIVE, BGP_FSM_ESTABLISHED, ) @@ -129,47 +128,6 @@ class GoBGPTestBase(unittest.TestCase): g2 = self.bgpds['g2'] self.assertTrue(len(g2.get_global_rib()) == 0) - def test_07_multineighbor_established(self): - g1 = self.bgpds['g1'] - g2 = self.bgpds['g2'] - g3 = self.bgpds['g3'] - - g1._start_gobgp() - - g1.del_peer(g2) - g1.del_peer(g3) - g2.del_peer(g1) - g3.del_peer(g1) - g1.add_peer(g2, graceful_restart=True, llgr=True) - g1.add_peer(g3, graceful_restart=True, llgr=True) - g2.add_peer(g1, graceful_restart=True, llgr=True) - g3.add_peer(g1, graceful_restart=True, llgr=True) - - g2.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g1) - g3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g1) - - def test_08_multineighbor_graceful_restart(self): - g1 = self.bgpds['g1'] - g2 = self.bgpds['g2'] - g3 = self.bgpds['g3'] - - g1.graceful_restart() - g2.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) - g3.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) - - g1._start_gobgp(graceful_restart=True) - - count = 0 - while ((g1.get_neighbor_state(g2) != BGP_FSM_ESTABLISHED) - or (g1.get_neighbor_state(g3) != BGP_FSM_ESTABLISHED)): - count += 1 - # assert connections are not refused - self.assertTrue(g1.get_neighbor_state(g2) != BGP_FSM_IDLE) - self.assertTrue(g1.get_neighbor_state(g3) != BGP_FSM_IDLE) - if count > 120: - raise Exception('timeout') - time.sleep(1) - if __name__ == '__main__': output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/Makefile b/vendor/github.com/osrg/gobgp/tools/grpc/cpp/Makefile index d50df9d9..2fcb5c8c 100644 --- a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/Makefile +++ b/vendor/github.com/osrg/gobgp/tools/grpc/cpp/Makefile @@ -1,17 +1,7 @@ -HOST_SYSTEM = $(shell uname | cut -f 1 -d_) -SYSTEM ?= $(HOST_SYSTEM) CXX = g++ -CPPFLAGS += -I/usr/local/include -pthread +CPPFLAGS += -I/opt/protobuf_3.0.0_alpha4/include -I/opt/grpc/include -pthread CXXFLAGS += -std=c++11 -ifeq ($(SYSTEM),Darwin) -LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \ - -lgrpc++_reflection \ - -lprotobuf -lpthread -ldl -else -LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \ - -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \ - -lprotobuf -lpthread -ldl -endif +LDFLAGS += -L/opt/grpc/lib -L/opt/protobuf_3.0.0_alpha4/lib -lgrpc++_unsecure -lgrpc -lgpr -lprotobuf -lpthread -ldl PROTOC = protoc GRPC_CPP_PLUGIN = grpc_cpp_plugin GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` @@ -23,7 +13,7 @@ vpath %.proto $(PROTOS_PATH) all: system-check gobgp_api_client gobgp_api_client: gobgp_api_client.pb.o gobgp_api_client.grpc.pb.o gobgp_api_client.o - $(CXX) $^ $(LDFLAGS) -L. -lgobgp -o $@ + $(CXX) $^ $(LDFLAGS) -L. -lgobgp -o $@ %.grpc.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $< diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/build.sh b/vendor/github.com/osrg/gobgp/tools/grpc/cpp/build.sh deleted file mode 100644 index f1c7a92c..00000000 --- a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -GOBGP_PATH=${GOPATH}/src/github.com/osrg/gobgp - -cd ${GOBGP_PATH}/gobgp/lib -go build -buildmode=c-shared -o libgobgp.so *.go -cd ${GOBGP_PATH}/tools/grpc/cpp -ln -s ${GOBGP_PATH}/gobgp/lib/libgobgp.h -ln -s ${GOBGP_PATH}/gobgp/lib/libgobgp.so -ln -s ${GOBGP_PATH}/api/gobgp.proto gobgp_api_client.proto -make diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/gobgp_api_client.cc b/vendor/github.com/osrg/gobgp/tools/grpc/cpp/gobgp_api_client.cc index b704c932..413c140c 100644 --- a/vendor/github.com/osrg/gobgp/tools/grpc/cpp/gobgp_api_client.cc +++ b/vendor/github.com/osrg/gobgp/tools/grpc/cpp/gobgp_api_client.cc @@ -25,44 +25,218 @@ using gobgpapi::GobgpApi; class GrpcClient { public: GrpcClient(std::shared_ptr channel) : stub_(GobgpApi::NewStub(channel)) {} + void GetAllActiveAnnounces(unsigned int route_family) { + ClientContext context; + gobgpapi::Table table; - std::string GetNeighbor() { - gobgpapi::GetNeighborRequest request; + table.set_family(route_family); + // We could specify certain neighbor here + table.set_name(""); + table.set_type(gobgpapi::Resource::GLOBAL); + + gobgpapi::Table response_table; + + auto status = stub_->GetRib(&context, table, &response_table); + + if (!status.ok()) { + // error_message + std::cout << "Problem with RPC: " << status.error_code() << " message " << status.error_message() << std::endl; + return; + } else { + // std::cout << "RPC working well" << std::endl; + } + + std::cout << "List of announced prefixes for route family: " << route_family << std::endl << std::endl; + + for (auto current_destination : response_table.destinations()) { + std::cout << "Prefix: " << current_destination.prefix() << std::endl; + + //std::cout << "Paths size: " << current_destination.paths_size() << std::endl; + + gobgpapi::Path my_path = current_destination.paths(0); + + // std::cout << "Pattrs size: " << my_path.pattrs_size() << std::endl; + + buf my_nlri; + my_nlri.value = (char*)my_path.nlri().c_str(); + my_nlri.len = my_path.nlri().size(); + + path_t gobgp_lib_path; + gobgp_lib_path.nlri = my_nlri; + // Not used in library code! + gobgp_lib_path.path_attributes_cap = 0; + gobgp_lib_path.path_attributes_len = my_path.pattrs_size(); + + buf* my_path_attributes[ my_path.pattrs_size() ]; + for (int i = 0; i < my_path.pattrs_size(); i++) { + my_path_attributes[i] = (buf*)malloc(sizeof(buf)); + my_path_attributes[i]->len = my_path.pattrs(i).size(); + my_path_attributes[i]->value = (char*)my_path.pattrs(i).c_str(); + } + + gobgp_lib_path.path_attributes = my_path_attributes; + + std::cout << "NLRI: " << decode_path(&gobgp_lib_path) << std::endl; + } + } + + void AnnounceFlowSpecPrefix(bool withdraw) { + const gobgpapi::ModPathArguments current_mod_path_arguments; + + unsigned int AFI_IP = 1; + unsigned int SAFI_FLOW_SPEC_UNICAST = 133; + unsigned int ipv4_flow_spec_route_family = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST; + + gobgpapi::Path* current_path = new gobgpapi::Path; + current_path->set_is_withdraw(withdraw); + + /* + buf: + char *value; + int len; + + path: + buf nlri; + buf** path_attributes; + int path_attributes_len; + int path_attributes_cap; + */ + + path* path_c_struct = serialize_path(ipv4_flow_spec_route_family, (char*)"match destination 10.0.0.0/24 protocol tcp source 20.0.0.0/24 then redirect 10:10"); + + // printf("Decoded NLRI output: %s, length %d raw string length: %d\n", decode_path(path_c_struct), path_c_struct->nlri.len, strlen(path_c_struct->nlri.value)); + + for (int path_attribute_number = 0; path_attribute_number < path_c_struct->path_attributes_len; path_attribute_number++) { + current_path->add_pattrs(path_c_struct->path_attributes[path_attribute_number]->value, + path_c_struct->path_attributes[path_attribute_number]->len); + } + + current_path->set_nlri(path_c_struct->nlri.value, path_c_struct->nlri.len); + + gobgpapi::ModPathsArguments request; + request.set_resource(gobgpapi::Resource::GLOBAL); + + google::protobuf::RepeatedPtrField< ::gobgpapi::Path >* current_path_list = request.mutable_paths(); + current_path_list->AddAllocated(current_path); + request.set_name(""); ClientContext context; - gobgpapi::GetNeighborResponse response; - grpc::Status status = stub_->GetNeighbor(&context, request, &response); + gobgpapi::Error return_error; + + // result is a std::unique_ptr > + auto send_stream = stub_->ModPaths(&context, &return_error); + + bool write_result = send_stream->Write(request); + + if (!write_result) { + std::cout << "Write to API failed\n"; + } + + // Finish all writes + send_stream->WritesDone(); + + auto status = send_stream->Finish(); + + if (status.ok()) { + //std::cout << "modpath executed correctly" << std::cout; + } else { + std::cout << "modpath failed with code: " << status.error_code() + << " message " << status.error_message() << std::endl; + } + } + + void AnnounceUnicastPrefix(bool withdraw) { + const gobgpapi::ModPathArguments current_mod_path_arguments; + + unsigned int AFI_IP = 1; + unsigned int SAFI_UNICAST = 1; + unsigned int ipv4_unicast_route_family = AFI_IP<<16 | SAFI_UNICAST; + + gobgpapi::Path* current_path = new gobgpapi::Path; + current_path->set_is_withdraw(withdraw); + + /* + buf: + char *value; + int len; + + path: + buf nlri; + buf** path_attributes; + int path_attributes_len; + int path_attributes_cap; + */ + + // 10.10.20.33/22 nexthop 10.10.1.99/32 + path* path_c_struct = serialize_path(ipv4_unicast_route_family, (char*)"10.10.20.33/22"); + + // printf("Decoded NLRI output: %s, length %d raw string length: %d\n", decode_path(path_c_struct), path_c_struct->nlri.len, strlen(path_c_struct->nlri.value)); + + for (int path_attribute_number = 0; path_attribute_number < path_c_struct->path_attributes_len; path_attribute_number++) { + current_path->add_pattrs(path_c_struct->path_attributes[path_attribute_number]->value, + path_c_struct->path_attributes[path_attribute_number]->len); + } + + current_path->set_nlri(path_c_struct->nlri.value, path_c_struct->nlri.len); + + gobgpapi::ModPathsArguments request; + request.set_resource(gobgpapi::Resource::GLOBAL); + google::protobuf::RepeatedPtrField< ::gobgpapi::Path >* current_path_list = request.mutable_paths(); + current_path_list->AddAllocated(current_path); + request.set_name(""); + + ClientContext context; + + gobgpapi::Error return_error; + + // result is a std::unique_ptr > + auto send_stream = stub_->ModPaths(&context, &return_error); + + bool write_result = send_stream->Write(request); + + if (!write_result) { + std::cout << "Write to API failed\n"; + } + + // Finish all writes + send_stream->WritesDone(); + + auto status = send_stream->Finish(); + + if (status.ok()) { + //std::cout << "modpath executed correctly" << std::cout; + } else { + std::cout << "modpath failed with code: " << status.error_code() + << " message " << status.error_message() << std::endl; + } + } + + std::string GetNeighbor(std::string neighbor_ip) { + gobgpapi::Arguments request; + request.set_family(4); + request.set_name(neighbor_ip); + + ClientContext context; + + gobgpapi::Peer peer; + grpc::Status status = stub_->GetNeighbor(&context, request, &peer); if (status.ok()) { + gobgpapi::PeerConf peer_conf = peer.conf(); + gobgpapi::PeerState peer_info = peer.info(); + std::stringstream buffer; - for (int i=0; i < response.peers_size(); i++) { + + buffer + << "Peer AS: " << peer_conf.peer_as() << "\n" + << "Peer router id: " << peer_conf.id() << "\n" + << "Peer flops: " << peer_info.flops() << "\n" + << "BGP state: " << peer_info.bgp_state(); - gobgpapi::PeerConf peer_conf = response.peers(i).conf(); - gobgpapi::PeerState peer_info = response.peers(i).info(); - gobgpapi::Timers peer_timers = response.peers(i).timers(); - - buffer - << "BGP neighbor is: " << peer_conf.neighbor_address() - << ", remote AS: " << peer_conf.peer_as() << "\n" - << "\tBGP version: 4, remote route ID " << peer_conf.id() << "\n" - << "\tBGP state = " << peer_info.bgp_state() - << ", up for " << peer_timers.state().uptime() << "\n" - << "\tBGP OutQ = " << peer_info.out_q() - << ", Flops = " << peer_info.flops() << "\n" - << "\tHold time is " << peer_timers.state().hold_time() - << ", keepalive interval is " << peer_timers.state().keepalive_interval() << "seconds\n" - << "\tConfigured hold time is " << peer_timers.config().hold_time() << "\n"; - - } return buffer.str(); } else { - std::stringstream buffer; - buffer - << status.error_code() << "\n" - << status.error_message() << "\n" - << status.error_details() << "\n"; - return buffer.str(); + return "Something wrong"; } } @@ -71,16 +245,25 @@ class GrpcClient { }; int main(int argc, char** argv) { - if(argc < 2) { - std::cout << "Usage: ./gobgp_api_client [gobgp address]\n"; - return 1; - } + GrpcClient gobgp_client(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); + + std::string reply = gobgp_client.GetNeighbor("213.133.111.200"); + std::cout << "Neighbor information: " << reply << std::endl; - std::string addr = argv[1]; - GrpcClient gobgp_client(grpc::CreateChannel(addr + ":50051", grpc::InsecureChannelCredentials())); + gobgp_client.AnnounceUnicastPrefix(false); - std::string reply = gobgp_client.GetNeighbor(); - std::cout << reply; + gobgp_client.AnnounceFlowSpecPrefix(false); + + unsigned int AFI_IP = 1; + unsigned int SAFI_UNICAST = 1; + unsigned int SAFI_FLOW_SPEC_UNICAST = 133; + + unsigned int ipv4_unicast_route_family = AFI_IP<<16 | SAFI_UNICAST; + unsigned int ipv4_flow_spec_route_family = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST; + + gobgp_client.GetAllActiveAnnounces(ipv4_unicast_route_family); + std::cout << std::endl << std::endl; + gobgp_client.GetAllActiveAnnounces(ipv4_flow_spec_route_family); return 0; } diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/java/src/gobgp/example/GobgpSampleClient.java b/vendor/github.com/osrg/gobgp/tools/grpc/java/src/gobgp/example/GobgpSampleClient.java deleted file mode 100644 index 287b46b6..00000000 --- a/vendor/github.com/osrg/gobgp/tools/grpc/java/src/gobgp/example/GobgpSampleClient.java +++ /dev/null @@ -1,44 +0,0 @@ -package gobgp.example; - -import gobgpapi.Gobgp; -import gobgpapi.GobgpApiGrpc; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; - -import java.util.List; - -public class GobgpSampleClient { - - private final GobgpApiGrpc.GobgpApiBlockingStub blockingStub; - - public GobgpSampleClient(String host, int port) { - ManagedChannel channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build(); - this.blockingStub = GobgpApiGrpc.newBlockingStub(channel); - } - - public void getNeighbors(){ - - Gobgp.GetNeighborRequest request = Gobgp.GetNeighborRequest.newBuilder().build(); - - for(Gobgp.Peer peer: this.blockingStub.getNeighbor(request).getPeersList()) { - Gobgp.PeerConf conf = peer.getConf(); - Gobgp.PeerState state = peer.getInfo(); - Gobgp.Timers timer = peer.getTimers(); - - System.out.printf("BGP neighbor is %s, remote AS %d\n", conf.getNeighborAddress(), conf.getPeerAs()); - System.out.printf("\tBGP version 4, remote router ID %s\n", conf.getId()); - System.out.printf("\tBGP state = %s, up for %d\n", state.getBgpState(), timer.getState().getUptime()); - System.out.printf("\tBGP OutQ = %d, Flops = %d\n", state.getOutQ(), state.getFlops()); - System.out.printf("\tHold time is %d, keepalive interval is %d seconds\n", - timer.getState().getHoldTime(), timer.getState().getKeepaliveInterval()); - System.out.printf("\tConfigured hold time is %d\n", timer.getConfig().getHoldTime()); - - } - } - - public static void main(String args[]){ - new GobgpSampleClient(args[0], 50051).getNeighbors(); - } - -} - diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/python/get_neighbor.py b/vendor/github.com/osrg/gobgp/tools/grpc/python/get_neighbor.py index ff94569d..3a57fdb8 100644 --- a/vendor/github.com/osrg/gobgp/tools/grpc/python/get_neighbor.py +++ b/vendor/github.com/osrg/gobgp/tools/grpc/python/get_neighbor.py @@ -1,28 +1,27 @@ -import gobgp_pb2_grpc import gobgp_pb2 import sys -import grpc +from grpc.beta import implementations from grpc.framework.interfaces.face.face import ExpirationError _TIMEOUT_SECONDS = 1 def run(gobgpd_addr): - channel = grpc.insecure_channel(gobgpd_addr + ':50051') - stub = gobgp_pb2_grpc.GobgpApiStub(channel) - try: - peers = stub.GetNeighbor(gobgp_pb2.GetNeighborRequest()).peers - for peer in peers: - print("BGP neighbor is %s, remote AS %d" % (peer.conf.neighbor_address, peer.conf.peer_as)) - print(" BGP version 4, remote router ID %s" % (peer.conf.id)) - print(" BGP state = %s, up for %s" % (peer.info.bgp_state, peer.timers.state.uptime)) - print(" BGP OutQ = %d, Flops = %d" % (peer.info.out_q, peer.info.flops)) - print(" Hold time is %d, keepalive interval is %d seconds" % (peer.timers.state.negotiated_hold_time, peer.timers.state.keepalive_interval)) - print(" Configured hold time is %d, keepalive interval is %d seconds" % (peer.timers.config.hold_time, peer.timers.config.keepalive_interval)) - except ExpirationError, e: - print str(e) - sys.exit(-1) + channel = implementations.insecure_channel(gobgpd_addr, 50051) + with gobgp_pb2.beta_create_GobgpApi_stub(channel) as stub: + try: + peers = stub.GetNeighbor(gobgp_pb2.GetNeighborRequest(), _TIMEOUT_SECONDS).peers + for peer in peers: + print("BGP neighbor is %s, remote AS %d" % (peer.conf.neighbor_address, peer.conf.peer_as)) + print(" BGP version 4, remote router ID %s" % (peer.conf.id)) + print(" BGP state = %s, up for %s" % (peer.info.bgp_state, peer.timers.state.uptime)) + print(" BGP OutQ = %d, Flops = %d" % (peer.info.out_q, peer.info.flops)) + print(" Hold time is %d, keepalive interval is %d seconds" % (peer.timers.state.negotiated_hold_time, peer.timers.state.keepalive_interval)) + print(" Configured hold time is %d, keepalive interval is %d seconds" % (peer.timers.config.hold_time, peer.timers.config.keepalive_interval)) + except ExpirationError, e: + print str(e) + sys.exit(-1) if __name__ == '__main__': gobgp = sys.argv[1] diff --git a/vendor/github.com/osrg/gobgp/tools/grpc/ruby/get_neighbors.rb b/vendor/github.com/osrg/gobgp/tools/grpc/ruby/get_neighbors.rb index a451f67f..36347373 100644 --- a/vendor/github.com/osrg/gobgp/tools/grpc/ruby/get_neighbors.rb +++ b/vendor/github.com/osrg/gobgp/tools/grpc/ruby/get_neighbors.rb @@ -1,11 +1,12 @@ -require 'gobgp_pb' -require 'gobgp_services_pb' +require 'gobgp' +require 'gobgp_services' -host = ARGV[0] +host = 'localhost' +host = ARGV[0] if ARGV.length > 0 stub = Gobgpapi::GobgpApi::Stub.new("#{host}:50051", :this_channel_is_insecure) -arg = Gobgpapi::GetNeighborRequest.new() -stub.get_neighbor(arg).peers.each do |n| +arg = Gobgpapi::Arguments.new() +stub.get_neighbors(arg).each do |n| puts "BGP neighbor is #{n.conf.neighbor_address}, remote AS #{n.conf.peer_as}" puts "\tBGP version 4, remote route ID #{n.conf.id}" puts "\tBGP state = #{n.info.bgp_state}, up for #{n.timers.state.uptime}" diff --git a/vendor/github.com/osrg/gobgp/tools/pyang_plugins/README.rst b/vendor/github.com/osrg/gobgp/tools/pyang_plugins/README.rst index 976b878c..ddf41f27 100644 --- a/vendor/github.com/osrg/gobgp/tools/pyang_plugins/README.rst +++ b/vendor/github.com/osrg/gobgp/tools/pyang_plugins/README.rst @@ -3,38 +3,21 @@ What's this ? This is a pyang plugin to generate config/bgp_configs.go from openconfig yang files (see https://github.com/openconfig/public). -Prerequisites -============= -Please confirm $GOPATH is configured before the following steps. - How to use ========== -Set the environment variables for this tool:: +:: - $ GOBGP_PATH=$GOPATH/src/github.com/osrg/gobgp/ - -Clone the required resources by using Git:: - - $ cd $HOME $ git clone https://github.com/osrg/public $ git clone https://github.com/YangModels/yang - $ git clone https://github.com/mbj4668/pyang - -Setup environments for pyang:: - - $ cd $HOME/pyang + $ YANG_DIR=`pwd` + $ cd $PYANG_INSTALL_DIR $ source ./env.sh - -Generate config/bgp_configs.go from yang files:: - - $ PYTHONPATH=. ./bin/pyang \ - --plugindir $GOBGP_PATH/tools/pyang_plugins \ - -p $HOME/yang/standard/ietf/RFC \ - -p $HOME/public/release/models \ - -p $HOME/public/release/models/bgp \ - -p $HOME/public/release/models/policy \ - -f golang \ - $HOME/public/release/models/bgp/openconfig-bgp.yang \ - $HOME/public/release/models/policy/openconfig-routing-policy.yang \ + $ PYTHONPATH=. ./bin/pyang --plugindir $GOBGP_PATH/tools/pyang_plugins \ + -p $YANG_DIR/yang/standard/ietf/RFC \ + -p $YANG_DIR/public/release/models \ + -p $YANG_DIR/public/release/models/bgp \ + -p $YANG_DIR/public/release/models/policy \ + -f golang $YANG_DIR/public/release/models/bgp/openconfig-bgp.yang \ + $YANG_DIR/public/release/models/policy/openconfig-routing-policy.yang \ $GOBGP_PATH/tools/pyang_plugins/gobgp.yang \ | gofmt > $GOBGP_PATH/config/bgp_configs.go diff --git a/vendor/github.com/osrg/gobgp/tools/pyang_plugins/gobgp.yang b/vendor/github.com/osrg/gobgp/tools/pyang_plugins/gobgp.yang index 9ada88d4..25299cc2 100644 --- a/vendor/github.com/osrg/gobgp/tools/pyang_plugins/gobgp.yang +++ b/vendor/github.com/osrg/gobgp/tools/pyang_plugins/gobgp.yang @@ -180,18 +180,6 @@ module gobgp { error condition has occurred exchanged."; } - leaf WITHDRAW-UPDATE { - type uint32; - description - "Number of updates subjected to treat-as-withdraw treatment."; - } - - leaf WITHDRAW-PREFIX { - type uint32; - description - "Number of prefixes subjected to treat-as-withdraw treatment."; - } - leaf DISCARDED { type uint64; description @@ -207,6 +195,7 @@ module gobgp { } } + grouping gobgp-adjacent-table { container adj-table { leaf ADVERTISED { @@ -559,30 +548,20 @@ module gobgp { "Reference to the address of the BMP server used as a key in the BMP server list"; } - leaf port { type uint32; description "Reference to the port of the BMP server"; } - leaf route-monitoring-policy { type bmp-route-monitoring-policy-type; default PRE-POLICY; } - leaf statistics-timeout { type uint16; description "Interval seconds of statistics messages sent to BMP server"; } - - leaf route-mirroring-enabled { - type boolean; - description - "Enable feature for mirroring of received BGP messages - mainly for debugging purpose"; - } } grouping gobgp-bmp-server-state { @@ -653,47 +632,6 @@ module gobgp { } } - grouping gobgp-ttl-security-config { - description - "Configuration parameters for TTL Security"; - - leaf enabled { - type boolean; - default "false"; - description - "Enable features for TTL Security"; - } - - leaf ttl-min { - type uint8; - description - "Reference to the port of the BMP server"; - } - } - - grouping gobgp-ttl-security-config-set { - description - "set of configurations for Generalized TTL Security Mechanism (GTSM)"; - - container ttl-security { - description - "Configure TTL Security feature"; - - container config { - description - "Configuration parameters for TTL Security"; - uses gobgp-ttl-security-config; - } - - container state { - config false; - description - "State information for TTL Security"; - uses gobgp-ttl-security-config; - } - } - } - // augment statements augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:state/bgp:messages/bgp:sent" { description "additional counters"; @@ -807,11 +745,6 @@ module gobgp { leaf remote-port { type inet:port-number; } - - leaf ttl { - description "TTL value for BGP packets"; - type uint8; - } } augment "/bgp:bgp/bgp:neighbors/bgp:neighbor/bgp:timers/bgp:config" { @@ -871,16 +804,6 @@ module gobgp { uses gobgp-route-server-config-set; } - augment "/bgp:bgp/bgp:peer-groups/bgp:peer-group" { - description "TTL Security configuration for peer-group"; - uses gobgp-ttl-security-config-set; - } - - augment "/bgp:bgp/bgp:neighbors/bgp:neighbor" { - description "TTL Security configuration for neighbor"; - uses gobgp-ttl-security-config-set; - } - augment "/bgp:bgp/bgp:global/bgp:apply-policy/bgp:config" { description "addtional policy"; uses gobgp-in-policy; @@ -1182,45 +1105,6 @@ module gobgp { uses listen-config; } - grouping dynamic-neighbors { - container dynamic-neighbors { - list dynamic-neighbor { - key "prefix"; - - leaf prefix { - type leafref { - path "../config/prefix"; - } - } - - container config { - uses bgp-global-dynamic-neighbor-config; - } - - container state { - config false; - uses bgp-global-dynamic-neighbor-config; - } - } - } - } - - grouping bgp-global-dynamic-neighbor-config { - description "A dynamic neighbor belongs to a peer group. - This configuration structure was taken from the latest openconfig."; - - leaf prefix { - type string; - } - leaf peer-group { - type string; - } - } - - augment "/bgp:bgp" { - uses dynamic-neighbors; - } - augment "/bgp:bgp/bgp:global/bgp:afi-safis/bgp:afi-safi" { uses bgp-mp:all-afi-safi-common; } diff --git a/vendor/github.com/osrg/gobgp/zebra/zapi.go b/vendor/github.com/osrg/gobgp/zebra/zapi.go index 01e8d2ff..0c131f7f 100644 --- a/vendor/github.com/osrg/gobgp/zebra/zapi.go +++ b/vendor/github.com/osrg/gobgp/zebra/zapi.go @@ -23,7 +23,7 @@ import ( "strings" "syscall" - log "github.com/sirupsen/logrus" + log "github.com/Sirupsen/logrus" ) const ( diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index 03fe4b15..c443aed0 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.0.2 * bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method # 1.0.1 diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go index 1aeaa90b..013183ed 100644 --- a/vendor/github.com/sirupsen/logrus/exported.go +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -31,7 +31,7 @@ func SetFormatter(formatter Formatter) { func SetLevel(level Level) { std.mu.Lock() defer std.mu.Unlock() - std.setLevel(level) + std.SetLevel(level) } // GetLevel returns the standard logger level. diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index 370fff5d..b44966f9 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -312,6 +312,6 @@ func (logger *Logger) level() Level { return Level(atomic.LoadUint32((*uint32)(&logger.Level))) } -func (logger *Logger) setLevel(level Level) { +func (logger *Logger) SetLevel(level Level) { atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) } diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index 6aa48cfb..cf3f17f2 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -52,10 +52,6 @@ type TextFormatter struct { // QuoteEmptyFields will wrap empty fields in quotes if true QuoteEmptyFields bool - // QuoteCharacter can be set to the override the default quoting character " - // with something else. For example: ', or `. - QuoteCharacter string - // Whether the logger's out is to a terminal isTerminal bool @@ -63,9 +59,6 @@ type TextFormatter struct { } func (f *TextFormatter) init(entry *Entry) { - if len(f.QuoteCharacter) == 0 { - f.QuoteCharacter = "\"" - } if entry.Logger != nil { f.isTerminal = IsTerminal(entry.Logger.Out) } @@ -177,13 +170,6 @@ func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { if !f.needsQuoting(stringVal) { b.WriteString(stringVal) } else { - b.WriteString(f.quoteString(stringVal)) + b.WriteString(fmt.Sprintf("%q", stringVal)) } } - -func (f *TextFormatter) quoteString(v string) string { - escapedQuote := fmt.Sprintf("\\%s", f.QuoteCharacter) - escapedValue := strings.Replace(v, f.QuoteCharacter, escapedQuote, -1) - - return fmt.Sprintf("%s%v%s", f.QuoteCharacter, escapedValue, f.QuoteCharacter) -} diff --git a/vendor/github.com/sirupsen/logrus/text_formatter_test.go b/vendor/github.com/sirupsen/logrus/text_formatter_test.go index d7b3bcb1..ecb8f127 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter_test.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter_test.go @@ -3,10 +3,10 @@ package logrus import ( "bytes" "errors" + "fmt" "strings" "testing" "time" - "fmt" ) func TestQuoting(t *testing.T) { @@ -15,7 +15,7 @@ func TestQuoting(t *testing.T) { checkQuoting := func(q bool, value interface{}) { b, _ := tf.Format(WithField("test", value)) idx := bytes.Index(b, ([]byte)("test=")) - cont := bytes.Contains(b[idx+5:], []byte(tf.QuoteCharacter)) + cont := bytes.Contains(b[idx+5:], []byte("\"")) if cont != q { if q { t.Errorf("quoting expected for: %#v", value) @@ -41,23 +41,6 @@ func TestQuoting(t *testing.T) { checkQuoting(false, errors.New("invalid")) checkQuoting(true, errors.New("invalid argument")) - // Test for custom quote character. - tf.QuoteCharacter = "`" - checkQuoting(false, "") - checkQuoting(false, "abcd") - checkQuoting(false, "/foobar") - checkQuoting(false, "foo_bar") - checkQuoting(false, "foo@bar") - checkQuoting(false, "foobar^") - checkQuoting(true, "foobar$") - checkQuoting(true, "&foobar") - checkQuoting(true, errors.New("invalid argument")) - - // Test for multi-character quotes. - tf.QuoteCharacter = "§~±" - checkQuoting(false, "abcd") - checkQuoting(true, errors.New("invalid argument")) - // Test for quoting empty fields. tf.QuoteEmptyFields = true checkQuoting(true, "") @@ -65,7 +48,7 @@ func TestQuoting(t *testing.T) { checkQuoting(true, errors.New("invalid argument")) } -func TestEscaping_DefaultQuoteCharacter(t *testing.T) { +func TestEscaping(t *testing.T) { tf := &TextFormatter{DisableColors: true} testCases := []struct { @@ -105,35 +88,13 @@ func TestEscaping_Interface(t *testing.T) { } } -func TestEscaping_CustomQuoteCharacter(t *testing.T) { - tf := &TextFormatter{DisableColors: true} - - testCases := []struct { - value string - expected string - quoteChar string - }{ - {`ba"r`, `ba"r`, `'`}, - {`ba'r`, `ba\'r`, `'`}, - {`ba'r`, `ba'r`, `^`}, - } - - for _, tc := range testCases { - tf.QuoteCharacter = tc.quoteChar - b, _ := tf.Format(WithField("test", tc.value)) - if !bytes.Contains(b, []byte(tc.expected)) { - t.Errorf("escaping expected for %q (result was %q instead of %q)", tc.value, string(b), tc.expected) - } - } -} - func TestTimestampFormat(t *testing.T) { checkTimeStr := func(format string) { customFormatter := &TextFormatter{DisableColors: true, TimestampFormat: format} customStr, _ := customFormatter.Format(WithField("test", "test")) timeStart := bytes.Index(customStr, ([]byte)("time=")) timeEnd := bytes.Index(customStr, ([]byte)("level=")) - timeStr := customStr[timeStart+5+len(customFormatter.QuoteCharacter) : timeEnd-1-len(customFormatter.QuoteCharacter)] + timeStr := customStr[timeStart+5+len("\"") : timeEnd-1-len("\"")] if format == "" { format = time.RFC3339 }