Merge pull request #15 from czerwonk/feature/initial_bird2_support
Feature/initial bird2 support
This commit is contained in:
commit
48384e8613
@ -13,8 +13,12 @@ To get meaningful uptime information bird has to be configured this way:
|
||||
timeformat protocol "%s";
|
||||
```
|
||||
|
||||
## Important information for users of bird 2.0
|
||||
Version 2.0 of bird was released on 2017-12-11. Since this version introcuces a new handling of IPv4 and IPv6 protocols (channels) bird_export does not support this version yet. There will be a version 1.1 in the next days which will introduce support for the new channel feature.
|
||||
## Important information for users of bird 2.0+
|
||||
Version 2.0 of bird routing daemon does support IPv4 and IPv6 in one single daemon now.
|
||||
For further information see [here](https://gitlab.labs.nic.cz/labs/bird/wikis/transition-notes-to-bird-2).
|
||||
Since version 1.1 bird_exporter can be used with bird 2.0+ using the `-bird.v2` parameter.
|
||||
When using this parameter bird_exporter queries the same bird socket for IPv4 and IPv6.
|
||||
In this mode the IP protocol is determined by the channel information and parameters `-bird.ipv4`, `-bird.ipv6` and `-bird.socket6` are ignored.
|
||||
|
||||
## Metric formats
|
||||
In version 1.0 a new metric format was introduced.
|
||||
|
@ -1,16 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/czerwonk/bird_exporter/parser"
|
||||
"github.com/czerwonk/bird_exporter/protocol"
|
||||
"github.com/czerwonk/bird_socket"
|
||||
"github.com/czerwonk/bird_exporter/parser"
|
||||
)
|
||||
|
||||
func getProtocols() ([]*protocol.Protocol, error) {
|
||||
var protocols []*protocol.Protocol = nil
|
||||
var err error = nil
|
||||
|
||||
if *birdV2 {
|
||||
protocols, err = getProtocolsFromBird(*birdSocket, "")
|
||||
} else {
|
||||
protocols, err = getProtocolsFromBird1()
|
||||
}
|
||||
|
||||
return protocols, err
|
||||
}
|
||||
|
||||
func getProtocolsFromBird1() ([]*protocol.Protocol, error) {
|
||||
protocols := make([]*protocol.Protocol, 0)
|
||||
|
||||
if *birdEnabled {
|
||||
s, err := getProtocolsFromBird(*birdSocket, 4)
|
||||
s, err := getProtocolsFromBird(*birdSocket, "4")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -18,7 +31,7 @@ func getProtocols() ([]*protocol.Protocol, error) {
|
||||
}
|
||||
|
||||
if *bird6Enabled {
|
||||
s, err := getProtocolsFromBird(*bird6Socket, 6)
|
||||
s, err := getProtocolsFromBird(*bird6Socket, "6")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -28,7 +41,7 @@ func getProtocols() ([]*protocol.Protocol, error) {
|
||||
return protocols, nil
|
||||
}
|
||||
|
||||
func getProtocolsFromBird(socketPath string, ipVersion int) ([]*protocol.Protocol, error) {
|
||||
func getProtocolsFromBird(socketPath string, ipVersion string) ([]*protocol.Protocol, error) {
|
||||
b, err := birdsocket.Query(socketPath, "show protocols all")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
14
main.go
14
main.go
@ -12,23 +12,24 @@ import (
|
||||
"github.com/prometheus/common/log"
|
||||
)
|
||||
|
||||
const version string = "1.0.0"
|
||||
const version string = "1.1.0"
|
||||
|
||||
var (
|
||||
showVersion = flag.Bool("version", false, "Print version information.")
|
||||
listenAddress = flag.String("web.listen-address", ":9324", "Address on which to expose metrics and web interface.")
|
||||
metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.")
|
||||
birdSocket = flag.String("bird.socket", "/var/run/bird.ctl", "Socket to communicate with bird routing daemon")
|
||||
bird6Socket = flag.String("bird.socket6", "/var/run/bird6.ctl", "Socket to communicate with bird6 routing daemon")
|
||||
birdEnabled = flag.Bool("bird.ipv4", true, "Get protocols from bird")
|
||||
bird6Enabled = flag.Bool("bird.ipv6", true, "Get protocols from bird6")
|
||||
birdV2 = flag.Bool("bird.v2", false, "Bird major version >= 2.0 (multi channel protocols)")
|
||||
newFormat = flag.Bool("format.new", false, "New metric format (more convinient / generic)")
|
||||
enableBgp = flag.Bool("proto.bgp", true, "Enables metrics for protocol BGP")
|
||||
enableOspf = flag.Bool("proto.ospf", true, "Enables metrics for protocol OSPF")
|
||||
enableKernel = flag.Bool("proto.kernel", true, "Enables metrics for protocol Kernel")
|
||||
enableStatic = flag.Bool("proto.static", true, "Enables metrics for protocol Static")
|
||||
enableDevice = flag.Bool("proto.device", true, "Enables metrics for protocol Device")
|
||||
enableDirect = flag.Bool("proto.direct", true, "Enables metrics for protocol Direct")
|
||||
// pre bird 2.0
|
||||
bird6Socket = flag.String("bird.socket6", "/var/run/bird6.ctl", "Socket to communicate with bird6 routing daemon (not compatible with -bird.v2)")
|
||||
birdEnabled = flag.Bool("bird.ipv4", true, "Get protocols from bird (not compatible with -bird.v2)")
|
||||
bird6Enabled = flag.Bool("bird.ipv6", true, "Get protocols from bird6 (not compatible with -bird.v2)")
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -126,9 +127,6 @@ func enabledProtocols() int {
|
||||
if *enableStatic {
|
||||
res |= protocol.Static
|
||||
}
|
||||
if *enableDevice {
|
||||
res |= protocol.Device
|
||||
}
|
||||
if *enableDirect {
|
||||
res |= protocol.Direct
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ func exportersForLegacy() map[int][]metrics.MetricExporter {
|
||||
|
||||
return map[int][]metrics.MetricExporter{
|
||||
protocol.BGP: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("bgp4_session", "bgp6_session", l)},
|
||||
protocol.Device: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("device4", "device6", l)},
|
||||
protocol.Direct: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("direct4", "direct6", l)},
|
||||
protocol.Kernel: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("kernel4", "kernel6", l)},
|
||||
protocol.OSPF: []metrics.MetricExporter{metrics.NewLegacyMetricExporter("ospf", "ospfv3", l), ospf.NewExporter("")},
|
||||
@ -44,7 +43,6 @@ func exportersForDefault() map[int][]metrics.MetricExporter {
|
||||
|
||||
return map[int][]metrics.MetricExporter{
|
||||
protocol.BGP: []metrics.MetricExporter{e},
|
||||
protocol.Device: []metrics.MetricExporter{e},
|
||||
protocol.Direct: []metrics.MetricExporter{e},
|
||||
protocol.Kernel: []metrics.MetricExporter{e},
|
||||
protocol.OSPF: []metrics.MetricExporter{e, ospf.NewExporter("bird_")},
|
||||
|
@ -2,7 +2,6 @@ package metrics
|
||||
|
||||
import (
|
||||
"github.com/czerwonk/bird_exporter/protocol"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type DefaultLabelStrategy struct {
|
||||
@ -13,14 +12,14 @@ func (*DefaultLabelStrategy) labelNames() []string {
|
||||
}
|
||||
|
||||
func (*DefaultLabelStrategy) labelValues(p *protocol.Protocol) []string {
|
||||
return []string{p.Name, protoString(p), strconv.Itoa(p.IpVersion)}
|
||||
return []string{p.Name, protoString(p), p.IpVersion}
|
||||
}
|
||||
func protoString(p *protocol.Protocol) string {
|
||||
switch p.Proto {
|
||||
case protocol.BGP:
|
||||
return "BGP"
|
||||
case protocol.OSPF:
|
||||
if p.IpVersion == 4 {
|
||||
if p.IpVersion == "4" {
|
||||
return "OSPF"
|
||||
} else {
|
||||
return "OSPFv3"
|
||||
@ -29,8 +28,6 @@ func protoString(p *protocol.Protocol) string {
|
||||
return "Static"
|
||||
case protocol.Kernel:
|
||||
return "Kernel"
|
||||
case protocol.Device:
|
||||
return "Device"
|
||||
case protocol.Direct:
|
||||
return "Direct"
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/czerwonk/bird_exporter/protocol"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
type LegacyMetricExporter struct {
|
||||
@ -11,7 +11,7 @@ type LegacyMetricExporter struct {
|
||||
}
|
||||
|
||||
func NewLegacyMetricExporter(prefixIpv4, prefixIpv6 string, labelStrategy LabelStrategy) MetricExporter {
|
||||
return &LegacyMetricExporter {
|
||||
return &LegacyMetricExporter{
|
||||
ipv4Exporter: NewGenericProtocolMetricExporter(prefixIpv4, false, labelStrategy),
|
||||
ipv6Exporter: NewGenericProtocolMetricExporter(prefixIpv6, false, labelStrategy),
|
||||
}
|
||||
@ -23,7 +23,7 @@ func (e *LegacyMetricExporter) Describe(ch chan<- *prometheus.Desc) {
|
||||
}
|
||||
|
||||
func (e *LegacyMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
|
||||
if p.IpVersion == 4 {
|
||||
if p.IpVersion == "4" {
|
||||
e.ipv4Exporter.Export(p, ch)
|
||||
} else {
|
||||
e.ipv6Exporter.Export(p, ch)
|
||||
|
@ -1,9 +1,9 @@
|
||||
package ospf
|
||||
|
||||
import (
|
||||
"github.com/czerwonk/bird_exporter/metrics"
|
||||
"github.com/czerwonk/bird_exporter/protocol"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/czerwonk/bird_exporter/metrics"
|
||||
)
|
||||
|
||||
type desc struct {
|
||||
@ -11,13 +11,13 @@ type desc struct {
|
||||
}
|
||||
|
||||
type ospfMetricExporter struct {
|
||||
descriptions map[int]*desc
|
||||
descriptions map[string]*desc
|
||||
}
|
||||
|
||||
func NewExporter(prefix string) metrics.MetricExporter {
|
||||
d := make(map[int]*desc)
|
||||
d[4] = getDesc(prefix+"ospf")
|
||||
d[6] = getDesc(prefix+"ospfv3")
|
||||
d := make(map[string]*desc)
|
||||
d["4"] = getDesc(prefix + "ospf")
|
||||
d["6"] = getDesc(prefix + "ospfv3")
|
||||
|
||||
return &ospfMetricExporter{descriptions: d}
|
||||
}
|
||||
@ -32,8 +32,8 @@ func getDesc(prefix string) *desc {
|
||||
}
|
||||
|
||||
func (m *ospfMetricExporter) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- m.descriptions[4].runningDesc
|
||||
ch <- m.descriptions[6].runningDesc
|
||||
ch <- m.descriptions["4"].runningDesc
|
||||
ch <- m.descriptions["6"].runningDesc
|
||||
}
|
||||
|
||||
func (m *ospfMetricExporter) Export(p *protocol.Protocol, ch chan<- prometheus.Metric) {
|
||||
|
169
parser/parser.go
169
parser/parser.go
@ -14,63 +14,84 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
protocolRegex *regexp.Regexp
|
||||
routeRegex *regexp.Regexp
|
||||
uptimeRegex *regexp.Regexp
|
||||
protocolRegex *regexp.Regexp
|
||||
routeRegex *regexp.Regexp
|
||||
uptimeRegex *regexp.Regexp
|
||||
routeChangeRegex *regexp.Regexp
|
||||
channelRegex *regexp.Regexp
|
||||
)
|
||||
|
||||
type context struct {
|
||||
current *protocol.Protocol
|
||||
line string
|
||||
handled bool
|
||||
protocols []*protocol.Protocol
|
||||
ipVersion string
|
||||
}
|
||||
|
||||
func init() {
|
||||
protocolRegex = regexp.MustCompile("^(?:1002\\-)?([^\\s]+)\\s+(BGP|OSPF|Direct|Device|Kernel)\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)(?:\\s+(.*?))?$")
|
||||
routeRegex = regexp.MustCompile("^\\s+Routes:\\s+(\\d+) imported, (?:(\\d+) filtered, )?(\\d+) exported(?:, (\\d+) preferred)?")
|
||||
uptimeRegex = regexp.MustCompile("^(?:((\\d+):(\\d{2}):(\\d{2}))|\\d+)$")
|
||||
routeChangeRegex = regexp.MustCompile("(Import|Export) (updates|withdraws):\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s+(\\d+|---)\\s*")
|
||||
channelRegex = regexp.MustCompile("Channel ipv(4|6)")
|
||||
}
|
||||
|
||||
// Parser parses bird output and returns protocol.Protocol structs
|
||||
func Parse(data []byte, ipVersion int) []*protocol.Protocol {
|
||||
protocols := make([]*protocol.Protocol, 0)
|
||||
|
||||
func Parse(data []byte, ipVersion string) []*protocol.Protocol {
|
||||
reader := bytes.NewReader(data)
|
||||
scanner := bufio.NewScanner(reader)
|
||||
var current *protocol.Protocol = nil
|
||||
|
||||
c := &context{protocols: make([]*protocol.Protocol, 0), ipVersion: ipVersion}
|
||||
|
||||
var handlers = []func(*context){
|
||||
handleEmptyLine,
|
||||
parseLineForProtocol,
|
||||
parseLineForChannel,
|
||||
parseLineForRoutes,
|
||||
parseLineForRouteChanges,
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimRight(scanner.Text(), " ")
|
||||
if p, ok := parseLineForProtocol(line, ipVersion); ok {
|
||||
current = p
|
||||
protocols = append(protocols, current)
|
||||
}
|
||||
c.line = strings.TrimRight(scanner.Text(), " ")
|
||||
c.handled = false
|
||||
|
||||
if current != nil {
|
||||
parseLineForRoutes(line, current)
|
||||
parseLineForRouteChanges(line, current)
|
||||
}
|
||||
|
||||
if line == "" {
|
||||
current = nil
|
||||
for _, h := range handlers {
|
||||
if !c.handled {
|
||||
h(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return protocols
|
||||
return c.protocols
|
||||
}
|
||||
|
||||
func parseLineForProtocol(line string, ipVersion int) (*protocol.Protocol, bool) {
|
||||
match := protocolRegex.FindStringSubmatch(line)
|
||||
func handleEmptyLine(c *context) {
|
||||
if c.line != "" {
|
||||
return
|
||||
}
|
||||
|
||||
c.current = nil
|
||||
c.handled = true
|
||||
}
|
||||
|
||||
func parseLineForProtocol(c *context) {
|
||||
match := protocolRegex.FindStringSubmatch(c.line)
|
||||
|
||||
if match == nil {
|
||||
return nil, false
|
||||
return
|
||||
}
|
||||
|
||||
proto := parseProto(match[2])
|
||||
ut := parseUptime(match[5])
|
||||
|
||||
p := protocol.NewProtocol(match[1], proto, ipVersion, ut)
|
||||
p.Up = parseState(match[4])
|
||||
c.current = protocol.NewProtocol(match[1], proto, c.ipVersion, ut)
|
||||
c.current.Up = parseState(match[4])
|
||||
|
||||
fillAttributes(p, match)
|
||||
fillAttributes(c.current, match)
|
||||
|
||||
return p, true
|
||||
c.protocols = append(c.protocols, c.current)
|
||||
c.handled = true
|
||||
}
|
||||
|
||||
func parseProto(val string) int {
|
||||
@ -81,8 +102,6 @@ func parseProto(val string) int {
|
||||
return protocol.OSPF
|
||||
case "Direct":
|
||||
return protocol.Direct
|
||||
case "Device":
|
||||
return protocol.Device
|
||||
case "Kernel":
|
||||
return protocol.Kernel
|
||||
case "Static":
|
||||
@ -92,25 +111,6 @@ func parseProto(val string) int {
|
||||
return protocol.PROTO_UNKNOWN
|
||||
}
|
||||
|
||||
func parseLineForRoutes(line string, p *protocol.Protocol) {
|
||||
match := routeRegex.FindStringSubmatch(line)
|
||||
|
||||
if match == nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.Imported, _ = strconv.ParseInt(match[1], 10, 64)
|
||||
p.Exported, _ = strconv.ParseInt(match[3], 10, 64)
|
||||
|
||||
if len(match[2]) > 0 {
|
||||
p.Filtered, _ = strconv.ParseInt(match[2], 10, 64)
|
||||
}
|
||||
|
||||
if len(match[4]) > 0 {
|
||||
p.Preferred, _ = strconv.ParseInt(match[4], 10, 64)
|
||||
}
|
||||
}
|
||||
|
||||
func parseState(state string) int {
|
||||
if state == "up" {
|
||||
return 1
|
||||
@ -121,6 +121,7 @@ func parseState(state string) int {
|
||||
|
||||
func parseUptime(value string) int {
|
||||
match := uptimeRegex.FindStringSubmatch(value)
|
||||
|
||||
if match == nil {
|
||||
return 0
|
||||
}
|
||||
@ -156,18 +157,74 @@ func parseUptimeForTimestamp(timestamp string) int {
|
||||
return int(d.Seconds())
|
||||
}
|
||||
|
||||
func parseLineForRouteChanges(line string, p *protocol.Protocol) {
|
||||
match := routeChangeRegex.FindStringSubmatch(line)
|
||||
func parseLineForChannel(c *context) {
|
||||
if c.ipVersion != "" || c.current == nil {
|
||||
return
|
||||
}
|
||||
|
||||
channel := channelRegex.FindStringSubmatch(c.line)
|
||||
if channel == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.current.IpVersion) == 0 {
|
||||
c.current.IpVersion = channel[1]
|
||||
} else {
|
||||
c.current = &protocol.Protocol{
|
||||
Name: c.current.Name,
|
||||
Proto: c.current.Proto,
|
||||
Up: c.current.Up,
|
||||
Uptime: c.current.Uptime,
|
||||
IpVersion: channel[1],
|
||||
}
|
||||
c.protocols = append(c.protocols, c.current)
|
||||
}
|
||||
|
||||
c.handled = true
|
||||
}
|
||||
|
||||
func parseLineForRoutes(c *context) {
|
||||
if c.current == nil {
|
||||
return
|
||||
}
|
||||
|
||||
match := routeRegex.FindStringSubmatch(c.line)
|
||||
if match == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c := getRouteChangeCount(match, p)
|
||||
c.Received = parseRouteChangeValue(match[3])
|
||||
c.Rejected = parseRouteChangeValue(match[4])
|
||||
c.Filtered = parseRouteChangeValue(match[5])
|
||||
c.Ignored = parseRouteChangeValue(match[6])
|
||||
c.Accepted = parseRouteChangeValue(match[7])
|
||||
c.current.Imported, _ = strconv.ParseInt(match[1], 10, 64)
|
||||
c.current.Exported, _ = strconv.ParseInt(match[3], 10, 64)
|
||||
|
||||
if len(match[2]) > 0 {
|
||||
c.current.Filtered, _ = strconv.ParseInt(match[2], 10, 64)
|
||||
}
|
||||
|
||||
if len(match[4]) > 0 {
|
||||
c.current.Preferred, _ = strconv.ParseInt(match[4], 10, 64)
|
||||
}
|
||||
|
||||
c.handled = true
|
||||
}
|
||||
|
||||
func parseLineForRouteChanges(c *context) {
|
||||
if c.current == nil {
|
||||
return
|
||||
}
|
||||
|
||||
match := routeChangeRegex.FindStringSubmatch(c.line)
|
||||
if match == nil {
|
||||
return
|
||||
}
|
||||
|
||||
x := getRouteChangeCount(match, c.current)
|
||||
x.Received = parseRouteChangeValue(match[3])
|
||||
x.Rejected = parseRouteChangeValue(match[4])
|
||||
x.Filtered = parseRouteChangeValue(match[5])
|
||||
x.Ignored = parseRouteChangeValue(match[6])
|
||||
x.Accepted = parseRouteChangeValue(match[7])
|
||||
|
||||
c.handled = true
|
||||
}
|
||||
|
||||
func getRouteChangeCount(values []string, p *protocol.Protocol) *protocol.RouteChangeCount {
|
||||
|
155
parser_test.go
155
parser_test.go
@ -3,14 +3,14 @@ package main
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/czerwonk/bird_exporter/parser"
|
||||
"github.com/czerwonk/bird_exporter/protocol"
|
||||
"github.com/czerwonk/testutils/assert"
|
||||
"github.com/czerwonk/bird_exporter/parser"
|
||||
)
|
||||
|
||||
func TestEstablishedBgpOldTimeFormat(t *testing.T) {
|
||||
data := "foo BGP master up 1481973060 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -21,12 +21,12 @@ func TestEstablishedBgpOldTimeFormat(t *testing.T) {
|
||||
assert.Int64Equal("exported", 34, x.Exported, t)
|
||||
assert.Int64Equal("filtered", 1, x.Filtered, t)
|
||||
assert.Int64Equal("preferred", 100, x.Preferred, t)
|
||||
assert.IntEqual("ipVersion", 4, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "4", x.IpVersion, t)
|
||||
}
|
||||
|
||||
func TestEstablishedBgpCurrentTimeFormat(t *testing.T) {
|
||||
data := "foo BGP master up 00:01:00 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -37,22 +37,22 @@ func TestEstablishedBgpCurrentTimeFormat(t *testing.T) {
|
||||
assert.Int64Equal("exported", 34, x.Exported, t)
|
||||
assert.Int64Equal("filtered", 1, x.Filtered, t)
|
||||
assert.Int64Equal("preferred", 100, x.Preferred, t)
|
||||
assert.IntEqual("ipVersion", 4, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "4", x.IpVersion, t)
|
||||
assert.IntEqual("uptime", 60, x.Uptime, t)
|
||||
}
|
||||
|
||||
func TestIpv6Bgp(t *testing.T) {
|
||||
data := "foo BGP master up 00:01:00 Established\ntest\nbar\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 6)
|
||||
p := parser.Parse([]byte(data), "6")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
assert.IntEqual("ipVersion", 6, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "6", x.IpVersion, t)
|
||||
}
|
||||
|
||||
func TestActiveBgp(t *testing.T) {
|
||||
data := "bar BGP master start 2016-01-01 Active\ntest\nbar"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -61,13 +61,13 @@ func TestActiveBgp(t *testing.T) {
|
||||
assert.IntEqual("established", 0, x.Up, t)
|
||||
assert.IntEqual("imported", 0, int(x.Imported), t)
|
||||
assert.IntEqual("exported", 0, int(x.Exported), t)
|
||||
assert.IntEqual("ipVersion", 4, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "4", x.IpVersion, t)
|
||||
assert.IntEqual("uptime", 0, int(x.Uptime), t)
|
||||
}
|
||||
|
||||
func Test2BgpSessions(t *testing.T) {
|
||||
data := "foo BGP master up 00:01:00 Established\ntest\n Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\nbar BGP master start 2016-01-01 Active\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 2, len(p), t)
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ func TestUpdateAndWithdrawCounts(t *testing.T) {
|
||||
" Import withdraws: 6 7 8 9 10\n" +
|
||||
" Export updates: 11 12 13 14 15\n" +
|
||||
" Export withdraws: 16 17 18 19 ---"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
x := p[0]
|
||||
|
||||
assert.Int64Equal("import updates received", 1, x.ImportUpdates.Received, t)
|
||||
@ -104,9 +104,126 @@ func TestUpdateAndWithdrawCounts(t *testing.T) {
|
||||
assert.Int64Equal("export withdraws accepted", 0, x.ExportWithdraws.Accepted, t)
|
||||
}
|
||||
|
||||
func TestWithBird2(t *testing.T) {
|
||||
data := "Name Proto Table State Since Info\n" +
|
||||
"bgp1 BGP master up 1494926415\n" +
|
||||
" Channel ipv6\n" +
|
||||
" Routes: 1 imported, 2 filtered, 3 exported, 4 preferred\n" +
|
||||
"\n" +
|
||||
"direct1 Direct --- up 1513027903\n" +
|
||||
" Channel ipv4\n" +
|
||||
" State: UP\n" +
|
||||
" Table: master4\n" +
|
||||
" Preference: 240\n" +
|
||||
" Input filter: ACCEPT\n" +
|
||||
" Output filter: REJECT\n" +
|
||||
" Routes: 12 imported, 1 filtered, 34 exported, 100 preferred\n" +
|
||||
" Route change stats: received rejected filtered ignored accepted\n" +
|
||||
" Import updates: 1 2 3 4 5\n" +
|
||||
" Import withdraws: 6 7 8 9 10\n" +
|
||||
" Export updates: 11 12 13 14 15\n" +
|
||||
" Export withdraws: 16 17 18 19 ---\n" +
|
||||
" Channel ipv6\n" +
|
||||
" State: UP\n" +
|
||||
" Table: master6\n" +
|
||||
" Preference: 240\n" +
|
||||
" Input filter: ACCEPT\n" +
|
||||
" Output filter: REJECT\n" +
|
||||
" Routes: 3 imported, 7 filtered, 5 exported, 13 preferred\n" +
|
||||
" Route change stats: received rejected filtered ignored accepted\n" +
|
||||
" Import updates: 20 21 22 23 24\n" +
|
||||
" Import withdraws: 25 26 27 28 29\n" +
|
||||
" Export updates: 30 31 32 33 34\n" +
|
||||
" Export withdraws: 35 36 37 38 ---\n" +
|
||||
"\n" +
|
||||
"ospf1 OSPF master up 1494926415\n" +
|
||||
" Channel ipv4\n" +
|
||||
" Routes: 4 imported, 3 filtered, 2 exported, 1 preferred\n" +
|
||||
"\n"
|
||||
|
||||
p := parser.Parse([]byte(data), "")
|
||||
assert.IntEqual("protocols", 4, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
assert.StringEqual("BGP ipv6 name", "bgp1", x.Name, t)
|
||||
assert.IntEqual("BGP ipv6 proto", protocol.BGP, x.Proto, t)
|
||||
assert.StringEqual("BGP ipv6 ip version", "6", x.IpVersion, t)
|
||||
assert.Int64Equal("BGP ipv6 imported", 1, x.Imported, t)
|
||||
assert.Int64Equal("BGP ipv6 exported", 3, x.Exported, t)
|
||||
assert.Int64Equal("BGP ipv6 filtered", 2, x.Filtered, t)
|
||||
assert.Int64Equal("BGP ipv6 preferred", 4, x.Preferred, t)
|
||||
|
||||
x = p[1]
|
||||
assert.StringEqual("BGP ipv4 name", "direct1", x.Name, t)
|
||||
assert.IntEqual("Direct ipv4 proto", protocol.Direct, x.Proto, t)
|
||||
assert.StringEqual("Direct ipv4 ip version", "4", x.IpVersion, t)
|
||||
assert.Int64Equal("Direct ipv4 imported", 12, x.Imported, t)
|
||||
assert.Int64Equal("Direct ipv4 exported", 34, x.Exported, t)
|
||||
assert.Int64Equal("Direct ipv4 filtered", 1, x.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv4 preferred", 100, x.Preferred, t)
|
||||
assert.Int64Equal("Direct ipv4 import updates received", 1, x.ImportUpdates.Received, t)
|
||||
assert.Int64Equal("Direct ipv4 import updates rejected", 2, x.ImportUpdates.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv4 import updates filtered", 3, x.ImportUpdates.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv4 import updates ignored", 4, x.ImportUpdates.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv4 import updates accepted", 5, x.ImportUpdates.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv4 import withdraws received", 6, x.ImportWithdraws.Received, t)
|
||||
assert.Int64Equal("Direct ipv4 import withdraws rejected", 7, x.ImportWithdraws.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv4 import withdraws filtered", 8, x.ImportWithdraws.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv4 import withdraws ignored", 9, x.ImportWithdraws.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv4 import withdraws accepted", 10, x.ImportWithdraws.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv4 export updates received", 11, x.ExportUpdates.Received, t)
|
||||
assert.Int64Equal("Direct ipv4 export updates rejected", 12, x.ExportUpdates.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv4 export updates filtered", 13, x.ExportUpdates.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv4 export updates ignored", 14, x.ExportUpdates.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv4 export updates accepted", 15, x.ExportUpdates.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv4 export withdraws received", 16, x.ExportWithdraws.Received, t)
|
||||
assert.Int64Equal("Direct ipv4 export withdraws rejected", 17, x.ExportWithdraws.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv4 export withdraws filtered", 18, x.ExportWithdraws.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv4 export withdraws ignored", 19, x.ExportWithdraws.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv4 export withdraws accepted", 0, x.ExportWithdraws.Accepted, t)
|
||||
|
||||
x = p[2]
|
||||
assert.StringEqual("BGP ipv4 name", "direct1", x.Name, t)
|
||||
assert.IntEqual("Direct ipv6 proto", protocol.Direct, x.Proto, t)
|
||||
assert.StringEqual("Direct ipv6 ip version", "6", x.IpVersion, t)
|
||||
assert.Int64Equal("Direct ipv6 imported", 3, x.Imported, t)
|
||||
assert.Int64Equal("Direct ipv6 exported", 5, x.Exported, t)
|
||||
assert.Int64Equal("Direct ipv6 filtered", 7, x.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv6 preferred", 13, x.Preferred, t)
|
||||
assert.Int64Equal("Direct ipv6 import updates received", 20, x.ImportUpdates.Received, t)
|
||||
assert.Int64Equal("Direct ipv6 import updates rejected", 21, x.ImportUpdates.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv6 import updates filtered", 22, x.ImportUpdates.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv6 import updates ignored", 23, x.ImportUpdates.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv6 import updates accepted", 24, x.ImportUpdates.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv6 import withdraws received", 25, x.ImportWithdraws.Received, t)
|
||||
assert.Int64Equal("Direct ipv6 import withdraws rejected", 26, x.ImportWithdraws.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv6 import withdraws filtered", 27, x.ImportWithdraws.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv6 import withdraws ignored", 28, x.ImportWithdraws.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv6 import withdraws accepted", 29, x.ImportWithdraws.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv6 export updates received", 30, x.ExportUpdates.Received, t)
|
||||
assert.Int64Equal("Direct ipv6 export updates rejected", 31, x.ExportUpdates.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv6 export updates filtered", 32, x.ExportUpdates.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv6 export updates ignored", 33, x.ExportUpdates.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv6 export updates accepted", 34, x.ExportUpdates.Accepted, t)
|
||||
assert.Int64Equal("Direct ipv6 export withdraws received", 35, x.ExportWithdraws.Received, t)
|
||||
assert.Int64Equal("Direct ipv6 export withdraws rejected", 36, x.ExportWithdraws.Rejected, t)
|
||||
assert.Int64Equal("Direct ipv6 export withdraws filtered", 37, x.ExportWithdraws.Filtered, t)
|
||||
assert.Int64Equal("Direct ipv6 export withdraws ignored", 38, x.ExportWithdraws.Ignored, t)
|
||||
assert.Int64Equal("Direct ipv6 export withdraws accepted", 0, x.ExportWithdraws.Accepted, t)
|
||||
|
||||
x = p[3]
|
||||
assert.StringEqual("OSPF ipv4 name", "ospf1", x.Name, t)
|
||||
assert.IntEqual("OSPF ipv4 proto", protocol.OSPF, x.Proto, t)
|
||||
assert.StringEqual("OSPF ipv4 ip version", "4", x.IpVersion, t)
|
||||
assert.Int64Equal("OSPF ipv4 imported", 4, x.Imported, t)
|
||||
assert.Int64Equal("OSPF ipv4 exported", 2, x.Exported, t)
|
||||
assert.Int64Equal("OSPF ipv4 filtered", 3, x.Filtered, t)
|
||||
assert.Int64Equal("OSPF ipv4 preferred", 1, x.Preferred, t)
|
||||
}
|
||||
|
||||
func TestOspfOldTimeFormat(t *testing.T) {
|
||||
data := "ospf1 OSPF master up 1481973060 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -116,12 +233,12 @@ func TestOspfOldTimeFormat(t *testing.T) {
|
||||
assert.Int64Equal("imported", 12, x.Imported, t)
|
||||
assert.Int64Equal("exported", 34, x.Exported, t)
|
||||
assert.Int64Equal("preferred", 100, x.Preferred, t)
|
||||
assert.IntEqual("ipVersion", 4, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "4", x.IpVersion, t)
|
||||
}
|
||||
|
||||
func TestOspfCurrentTimeFormat(t *testing.T) {
|
||||
data := "ospf1 OSPF master up 00:01:00 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -131,13 +248,13 @@ func TestOspfCurrentTimeFormat(t *testing.T) {
|
||||
assert.Int64Equal("imported", 12, x.Imported, t)
|
||||
assert.Int64Equal("exported", 34, x.Exported, t)
|
||||
assert.Int64Equal("preferred", 100, x.Preferred, t)
|
||||
assert.IntEqual("ipVersion", 4, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "4", x.IpVersion, t)
|
||||
assert.IntEqual("uptime", 60, x.Uptime, t)
|
||||
}
|
||||
|
||||
func TestOspfProtocolDown(t *testing.T) {
|
||||
data := "o_hrz OSPF t_hrz down 1494926415 \n Preference: 150\n Input filter: ACCEPT\n Output filter: REJECT\nxxx"
|
||||
p := parser.Parse([]byte(data), 6)
|
||||
p := parser.Parse([]byte(data), "6")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -146,12 +263,12 @@ func TestOspfProtocolDown(t *testing.T) {
|
||||
assert.IntEqual("up", 0, x.Up, t)
|
||||
assert.Int64Equal("imported", 0, x.Imported, t)
|
||||
assert.Int64Equal("exported", 0, x.Exported, t)
|
||||
assert.IntEqual("ipVersion", 6, x.IpVersion, t)
|
||||
assert.StringEqual("ipVersion", "6", x.IpVersion, t)
|
||||
}
|
||||
|
||||
func TestOspfRunning(t *testing.T) {
|
||||
data := "ospf1 OSPF master up 00:01:00 Running\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
@ -160,7 +277,7 @@ func TestOspfRunning(t *testing.T) {
|
||||
|
||||
func TestOspfAlone(t *testing.T) {
|
||||
data := "ospf1 OSPF master up 00:01:00 Alone\ntest\nbar\n Routes: 12 imported, 34 exported, 100 preferred\nxxx"
|
||||
p := parser.Parse([]byte(data), 4)
|
||||
p := parser.Parse([]byte(data), "4")
|
||||
assert.IntEqual("protocols", 1, len(p), t)
|
||||
|
||||
x := p[0]
|
||||
|
@ -7,12 +7,11 @@ const (
|
||||
Kernel = 4
|
||||
Static = 8
|
||||
Direct = 16
|
||||
Device = 32
|
||||
)
|
||||
|
||||
type Protocol struct {
|
||||
Name string
|
||||
IpVersion int
|
||||
IpVersion string
|
||||
Proto int
|
||||
Up int
|
||||
Imported int64
|
||||
@ -35,6 +34,6 @@ type RouteChangeCount struct {
|
||||
Accepted int64
|
||||
}
|
||||
|
||||
func NewProtocol(name string, proto, ipVersion, uptime int) *Protocol {
|
||||
func NewProtocol(name string, proto int, ipVersion string, uptime int) *Protocol {
|
||||
return &Protocol{Name: name, Proto: proto, IpVersion: ipVersion, Uptime: uptime, Attributes: make(map[string]float64)}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user