Skip to content

Commit

Permalink
Add link_speed
Browse files Browse the repository at this point in the history
  • Loading branch information
dalance committed Oct 8, 2018
1 parent 34f65d3 commit 328f692
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
| prosafe_receive_bytes_total | Incoming transfer in bytes | port |
| prosafe_transmit_bytes_total | Outgoing transfer in bytes | port |
| prosafe_error_packets_total | Transfer error in packets | port |
| prosafe_link_speed | Link speed in Mbps | port |
| prosafe_build_info | prosafe_exporter Build information | version, revision, rustversion |

## Tested Switches
Expand Down
30 changes: 25 additions & 5 deletions src/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use hyper::rt::{self, Future};
use hyper::service::service_fn_ok;
use hyper::{Body, Response, Server, Uri};
use prometheus::{Encoder, Gauge, GaugeVec, Opts, Registry, TextEncoder};
use prosafe_switch::ProSafeSwitch;
use prosafe_switch::{Link, ProSafeSwitch};
use url::form_urlencoded;

// ---------------------------------------------------------------------------------------------------------------------
Expand All @@ -20,6 +20,7 @@ lazy_static! {
);
static ref ERROR_PACKETS_OPT: Opts =
Opts::new("prosafe_error_packets_total", "Transfer error in packets.");
static ref LINK_SPEED_OPT: Opts = Opts::new("prosafe_link_speed", "Link speed in Mbps.");
static ref BUILD_INFO_OPT: Opts = Opts::new(
"prosafe_build_info",
"A metric with a constant '1' value labeled by version, revision and rustversion."
Expand Down Expand Up @@ -76,7 +77,7 @@ impl Exporter {

let server = Server::bind(&addr)
.serve(service)
.map_err(|e| eprintln!("server error: {}", e));
.map_err(|e| eprintln!("Server error: {}", e));

rt::run(server);

Expand All @@ -95,12 +96,14 @@ impl Exporter {
let receive_bytes = GaugeVec::new(RECEIVE_BYTES_OPT.clone(), &["port"]).unwrap();
let transmit_bytes = GaugeVec::new(TRANSMIT_BYTES_OPT.clone(), &["port"]).unwrap();
let error_packets = GaugeVec::new(ERROR_PACKETS_OPT.clone(), &["port"]).unwrap();
let link_speed = GaugeVec::new(LINK_SPEED_OPT.clone(), &["port"]).unwrap();

let _ = registry.register(Box::new(build_info.clone()));
let _ = registry.register(Box::new(up.clone()));
let _ = registry.register(Box::new(receive_bytes.clone()));
let _ = registry.register(Box::new(transmit_bytes.clone()));
let _ = registry.register(Box::new(error_packets.clone()));
let _ = registry.register(Box::new(link_speed.clone()));

let git_revision = GIT_REVISION.unwrap_or("");
let rust_version = RUST_VERSION.unwrap_or("");
Expand Down Expand Up @@ -144,11 +147,28 @@ impl Exporter {
}
Err(x) => {
up.set(0.0);

if verbose {
println!("Fail to access: {}", x);
eprintln!("Fail to access: {}", x);
}
}
match sw.speed_stat() {
Ok(stats) => {
for s in stats.stats {
let speed = match s.link {
Link::None => 0,
Link::Speed10Mbps => 10,
Link::Speed100Mbps => 100,
Link::Speed1Gbps => 1000,
Link::Speed10Gbps => 10000,
Link::Unknown => 0,
};
link_speed
.with_label_values(&[&format!("{}", s.port_no)])
.set(speed as f64);
}
}
Err(x) => {
eprintln!("Fail to access: {}", x);
}
}
}
}
Expand Down
85 changes: 85 additions & 0 deletions src/prosafe_switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::time::Duration;
#[repr(u32)]
enum Cmd {
PortStat = 0x10000000,
SpeedStat = 0x0c000000,
End = 0xffff0000,
}

Expand Down Expand Up @@ -116,6 +117,85 @@ impl PortStats {
}
}

// ---------------------------------------------------------------------------------------------------------------------
// SpeedStats
// ---------------------------------------------------------------------------------------------------------------------

#[derive(Debug)]
pub struct SpeedStats {
pub stats: Vec<SpeedStat>,
}

#[derive(Debug)]
pub struct SpeedStat {
pub port_no: u8,
pub link: Link,
}

#[derive(Debug)]
pub enum Link {
None,
Speed10Mbps,
Speed100Mbps,
Speed1Gbps,
Speed10Gbps,
Unknown,
}

impl SpeedStats {
fn decode(dat: &[u8]) -> Result<Self, Error> {
let (_, rest) = bytes(&[0x01, 0x02])
.and(be_u16())
.and(be_u16())
.and(skip_count(26, any()))
.parse(dat)
.map_err(|x| format_err!("failed to parse: {:?}", x))?;
let mut stats = Vec::new();
let mut buf = rest;
while buf.len() != 0 {
let ((cmd, len), rest) = be_u16()
.and(be_u16())
.parse(buf)
.map_err(|x| format_err!("failed to parse: {:?}", x))?;
buf = rest;

if cmd == 0xffff {
break;
}

let (dat, rest) = count::<Vec<_>, _>(len as usize, any())
.parse(buf)
.map_err(|x| format_err!("failed to parse: {:?}", x))?;
buf = rest;

let ((port_no, metrics), _rest) = any()
.and(count::<Vec<_>, _>(2, any()))
.parse(&dat as &[u8])
.map_err(|x| format_err!("failed to parse: {:?}", x))?;

let link = match metrics[0] {
0 => Link::None,
1 => Link::Speed10Mbps,
2 => Link::Speed10Mbps,
3 => Link::Speed100Mbps,
4 => Link::Speed100Mbps,
5 => Link::Speed1Gbps,
6 => Link::Speed10Gbps,
_ => Link::Unknown,
};

let stat = SpeedStat {
port_no: port_no,
link: link,
};

stats.push(stat);
}

Ok(SpeedStats { stats: stats })
}
}

// ---------------------------------------------------------------------------------------------------------------------
// ProSafeSwitch
// ---------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -176,4 +256,9 @@ impl ProSafeSwitch {
let ret = self.request(Cmd::PortStat)?;
Ok(PortStats::decode(&ret)?)
}

pub fn speed_stat(&self) -> Result<SpeedStats, Error> {
let ret = self.request(Cmd::SpeedStat)?;
Ok(SpeedStats::decode(&ret)?)
}
}

0 comments on commit 328f692

Please sign in to comment.