Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic mpls lsp #184

Merged
merged 6 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions collectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
"github.com/czerwonk/junos_exporter/ipsec"
"github.com/czerwonk/junos_exporter/isis"
"github.com/czerwonk/junos_exporter/l2circuit"
"github.com/czerwonk/junos_exporter/lacp"
"github.com/czerwonk/junos_exporter/ldp"
"github.com/czerwonk/junos_exporter/mac"
"github.com/czerwonk/junos_exporter/mpls_lsp"
"github.com/czerwonk/junos_exporter/nat"
"github.com/czerwonk/junos_exporter/nat2"
"github.com/czerwonk/junos_exporter/ospf"
Expand All @@ -32,6 +34,7 @@ import (
"github.com/czerwonk/junos_exporter/storage"
"github.com/czerwonk/junos_exporter/system"
"github.com/czerwonk/junos_exporter/vrrp"
"github.com/czerwonk/junos_exporter/vpws"
)

type collectors struct {
Expand Down Expand Up @@ -87,6 +90,7 @@ func (c *collectors) initCollectorsForDevices(device *connector.Device) {
c.addCollectorIfEnabledForDevice(device, "ipsec", f.IPSec, ipsec.NewCollector)
c.addCollectorIfEnabledForDevice(device, "isis", f.ISIS, isis.NewCollector)
c.addCollectorIfEnabledForDevice(device, "l2c", f.L2Circuit, l2circuit.NewCollector)
c.addCollectorIfEnabledForDevice(device, "lacp", f.LACP, lacp.NewCollector)
c.addCollectorIfEnabledForDevice(device, "ldp", f.LDP, ldp.NewCollector)
c.addCollectorIfEnabledForDevice(device, "nat", f.NAT, nat.NewCollector)
c.addCollectorIfEnabledForDevice(device, "nat2", f.NAT2, nat2.NewCollector)
Expand All @@ -102,6 +106,8 @@ func (c *collectors) initCollectorsForDevices(device *connector.Device) {
c.addCollectorIfEnabledForDevice(device, "power", f.Power, power.NewCollector)
c.addCollectorIfEnabledForDevice(device, "mac", f.MAC, mac.NewCollector)
c.addCollectorIfEnabledForDevice(device, "vrrp", f.VRRP, vrrp.NewCollector)
c.addCollectorIfEnabledForDevice(device, "vpws", f.VPWS, vpws.NewCollector)
c.addCollectorIfEnabledForDevice(device, "mpls_lsp", f.MPLS_LSP, mpls_lsp.NewCollector)
}

func (c *collectors) addCollectorIfEnabledForDevice(device *connector.Device, key string, enabled bool, newCollector func() collector.RPCCollector) {
Expand Down
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type FeatureConfig struct {
NAT bool `yaml:"nat,omitempty"`
NAT2 bool `yaml:"nat2,omitempty"`
L2Circuit bool `yaml:"l2circuit,omitempty"`
LACP bool `yaml:"lacp,omitempty"`
LDP bool `yaml:"ldp,omitempty"`
Routes bool `yaml:"routes,omitempty"`
RoutingEngine bool `yaml:"routing_engine,omitempty"`
Expand All @@ -59,6 +60,8 @@ type FeatureConfig struct {
System bool `yaml:"system,omitempty"`
Power bool `yaml:"power,omitempty"`
MAC bool `yaml:"mac,omitempty"`
MPLS_LSP bool `yaml:"mpls_lsp,omitempty"`
VPWS bool `yaml:"vpws,omitempty"`
VRRP bool `yaml:"vrrp,omitempty"`
}

Expand Down Expand Up @@ -126,6 +129,8 @@ func setDefaultValues(c *Config) {
f.Satellite = false
f.Power = false
f.MAC = false
f.MPLS_LSP = false
f.VPWS = false
f.VRRP = false
}

Expand Down
65 changes: 65 additions & 0 deletions lacp/collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package lacp

import (
"github.com/czerwonk/junos_exporter/collector"
"github.com/czerwonk/junos_exporter/rpc"
"github.com/prometheus/client_golang/prometheus"
)

const prefix = "junos_lacp_"

var (
lacpMuxState *prometheus.Desc
lacpMuxStateMap = map[string]int{
"Detached": 1,
"Waiting": 2,
"Attached": 3,
"Collecting": 4,
"Distributing": 5,
"Collecting distributing": 6,
}
)

func init() {
l := []string{"target", "name", "member"}
lacpMuxState = prometheus.NewDesc(prefix+"muxstate", "lacp mux state (1: detached, 2: waiting, 3: attached, 4: collecting, 5: distributing, 6: collecting distribuging)", l, nil)
}

type lacpCollector struct {
}

// Name returns the name of the collector
func (*lacpCollector) Name() string {
return "lacp"
}

// NewCollector creates a new collector
func NewCollector() collector.RPCCollector {
return &lacpCollector{}
}

// Describe describes the metrics
func (*lacpCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- lacpMuxState
}


// Collect collects metrics from JunOS
func (c *lacpCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metric, labelValues []string) error {
var x = lacpRpc{}
err := client.RunCommandAndParse("show lacp interfaces", &x)
if err != nil {
return err
}

for _, iface := range x.Information.LacpInterfaces {

for _, member := range iface.LagLacpProtocols {
l := append(labelValues, iface.LagLacpHeader.Name, member.Member)
ch <- prometheus.MustNewConstMetric(lacpMuxState, prometheus.GaugeValue, float64(lacpMuxStateMap[member.LacpMuxState]), l...)
}

}

return nil
}
25 changes: 25 additions & 0 deletions lacp/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package lacp

type lacpRpc struct {
Information struct {
LacpInterfaces []lacpInterface `xml:"lacp-interface-information"`
} `xml:"lacp-interface-information-list"`
}

type lacpInterface struct {
LagLacpHeader struct {
Name string `xml:"aggregate-name"`
} `xml:"lag-lacp-header"`
LagLacpStates []LagLacpStateStruct `xml:"lag-lacp-state"`
LagLacpProtocols []LagLacpProtocolStruct `xml:"lag-lacp-protocol"`
}


type LagLacpStateStruct struct{
}

type LagLacpProtocolStruct struct{
Member string `xml:"name"`
LacpMuxState string `xml:"lacp-mux-state"`
}

5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ var (
interfaceDescriptionRegex = flag.String("interface-description-regex", "", "give a regex to retrieve the interface description labels")
lsEnabled = flag.Bool("logical-systems.enabled", false, "Enable logical systems support")
powerEnabled = flag.Bool("power.enabled", true, "Scrape power metrics")
bfdEnabled = flag.Bool("bfd.enabled", true, "Scrape bfd metrics")
lacpEnabled = flag.Bool("lacp.enabled", false, "Scrape lacp metrics")
bfdEnabled = flag.Bool("bfd.enabled", false, "Scrape bfd metrics")
vpwsEnabled = flag.Bool("vpws.enabled", false, "Scrape evpn vpws metrics")
mpls_lspEnabled = flag.Bool("mpls_lsp.enabled", false, "Scrape mpls LSP metrics")
cfg *config.Config
devices []*connector.Device
connManager *connector.SSHConnectionManager
Expand Down
71 changes: 71 additions & 0 deletions mpls_lsp/collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package mpls_lsp

import (
"github.com/czerwonk/junos_exporter/collector"
"github.com/czerwonk/junos_exporter/rpc"
"github.com/prometheus/client_golang/prometheus"
)

const prefix = "junos_mpls_lsp_"

var (
mpls_lspState *prometheus.Desc
mpls_lspPathState *prometheus.Desc
mpls_lspPathFlapCount *prometheus.Desc

mpls_lspStateMap = map[string]int{
"Dn": 0,
"Up": 1,
}

)

func init() {
ls := []string{"target", "lspname", "lspsrc", "lspdst" }
mpls_lspState = prometheus.NewDesc(prefix+"state", "mpls_lsp state (0: down, 1:up)", ls, nil)

lps := []string{"target", "lspname", "lspsrc", "lspdst", "title", "name"}
mpls_lspPathState = prometheus.NewDesc(prefix+"path_state", "mpls_lsp pathstate (0: down, 1:up)", lps, nil)
mpls_lspPathFlapCount = prometheus.NewDesc(prefix+"path_flapcount", "mpls_lsp path flap count", lps, nil)
}

type mpls_lspCollector struct {
}

// Name returns the name of the collector
func (*mpls_lspCollector) Name() string {
return "mpls_lsp"
}

// NewCollector creates a new collector
func NewCollector() collector.RPCCollector {
return &mpls_lspCollector{}
}

// Describe describes the metrics
func (*mpls_lspCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- mpls_lspState
}


// Collect collects metrics from JunOS
func (c *mpls_lspCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metric, labelValues []string) error {
var x = mpls_lspRpc{}
err := client.RunCommandAndParse("show mpls lsp ingress extensive", &x) //ingress:Display LSPs originating at this router
if err != nil {
return err
}

for _, lsp := range x.Information.Sessions {
l := append(labelValues, lsp.Name, lsp.SrcIP, lsp.DstIP)
ch <- prometheus.MustNewConstMetric(mpls_lspState, prometheus.GaugeValue, float64(mpls_lspStateMap[lsp.LSPState]), l...)

for _, path := range lsp.Path {
l := append(labelValues, lsp.Name, lsp.SrcIP, lsp.DstIP, path.Title, path.Name)
ch <- prometheus.MustNewConstMetric(mpls_lspPathState, prometheus.GaugeValue, float64(mpls_lspStateMap[path.State]), l...)
ch <- prometheus.MustNewConstMetric(mpls_lspPathFlapCount, prometheus.GaugeValue, float64(path.FlapCount), l...)
}
}

return nil
}
24 changes: 24 additions & 0 deletions mpls_lsp/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package mpls_lsp

type mpls_lspRpc struct {
Information struct {
Sessions []mpls_lspSession `xml:"rsvp-session"`
} `xml:"mpls-lsp-information>rsvp-session-data"`
}

type mpls_lspSession struct {
DstIP string `xml:"mpls-lsp>destination-address"`
SrcIP string `xml:"mpls-lsp>source-address"`
LSPState string `xml:"mpls-lsp>lsp-state"`
Name string `xml:"mpls-lsp>name"`

Path []mpls_lspPath `xml:"mpls-lsp>mpls-lsp-path"`
}

type mpls_lspPath struct {
Title string `xml:"title"`
Name string `xml:"name"`
State string `xml:"path-state"`
FlapCount int64 `xml:"path-flap-count"`
}

82 changes: 82 additions & 0 deletions vpws/collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package vpws

import (
"github.com/czerwonk/junos_exporter/collector"
"github.com/czerwonk/junos_exporter/rpc"
"github.com/prometheus/client_golang/prometheus"
)

const prefix = "junos_vpws_"

var (
vpwsStatus *prometheus.Desc
vpwsSid *prometheus.Desc

vpwsStatusMap = map[string]int{
"Down": 0,
"Up": 1,
}

vpwsSidMap = map[string]int{
"Unresolved": 0,
"Resolved": 1,
}

)

func init() {
l := []string{"target", "vpwsinstance", "rd", "interface", "esi", "mode", "role"}
vpwsStatus = prometheus.NewDesc(prefix+"status", "vpws status (0: down, 1:up)", l, nil)

ls := []string{"target", "vpwsinstance", "rd", "interface", "sidorigin", "sid", "ip", "esi", "mode", "role"}
vpwsSid = prometheus.NewDesc(prefix+"sid", "vpws sid (0: Unresolved, 1:Resolved)", ls, nil)
}

type vpwsCollector struct {
}

// Name returns the name of the collector
func (*vpwsCollector) Name() string {
return "vpws"
}

// NewCollector creates a new collector
func NewCollector() collector.RPCCollector {
return &vpwsCollector{}
}

// Describe describes the metrics
func (*vpwsCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- vpwsStatus
ch <- vpwsSid
}


// Collect collects metrics from JunOS
func (c *vpwsCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metric, labelValues []string) error {
var x = vpwsRpc{}
err := client.RunCommandAndParse("show evpn vpws-instance", &x)
if err != nil {
return err
}

for _, vInst := range x.Information.VpwsInstances {
for _, vIf := range vInst.VpwsInterfaces {
l := append(labelValues, vInst.Name, vInst.RD, vIf.Name, vIf.Esi, vIf.Mode, vIf.Role )
ch <- prometheus.MustNewConstMetric(vpwsStatus, prometheus.GaugeValue, float64(vpwsStatusMap[vIf.Status]), l...)

for _, vSid := range vIf.LocalStatus.SidPeInfo {
l := append(labelValues, vInst.Name, vInst.RD, vIf.Name, "local", vIf.LocalStatus.Sid, vSid.IP, vSid.Esi, vSid.Mode, vSid.Role )
ch <- prometheus.MustNewConstMetric(vpwsSid, prometheus.GaugeValue, float64(vpwsSidMap[vSid.Status]), l...)
}

for _, vSid := range vIf.RemoteStatus.SidPeInfo {
l := append(labelValues, vInst.Name, vInst.RD, vIf.Name, "remote", vIf.RemoteStatus.Sid, vSid.IP, vSid.Esi, vSid.Mode, vSid.Role )
ch <- prometheus.MustNewConstMetric(vpwsSid, prometheus.GaugeValue, float64(vpwsSidMap[vSid.Status]), l...)
}

}
}

return nil
}
48 changes: 48 additions & 0 deletions vpws/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package vpws


type vpwsRpc struct {
Information struct {
VpwsInstances []vpwsInstance `xml:"evpn-vpws-instance"`
} `xml:"evpn-vpws-information"`
}


type vpwsInstance struct {
Name string `xml:"evpn-vpws-instance-name"`
RD string `xml:"route-distinguisher"`
LocalInterfaces int64 `xml:"local-interfaces"`
LocalInterfacesUp int64 `xml:"local-interfaces-up"`

VpwsInterfaces []vpwsInterface `xml:"evpn-vpws-interface-status-table>evpn-vpws-interface"`
}



type vpwsInterface struct {
Name string `xml:"evpn-vpws-interface-name"`
Esi string `xml:"evpn-vpws-interface-esi"`
Mode string `xml:"evpn-vpws-interface-mode"`
Role string `xml:"evpn-vpws-interface-role"`
Status string `xml:"evpn-vpws-interface-status"`

LocalStatus struct {
Sid string `xml:"evpn-vpws-sid-local-value"`
SidPeInfo []vpwsSidPeInfo `xml:"evpn-vpws-sid-pe-status-table>evpn-vpws-sid-pe-info"`
} `xml:"evpn-vpws-service-id-local-status-table>evpn-vpws-sid-local"`

RemoteStatus struct {
Sid string `xml:"evpn-vpws-sid-remote-value"`
SidPeInfo []vpwsSidPeInfo `xml:"evpn-vpws-sid-pe-status-table>evpn-vpws-sid-pe-info"`
} `xml:"evpn-vpws-service-id-remote-status-table>evpn-vpws-sid-remote"`

}


type vpwsSidPeInfo struct {
Esi string `xml:"evpn-vpws-sid-interface-esi"`
IP string `xml:"evpn-vpws-sid-pe-ipaddr"`
Mode string `xml:"evpn-vpws-sid-pe-mode"`
Role string `xml:"evpn-vpws-sid-pe-role"`
Status string `xml:"evpn-vpws-sid-pe-status"`
}