netstack3_base/device/
link.rs1use core::fmt::Debug;
11
12use net_types::ethernet::Mac;
13use net_types::{MulticastAddress, UnicastAddress};
14use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
15
16use crate::Device;
17
18pub trait LinkAddress:
20 'static
21 + FromBytes
22 + IntoBytes
23 + KnownLayout
24 + Immutable
25 + Unaligned
26 + Copy
27 + Clone
28 + Debug
29 + Eq
30 + Send
31{
32 const BYTES_LENGTH: usize;
34
35 fn bytes(&self) -> &[u8];
37
38 fn from_bytes(bytes: &[u8]) -> Self;
45}
46
47impl LinkAddress for Mac {
48 const BYTES_LENGTH: usize = 6;
49
50 fn bytes(&self) -> &[u8] {
51 self.as_ref()
52 }
53
54 fn from_bytes(bytes: &[u8]) -> Self {
55 debug_assert_eq!(bytes.len(), Self::BYTES_LENGTH);
57 let mut b = [0; Self::BYTES_LENGTH];
58 b.copy_from_slice(bytes);
59 Self::new(b)
60 }
61}
62
63pub trait LinkDeviceAddress: LinkAddress + UnicastAddress + MulticastAddress {}
65impl<L: LinkAddress + UnicastAddress + MulticastAddress> LinkDeviceAddress for L {}
66
67pub trait LinkDevice: Device + Debug {
72 type Address: LinkDeviceAddress;
74}
75
76#[cfg(any(test, feature = "testutils"))]
78pub(crate) mod testutil {
79 use net_types::BroadcastAddress;
80 use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
81
82 use super::*;
83 use crate::testutil::{FakeCoreCtx, FakeStrongDeviceId, FakeWeakDeviceId};
84 use crate::{DeviceIdContext, DeviceIdentifier, StrongDeviceIdentifier};
85
86 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
88 pub enum FakeLinkDevice {}
89
90 const FAKE_LINK_ADDRESS_LEN: usize = 1;
91
92 #[derive(
96 KnownLayout,
97 FromBytes,
98 IntoBytes,
99 Immutable,
100 Unaligned,
101 Copy,
102 Clone,
103 Debug,
104 Hash,
105 PartialEq,
106 Eq,
107 )]
108 #[repr(transparent)]
109 pub struct FakeLinkAddress(pub [u8; FAKE_LINK_ADDRESS_LEN]);
110
111 impl FakeLinkAddress {
112 const BROADCAST: Self = Self([0xff; FAKE_LINK_ADDRESS_LEN]);
113 }
114
115 impl UnicastAddress for FakeLinkAddress {
116 #[inline]
117 fn is_unicast(&self) -> bool {
118 self.0[0] & 1 == 0
119 }
120 }
121
122 impl MulticastAddress for FakeLinkAddress {
123 #[inline]
124 fn is_multicast(&self) -> bool {
125 (self.0[0] & 1 == 1) && !self.is_broadcast()
126 }
127 }
128
129 impl BroadcastAddress for FakeLinkAddress {
130 #[inline]
131 fn is_broadcast(&self) -> bool {
132 *self == Self::BROADCAST
133 }
134 }
135
136 impl LinkAddress for FakeLinkAddress {
137 const BYTES_LENGTH: usize = FAKE_LINK_ADDRESS_LEN;
138
139 fn bytes(&self) -> &[u8] {
140 &self.0[..]
141 }
142
143 fn from_bytes(bytes: &[u8]) -> FakeLinkAddress {
144 FakeLinkAddress(bytes.try_into().unwrap())
145 }
146 }
147
148 impl Device for FakeLinkDevice {}
149
150 impl LinkDevice for FakeLinkDevice {
151 type Address = FakeLinkAddress;
152 }
153
154 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
156 pub struct FakeLinkDeviceId;
157
158 impl StrongDeviceIdentifier for FakeLinkDeviceId {
159 type Weak = FakeWeakDeviceId<Self>;
160
161 fn downgrade(&self) -> Self::Weak {
162 FakeWeakDeviceId(*self)
163 }
164 }
165
166 impl DeviceIdentifier for FakeLinkDeviceId {
167 fn is_loopback(&self) -> bool {
168 false
169 }
170 }
171
172 impl<S, M> DeviceIdContext<FakeLinkDevice> for FakeCoreCtx<S, M, FakeLinkDeviceId> {
173 type DeviceId = FakeLinkDeviceId;
174 type WeakDeviceId = FakeWeakDeviceId<FakeLinkDeviceId>;
175 }
176
177 impl FakeStrongDeviceId for FakeLinkDeviceId {
178 fn is_alive(&self) -> bool {
179 true
180 }
181 }
182
183 impl PartialEq<FakeWeakDeviceId<FakeLinkDeviceId>> for FakeLinkDeviceId {
184 fn eq(&self, FakeWeakDeviceId(other): &FakeWeakDeviceId<FakeLinkDeviceId>) -> bool {
185 self == other
186 }
187 }
188}