Skip to content

Commit c757fc7

Browse files
maerlynnshttpd
authored andcommitted
Create ipsec collector (#51)
1 parent 0250e6c commit c757fc7

File tree

6 files changed

+126
-1
lines changed

6 files changed

+126
-1
lines changed

collector/collector.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ func WithTLS(insecure bool) Option {
134134
}
135135
}
136136

137+
// WithIpsec enables ipsec metrics
138+
func WithIpsec() Option {
139+
return func(c *collector) {
140+
c.collectors = append(c.collectors, newIpsecCollector())
141+
}
142+
}
143+
137144
// Option applies options to collector
138145
type Option func(*collector)
139146

collector/ipsec_collector.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package collector
2+
3+
import (
4+
"strconv"
5+
"strings"
6+
7+
"github.com/prometheus/client_golang/prometheus"
8+
log "github.com/sirupsen/logrus"
9+
"gopkg.in/routeros.v2/proto"
10+
)
11+
12+
type ipsecCollector struct {
13+
props []string
14+
descriptions map[string]*prometheus.Desc
15+
}
16+
17+
func newIpsecCollector() routerOSCollector {
18+
c := &ipsecCollector{}
19+
c.init()
20+
return c
21+
}
22+
23+
func (c *ipsecCollector) init() {
24+
c.props = []string{"src-address", "dst-address", "ph2-state", "invalid", "active", "comment"}
25+
26+
labelNames := []string{"devicename", "srcdst", "comment"}
27+
c.descriptions = make(map[string]*prometheus.Desc)
28+
for _, p := range c.props[1:] {
29+
c.descriptions[p] = descriptionForPropertyName("ipsec", p, labelNames)
30+
}
31+
}
32+
33+
func (c *ipsecCollector) describe(ch chan<- *prometheus.Desc) {
34+
for _, d := range c.descriptions {
35+
ch <- d
36+
}
37+
}
38+
39+
func (c *ipsecCollector) collect(ctx *collectorContext) error {
40+
stats, err := c.fetch(ctx)
41+
if err != nil {
42+
return err
43+
}
44+
45+
for _, re := range stats {
46+
c.collectForStat(re, ctx)
47+
}
48+
49+
return nil
50+
}
51+
52+
func (c *ipsecCollector) fetch(ctx *collectorContext) ([]*proto.Sentence, error) {
53+
reply, err := ctx.client.Run("/ip/ipsec/policy/print", "?disabled=false", "?dynamic=false", "=.proplist="+strings.Join(c.props, ","))
54+
if err != nil {
55+
log.WithFields(log.Fields{
56+
"device": ctx.device.Name,
57+
"error": err,
58+
}).Error("error fetching interface metrics")
59+
return nil, err
60+
}
61+
62+
return reply.Re, nil
63+
}
64+
65+
func (c *ipsecCollector) collectForStat(re *proto.Sentence, ctx *collectorContext) {
66+
srcdst := re.Map["src-address"] + "-" + re.Map["dst-address"]
67+
comment := re.Map["comment"]
68+
69+
for _, p := range c.props[2:] {
70+
c.collectMetricForProperty(p, srcdst, comment, re, ctx)
71+
}
72+
}
73+
74+
func (c *ipsecCollector) collectMetricForProperty(property, srcdst, comment string, re *proto.Sentence, ctx *collectorContext) {
75+
desc := c.descriptions[property]
76+
if value := re.Map[property]; value != "" {
77+
var v float64
78+
var err error
79+
v, err = strconv.ParseFloat(value, 64)
80+
81+
switch property {
82+
case "ph2-state":
83+
if value == "established" {
84+
v, err = 1, nil
85+
} else {
86+
v, err = 0, nil
87+
}
88+
case "active", "invalid":
89+
if value == "true" {
90+
v, err = 1, nil
91+
} else {
92+
v, err = 0, nil
93+
}
94+
case "comment":
95+
return
96+
}
97+
98+
if err != nil {
99+
log.WithFields(log.Fields{
100+
"device": ctx.device.Name,
101+
"srcdst": srcdst,
102+
"property": property,
103+
"value": value,
104+
"error": err,
105+
}).Error("error parsing ipsec metric value")
106+
return
107+
}
108+
ctx.ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, v, ctx.device.Name, srcdst, comment)
109+
}
110+
}

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type Config struct {
2020
WlanSTA bool `yaml:"wlansta,omitempty"`
2121
WlanIF bool `yaml:"wlanif,omitempty"`
2222
Monitor bool `yaml:"monitor,omitempty"`
23+
Ipsec bool `yaml:"ipsec,omitempty"`
2324
} `yaml:"features,omitempty"`
2425
}
2526

config/config.test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ features:
1717
pools: true
1818
optics: true
1919
wlansta: true
20-
wlanif: true
20+
wlanif: true
21+
ipsec: true

config/config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func TestShouldParse(t *testing.T) {
2727
assertFeature("Optics", c.Features.Optics, t)
2828
assertFeature("WlanSTA", c.Features.WlanSTA, t)
2929
assertFeature("WlanIF", c.Features.WlanIF, t)
30+
assertFeature("Ipsec", c.Features.Ipsec, t)
3031
}
3132

3233
func loadTestFile(t *testing.T) []byte {

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var (
4343
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
4444
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
4545
withMonitor = flag.Bool("with-monitor", false, "retrieves ethernet interface monitor info")
46+
withIpsec = flag.Bool("with-ipsec", false, "retrieves ipsec metrics")
4647

4748
cfg *config.Config
4849

@@ -208,6 +209,10 @@ func collectorOptions() []collector.Option {
208209

209210
}
210211

212+
if *withIpsec || cfg.Features.Ipsec {
213+
opts = append(opts, collector.WithIpsec())
214+
}
215+
211216
if *timeout != collector.DefaultTimeout {
212217
opts = append(opts, collector.WithTimeout(*timeout))
213218
}

0 commit comments

Comments
 (0)