Skip to main content

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}