erbium/lldp/mod.rs
1use crate::lldp::lldppkt::*;
2
3use erbium_net::raw::MsgFlags;
4
5pub mod lldppkt;
6
7pub struct LldpService {
8 sock: erbium_net::raw::RawSocket,
9}
10
11impl LldpService {
12 pub fn new() -> std::io::Result<LldpService> {
13 let sock = erbium_net::raw::RawSocket::new(erbium_net::raw::EthProto::LLDP)?;
14 Ok(Self { sock })
15 }
16
17 pub async fn run(&self) -> ! {
18 let mut prev = None;
19 loop {
20 match self.sock.recv_msg(1500, MsgFlags::empty()).await {
21 Err(err) => log::warn!("LLDP Failed to receive frame: {:?}", err),
22 Ok(msg) => {
23 use crate::pktparser::Deserialise as _;
24 match lldppkt::LldpPacket::from_wire(&mut crate::pktparser::Buffer::new(
25 &msg.buffer[14..],
26 )) {
27 Ok(new) => {
28 if prev.is_none() || prev.as_ref().unwrap() != &new {
29 for i in &new.tlvs {
30 match i {
31 LldpTlv::ChassisID(ChassisId {
32 r#type: ChassisIdType::ChassisComponent,
33 identifier,
34 }) => log::info!(
35 "{:?}: Peer Chassis Component: {:?}",
36 msg.local_intf(),
37 identifier
38 ),
39 LldpTlv::ChassisID(ChassisId {
40 r#type: ChassisIdType::InterfaceAlias,
41 identifier,
42 }) => log::info!(
43 "{:?}: Peer IfAlias: {}",
44 msg.local_intf(),
45 String::from_utf8_lossy(identifier)
46 ),
47 LldpTlv::ChassisID(ChassisId {
48 r#type: ChassisIdType::PortComponent,
49 identifier,
50 }) => log::info!(
51 "{:?}: Peer entPhysicalAlias: {}",
52 msg.local_intf(),
53 String::from_utf8_lossy(identifier)
54 ),
55 LldpTlv::ChassisID(ChassisId {
56 r#type: ChassisIdType::MacAddress,
57 identifier,
58 }) => log::info!(
59 "{:?}: Peer Device MAC Address: {:?}",
60 msg.local_intf(),
61 identifier
62 .iter()
63 .map(|o| format!("{:0>2x}", o))
64 .collect::<Vec<_>>()
65 .join(":")
66 ),
67 LldpTlv::ChassisID(ChassisId {
68 r#type: ChassisIdType::NetworkAddress,
69 identifier,
70 }) => log::info!(
71 "{:?}: Peer Device Network Address: {:?}",
72 msg.local_intf(),
73 /* TODO: Render this as an IPv4/IPv6 address */
74 identifier
75 .iter()
76 .map(|o| format!("{:0>2x}", o))
77 .collect::<Vec<_>>()
78 .join(":")
79 ),
80 LldpTlv::ChassisID(ChassisId {
81 r#type: ChassisIdType::InterfaceName,
82 identifier,
83 }) => log::info!(
84 "{:?}: Peer Interface Name: {}",
85 msg.local_intf(),
86 String::from_utf8_lossy(identifier)
87 ),
88 LldpTlv::ChassisID(ChassisId {
89 r#type: ChassisIdType::Local,
90 identifier,
91 }) => log::info!(
92 "{:?}: Peer Locally Defined Name: {}",
93 msg.local_intf(),
94 String::from_utf8_lossy(identifier)
95 ),
96 LldpTlv::PortID(PortId {
97 r#type: ty,
98 identifier,
99 }) => {
100 log::info!(
101 "{:?}: Peer Port {:?}: {}",
102 msg.local_intf(),
103 ty,
104 String::from_utf8_lossy(identifier)
105 );
106 }
107 other => {
108 log::info!(
109 "{:?}: Peer Attribute: {:?}",
110 msg.local_intf(),
111 other
112 );
113 }
114 }
115 }
116 prev = Some(new);
117 }
118 }
119 Err(e) => log::warn!("Failed to decode LLDP frame: {:?}", e),
120 }
121 }
122 }
123 }
124 }
125}