1use core::fmt::Debug;
8use core::num::NonZeroU8;
9use core::ops::Deref as _;
10
11use lock_order::lock::{DelegatedOrderedLockAccess, LockLevelFor, UnlockedAccess};
12use lock_order::relation::LockBefore;
13use log::debug;
14use net_types::ethernet::Mac;
15use net_types::ip::{
16 AddrSubnet, Ip, IpAddress, IpInvariant, IpVersion, IpVersionMarker, Ipv4, Ipv4Addr, Ipv6,
17 Ipv6Addr, Mtu,
18};
19use net_types::{MulticastAddr, SpecifiedAddr, UnicastAddr, Witness as _, map_ip_twice};
20use netstack3_base::{
21 AnyDevice, BroadcastIpExt, CounterContext, DeviceIdContext, ExistsError, IpAddressId,
22 IpDeviceAddressIdContext, Ipv4DeviceAddr, Ipv6DeviceAddr, NetworkSerializer, NotFoundError,
23 ReceivableFrameMeta, RecvIpFrameMeta, ReferenceNotifiersExt, RemoveResourceResultWithContext,
24 ResourceCounterContext, SendFrameError, WeakDeviceIdentifier,
25};
26use netstack3_device::blackhole::{BlackholeDeviceCounters, BlackholeDeviceId};
27use netstack3_device::ethernet::{
28 self, EthernetDeviceCounters, EthernetDeviceId, EthernetIpLinkDeviceDynamicStateContext,
29 EthernetLinkDevice, EthernetPrimaryDeviceId, EthernetWeakDeviceId,
30};
31use netstack3_device::loopback::{self, LoopbackDevice, LoopbackDeviceId, LoopbackPrimaryDeviceId};
32use netstack3_device::pure_ip::{self, PureIpDeviceCounters, PureIpDeviceId};
33use netstack3_device::queue::TransmitQueueHandler;
34use netstack3_device::socket::{DeviceSocketCounters, DeviceSocketId, HeldDeviceSockets};
35use netstack3_device::{
36 ArpCounters, BaseDeviceId, DeviceCollectionContext, DeviceConfigurationContext, DeviceCounters,
37 DeviceId, DeviceLayerState, DeviceStateSpec, Devices, DevicesIter, IpLinkDeviceState,
38 IpLinkDeviceStateInner, Ipv6DeviceLinkLayerAddr, OriginTracker, OriginTrackerContext,
39 WeakDeviceId, for_any_device_id,
40};
41use netstack3_filter::ProofOfEgressCheck;
42use netstack3_ip::device::{
43 AddressId, AddressIdIter, DadState, DualStackIpDeviceState, IpAddressData, IpAddressEntry,
44 IpDeviceAddAddressContext, IpDeviceAddressContext, IpDeviceConfigurationContext, IpDeviceFlags,
45 IpDeviceIpExt, IpDeviceSendContext, IpDeviceStateContext, Ipv4AddrConfig,
46 Ipv4DeviceConfiguration, Ipv6AddrConfig, Ipv6DeviceConfiguration,
47 Ipv6DeviceConfigurationContext, Ipv6DeviceContext, Ipv6NetworkLearnedParameters,
48 PrimaryAddressId, WeakAddressId,
49};
50use netstack3_ip::nud::{
51 ConfirmationFlags, DynamicNeighborUpdateSource, NudHandler, NudIpHandler, NudUserConfig,
52};
53use netstack3_ip::{
54 self as ip, DeviceIpLayerMetadata, IpPacketDestination, IpRoutingDeviceContext, RawMetric,
55};
56use packet::BufferMut;
57use packet_formats::ethernet::EthernetIpExt;
58
59use crate::context::prelude::*;
60use crate::context::{CoreCtxAndResource, Locked, WrapLockLevel};
61use crate::ip::integration::CoreCtxWithIpDeviceConfiguration;
62use crate::{BindingsContext, BindingsTypes, CoreCtx, StackState};
63
64fn bytes_to_unicast_mac(b: &[u8]) -> Option<UnicastAddr<Mac>> {
65 (b.len() >= Mac::BYTES)
66 .then(|| {
67 let mut bytes = [0; Mac::BYTES];
68 bytes.copy_from_slice(&b[..Mac::BYTES]);
69 Mac::new(bytes)
70 })
71 .and_then(UnicastAddr::new)
72}
73
74impl<
75 I: Ip,
76 BC: BindingsContext,
77 L: LockBefore<crate::lock_ordering::EthernetIpv4Arp>
78 + LockBefore<crate::lock_ordering::EthernetIpv6Nud>,
79> NudIpHandler<I, BC> for CoreCtx<'_, BC, L>
80where
81 Self: NudHandler<I, EthernetLinkDevice, BC>
82 + DeviceIdContext<EthernetLinkDevice, DeviceId = EthernetDeviceId<BC>>,
83{
84 fn handle_neighbor_probe(
85 &mut self,
86 bindings_ctx: &mut BC,
87 device_id: &DeviceId<BC>,
88 neighbor: SpecifiedAddr<I::Addr>,
89 link_addr: &[u8],
90 ) {
91 match device_id {
92 DeviceId::Ethernet(id) => {
93 if let Some(link_address) = bytes_to_unicast_mac(link_addr) {
94 NudHandler::<I, EthernetLinkDevice, _>::handle_neighbor_update(
95 self,
96 bindings_ctx,
97 &id,
98 neighbor,
99 DynamicNeighborUpdateSource::Probe { link_address },
100 )
101 }
102 }
103 DeviceId::Loopback(LoopbackDeviceId { .. })
105 | DeviceId::Blackhole(BlackholeDeviceId { .. })
106 | DeviceId::PureIp(PureIpDeviceId { .. }) => {}
107 }
108 }
109
110 fn handle_neighbor_confirmation(
111 &mut self,
112 bindings_ctx: &mut BC,
113 device_id: &DeviceId<BC>,
114 neighbor: SpecifiedAddr<I::Addr>,
115 link_addr: Option<&[u8]>,
116 flags: ConfirmationFlags,
117 ) {
118 match device_id {
119 DeviceId::Ethernet(id) => {
120 let link_address = match link_addr {
121 Some(link_addr) => {
122 let Some(link_addr) = bytes_to_unicast_mac(link_addr) else {
125 return;
126 };
127 Some(link_addr)
128 }
129 None => None,
130 };
131
132 NudHandler::<I, EthernetLinkDevice, _>::handle_neighbor_update(
133 self,
134 bindings_ctx,
135 &id,
136 neighbor,
137 DynamicNeighborUpdateSource::Confirmation { link_address, flags },
138 )
139 }
140 DeviceId::Loopback(LoopbackDeviceId { .. })
142 | DeviceId::Blackhole(BlackholeDeviceId { .. })
143 | DeviceId::PureIp(PureIpDeviceId { .. }) => {}
144 }
145 }
146
147 fn flush_neighbor_table(&mut self, bindings_ctx: &mut BC, device_id: &DeviceId<BC>) {
148 match device_id {
149 DeviceId::Ethernet(id) => {
150 NudHandler::<I, EthernetLinkDevice, _>::flush(self, bindings_ctx, &id)
151 }
152 DeviceId::Loopback(LoopbackDeviceId { .. })
154 | DeviceId::Blackhole(BlackholeDeviceId { .. })
155 | DeviceId::PureIp(PureIpDeviceId { .. }) => {}
156 }
157 }
158}
159
160impl<I, D, L, BC> ReceivableFrameMeta<CoreCtx<'_, BC, L>, BC>
161 for RecvIpFrameMeta<D, DeviceIpLayerMetadata<BC>, I>
162where
163 BC: BindingsContext,
164 D: Into<DeviceId<BC>>,
165 L: LockBefore<crate::lock_ordering::IcmpAllSocketsSet<Ipv4>>,
166 I: Ip,
167{
168 fn receive_meta<B: BufferMut + Debug>(
169 self,
170 core_ctx: &mut CoreCtx<'_, BC, L>,
171 bindings_ctx: &mut BC,
172 frame: B,
173 ) {
174 let RecvIpFrameMeta {
175 device,
176 frame_dst,
177 ip_layer_metadata,
178 marker: IpVersionMarker { .. },
179 parsing_context,
180 } = self;
181 let device = device.into();
182 match I::VERSION {
183 IpVersion::V4 => ip::receive_ipv4_packet(
184 core_ctx,
185 bindings_ctx,
186 &device,
187 frame_dst,
188 ip_layer_metadata,
189 parsing_context,
190 frame,
191 ),
192 IpVersion::V6 => ip::receive_ipv6_packet(
193 core_ctx,
194 bindings_ctx,
195 &device,
196 frame_dst,
197 ip_layer_metadata,
198 parsing_context,
199 frame,
200 ),
201 }
202 }
203}
204
205#[netstack3_macros::instantiate_ip_impl_block(I)]
206impl<I: BroadcastIpExt, BC: BindingsContext, L: LockBefore<crate::lock_ordering::FilterState<I>>>
207 IpDeviceSendContext<I, BC> for CoreCtx<'_, BC, L>
208{
209 fn send_ip_frame<S>(
210 &mut self,
211 bindings_ctx: &mut BC,
212 device: &DeviceId<BC>,
213 destination: IpPacketDestination<I, &DeviceId<BC>>,
214 ip_layer_metadata: DeviceIpLayerMetadata<BC>,
215 body: S,
216 ProofOfEgressCheck { .. }: ProofOfEgressCheck,
217 ) -> Result<(), SendFrameError<S>>
218 where
219 S: NetworkSerializer,
220 S::Buffer: BufferMut,
221 {
222 send_ip_frame(self, bindings_ctx, device, destination, ip_layer_metadata, body)
223 }
224}
225
226#[netstack3_macros::instantiate_ip_impl_block(I)]
227impl<
228 I: BroadcastIpExt,
229 Config,
230 BC: BindingsContext,
231 L: LockBefore<crate::lock_ordering::FilterState<I>>,
232> IpDeviceSendContext<I, BC> for CoreCtxWithIpDeviceConfiguration<'_, Config, L, BC>
233{
234 fn send_ip_frame<S>(
235 &mut self,
236 bindings_ctx: &mut BC,
237 device: &DeviceId<BC>,
238 destination: IpPacketDestination<I, &DeviceId<BC>>,
239 ip_layer_metadata: DeviceIpLayerMetadata<BC>,
240 body: S,
241 ProofOfEgressCheck { .. }: ProofOfEgressCheck,
242 ) -> Result<(), SendFrameError<S>>
243 where
244 S: NetworkSerializer,
245 S::Buffer: BufferMut,
246 {
247 let Self { config: _, core_ctx } = self;
248 send_ip_frame(core_ctx, bindings_ctx, device, destination, ip_layer_metadata, body)
249 }
250}
251
252impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceConfiguration<Ipv4>>>
253 IpDeviceConfigurationContext<Ipv4, BC> for CoreCtx<'_, BC, L>
254{
255 type DevicesIter<'s> = DevicesIter<'s, BC>;
256 type WithIpDeviceConfigurationInnerCtx<'s> = CoreCtxWithIpDeviceConfiguration<
257 's,
258 &'s Ipv4DeviceConfiguration,
259 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv4>>,
260 BC,
261 >;
262 type WithIpDeviceConfigurationMutInner<'s> = CoreCtxWithIpDeviceConfiguration<
263 's,
264 &'s mut Ipv4DeviceConfiguration,
265 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv4>>,
266 BC,
267 >;
268 type DeviceAddressAndGroupsAccessor<'s> =
269 CoreCtx<'s, BC, WrapLockLevel<crate::lock_ordering::DeviceLayerState>>;
270
271 fn with_ip_device_configuration<
272 O,
273 F: FnOnce(&Ipv4DeviceConfiguration, Self::WithIpDeviceConfigurationInnerCtx<'_>) -> O,
274 >(
275 &mut self,
276 device_id: &Self::DeviceId,
277 cb: F,
278 ) -> O {
279 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
280 let (state, mut locked) = core_ctx_and_resource
281 .read_lock_with_and::<crate::lock_ordering::IpDeviceConfiguration<Ipv4>, _>(|c| {
282 c.right()
283 });
284 cb(
285 &state,
286 CoreCtxWithIpDeviceConfiguration { config: &state, core_ctx: locked.cast_core_ctx() },
287 )
288 }
289
290 fn with_ip_device_configuration_mut<
291 O,
292 F: FnOnce(Self::WithIpDeviceConfigurationMutInner<'_>) -> O,
293 >(
294 &mut self,
295 device_id: &Self::DeviceId,
296 cb: F,
297 ) -> O {
298 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
299 let (mut state, mut locked) = core_ctx_and_resource
300 .write_lock_with_and::<crate::lock_ordering::IpDeviceConfiguration<Ipv4>, _>(
301 |c| c.right(),
302 );
303 cb(CoreCtxWithIpDeviceConfiguration {
304 config: &mut state,
305 core_ctx: locked.cast_core_ctx(),
306 })
307 }
308
309 fn with_devices_and_state<
310 O,
311 F: FnOnce(Self::DevicesIter<'_>, Self::DeviceAddressAndGroupsAccessor<'_>) -> O,
312 >(
313 &mut self,
314 cb: F,
315 ) -> O {
316 let (devices, locked) = self.read_lock_and::<crate::lock_ordering::DeviceLayerState>();
317 cb(devices.iter(), locked)
318 }
319
320 fn loopback_id(&mut self) -> Option<Self::DeviceId> {
321 let devices = &*self.read_lock::<crate::lock_ordering::DeviceLayerState>();
322 devices.loopback.as_ref().map(|primary| DeviceId::Loopback(primary.clone_strong()))
323 }
324}
325
326impl<BC: BindingsContext, L> IpDeviceAddressIdContext<Ipv4> for CoreCtx<'_, BC, L> {
327 type AddressId = AddressId<Ipv4, BC>;
328 type WeakAddressId = WeakAddressId<Ipv4, BC>;
329}
330
331impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceAddresses<Ipv4>>>
332 IpDeviceAddAddressContext<Ipv4, BC> for CoreCtx<'_, BC, L>
333{
334 fn add_ip_address(
335 &mut self,
336 device_id: &Self::DeviceId,
337 addr: AddrSubnet<Ipv4Addr, Ipv4DeviceAddr>,
338 config: Ipv4AddrConfig<BC::Instant>,
339 ) -> Result<Self::AddressId, ExistsError> {
340 let mut state = ip_device_state(self, device_id);
341 let addr_id = state
342 .write_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv4>>()
343 .add(IpAddressEntry::new(addr, DadState::Uninitialized, config));
344 addr_id
345 }
346}
347
348impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceAddresses<Ipv4>>>
349 IpDeviceStateContext<Ipv4, BC> for CoreCtx<'_, BC, L>
350{
351 type IpDeviceAddressCtx<'a> =
352 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IpDeviceAddresses<Ipv4>>>;
353
354 fn with_ip_device_flags<O, F: FnOnce(&IpDeviceFlags) -> O>(
355 &mut self,
356 device_id: &Self::DeviceId,
357 cb: F,
358 ) -> O {
359 let mut state = ip_device_state(self, device_id);
360 let flags = &*state.lock::<crate::lock_ordering::IpDeviceFlags<Ipv4>>();
361 cb(flags)
362 }
363
364 fn remove_ip_address(
365 &mut self,
366 device_id: &Self::DeviceId,
367 addr: Self::AddressId,
368 ) -> RemoveResourceResultWithContext<AddrSubnet<Ipv4Addr>, BC> {
369 let mut state = ip_device_state(self, device_id);
370 let primary = state
371 .write_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv4>>()
372 .remove(&addr.addr().addr())
373 .expect("should exist when address ID exists");
374 assert!(PrimaryAddressId::ptr_eq(&primary, &addr));
375 core::mem::drop(addr);
376
377 BC::unwrap_or_notify_with_new_reference_notifier(primary.into_inner(), |entry| {
378 entry.addr_sub().to_witness::<SpecifiedAddr<_>>()
379 })
380 }
381
382 fn get_address_id(
383 &mut self,
384 device_id: &Self::DeviceId,
385 addr: SpecifiedAddr<Ipv4Addr>,
386 ) -> Result<Self::AddressId, NotFoundError> {
387 let mut state = ip_device_state(self, device_id);
388 let addr_id = state
389 .read_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv4>>()
390 .iter()
391 .find(|a| {
392 let a: Ipv4Addr = a.addr().get();
393 a == *addr
394 })
395 .map(PrimaryAddressId::clone_strong)
396 .ok_or(NotFoundError);
397 addr_id
398 }
399
400 type AddressIdsIter<'a> = AddressIdIter<'a, Ipv4, BC>;
401 fn with_address_ids<
402 O,
403 F: FnOnce(Self::AddressIdsIter<'_>, &mut Self::IpDeviceAddressCtx<'_>) -> O,
404 >(
405 &mut self,
406 device_id: &Self::DeviceId,
407 cb: F,
408 ) -> O {
409 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
410 let (state, mut locked) = core_ctx_and_resource
411 .read_lock_with_and::<crate::lock_ordering::IpDeviceAddresses<Ipv4>, _>(|c| c.right());
412 cb(state.strong_iter(), &mut locked.cast_core_ctx())
413 }
414
415 fn with_default_hop_limit<O, F: FnOnce(&NonZeroU8) -> O>(
416 &mut self,
417 device_id: &Self::DeviceId,
418 cb: F,
419 ) -> O {
420 let mut state = ip_device_state(self, device_id);
421 let mut state = state.read_lock::<crate::lock_ordering::IpDeviceDefaultHopLimit<Ipv4>>();
422 cb(&mut state)
423 }
424
425 fn with_default_hop_limit_mut<O, F: FnOnce(&mut NonZeroU8) -> O>(
426 &mut self,
427 device_id: &Self::DeviceId,
428 cb: F,
429 ) -> O {
430 let mut state = ip_device_state(self, device_id);
431 let mut state = state.write_lock::<crate::lock_ordering::IpDeviceDefaultHopLimit<Ipv4>>();
432 cb(&mut state)
433 }
434
435 fn join_link_multicast_group(
436 &mut self,
437 bindings_ctx: &mut BC,
438 device_id: &Self::DeviceId,
439 multicast_addr: MulticastAddr<Ipv4Addr>,
440 ) {
441 join_link_multicast_group(self, bindings_ctx, device_id, multicast_addr)
442 }
443
444 fn leave_link_multicast_group(
445 &mut self,
446 bindings_ctx: &mut BC,
447 device_id: &Self::DeviceId,
448 multicast_addr: MulticastAddr<Ipv4Addr>,
449 ) {
450 leave_link_multicast_group(self, bindings_ctx, device_id, multicast_addr)
451 }
452}
453
454impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>>
455 Ipv6DeviceConfigurationContext<BC> for CoreCtx<'_, BC, L>
456{
457 type Ipv6DeviceStateCtx<'s> = CoreCtxWithIpDeviceConfiguration<
458 's,
459 &'s Ipv6DeviceConfiguration,
460 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>,
461 BC,
462 >;
463 type WithIpv6DeviceConfigurationMutInner<'s> = CoreCtxWithIpDeviceConfiguration<
464 's,
465 &'s mut Ipv6DeviceConfiguration,
466 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>,
467 BC,
468 >;
469
470 fn with_ipv6_device_configuration<
471 O,
472 F: FnOnce(&Ipv6DeviceConfiguration, Self::Ipv6DeviceStateCtx<'_>) -> O,
473 >(
474 &mut self,
475 device_id: &Self::DeviceId,
476 cb: F,
477 ) -> O {
478 IpDeviceConfigurationContext::<Ipv6, _>::with_ip_device_configuration(self, device_id, cb)
479 }
480
481 fn with_ipv6_device_configuration_mut<
482 O,
483 F: FnOnce(Self::WithIpv6DeviceConfigurationMutInner<'_>) -> O,
484 >(
485 &mut self,
486 device_id: &Self::DeviceId,
487 cb: F,
488 ) -> O {
489 IpDeviceConfigurationContext::<Ipv6, _>::with_ip_device_configuration_mut(
490 self, device_id, cb,
491 )
492 }
493}
494
495impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>>
496 IpDeviceConfigurationContext<Ipv6, BC> for CoreCtx<'_, BC, L>
497{
498 type DevicesIter<'s> = DevicesIter<'s, BC>;
499 type WithIpDeviceConfigurationInnerCtx<'s> = CoreCtxWithIpDeviceConfiguration<
500 's,
501 &'s Ipv6DeviceConfiguration,
502 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>,
503 BC,
504 >;
505 type WithIpDeviceConfigurationMutInner<'s> = CoreCtxWithIpDeviceConfiguration<
506 's,
507 &'s mut Ipv6DeviceConfiguration,
508 WrapLockLevel<crate::lock_ordering::IpDeviceConfiguration<Ipv6>>,
509 BC,
510 >;
511 type DeviceAddressAndGroupsAccessor<'s> =
512 CoreCtx<'s, BC, WrapLockLevel<crate::lock_ordering::DeviceLayerState>>;
513
514 fn with_ip_device_configuration<
515 O,
516 F: FnOnce(&Ipv6DeviceConfiguration, Self::WithIpDeviceConfigurationInnerCtx<'_>) -> O,
517 >(
518 &mut self,
519 device_id: &Self::DeviceId,
520 cb: F,
521 ) -> O {
522 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
523 let (state, mut locked) = core_ctx_and_resource
524 .read_lock_with_and::<crate::lock_ordering::IpDeviceConfiguration<Ipv6>, _>(|c| {
525 c.right()
526 });
527 cb(
528 &state,
529 CoreCtxWithIpDeviceConfiguration { config: &state, core_ctx: locked.cast_core_ctx() },
530 )
531 }
532
533 fn with_ip_device_configuration_mut<
534 O,
535 F: FnOnce(Self::WithIpDeviceConfigurationMutInner<'_>) -> O,
536 >(
537 &mut self,
538 device_id: &Self::DeviceId,
539 cb: F,
540 ) -> O {
541 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
542 let (mut state, mut locked) = core_ctx_and_resource
543 .write_lock_with_and::<crate::lock_ordering::IpDeviceConfiguration<Ipv6>, _>(
544 |c| c.right(),
545 );
546 cb(CoreCtxWithIpDeviceConfiguration {
547 config: &mut state,
548 core_ctx: locked.cast_core_ctx(),
549 })
550 }
551
552 fn with_devices_and_state<
553 O,
554 F: FnOnce(Self::DevicesIter<'_>, Self::DeviceAddressAndGroupsAccessor<'_>) -> O,
555 >(
556 &mut self,
557 cb: F,
558 ) -> O {
559 let (devices, locked) = self.read_lock_and::<crate::lock_ordering::DeviceLayerState>();
560 cb(devices.iter(), locked)
561 }
562
563 fn loopback_id(&mut self) -> Option<Self::DeviceId> {
564 let devices = &*self.read_lock::<crate::lock_ordering::DeviceLayerState>();
565 devices.loopback.as_ref().map(|primary| DeviceId::Loopback(primary.clone_strong()))
566 }
567}
568
569impl<BC: BindingsContext, L> IpDeviceAddressIdContext<Ipv6> for CoreCtx<'_, BC, L> {
570 type AddressId = AddressId<Ipv6, BC>;
571 type WeakAddressId = WeakAddressId<Ipv6, BC>;
572}
573
574#[netstack3_macros::instantiate_ip_impl_block(I)]
575impl<
576 I: IpLayerIpExt,
577 BC: BindingsContext,
578 L: LockBefore<crate::lock_ordering::IpDeviceAddressData<I>>,
579> IpDeviceAddressContext<I, BC> for CoreCtx<'_, BC, L>
580{
581 fn with_ip_address_data<O, F: FnOnce(&IpAddressData<I, BC::Instant>) -> O>(
582 &mut self,
583 _device_id: &Self::DeviceId,
584 addr_id: &Self::AddressId,
585 cb: F,
586 ) -> O {
587 let mut locked = self.adopt(addr_id.deref());
588 let x = cb(&locked
589 .read_lock_with::<crate::lock_ordering::IpDeviceAddressData<I>, _>(|c| c.right()));
590 x
591 }
592
593 fn with_ip_address_data_mut<O, F: FnOnce(&mut IpAddressData<I, BC::Instant>) -> O>(
594 &mut self,
595 _device_id: &Self::DeviceId,
596 addr_id: &Self::AddressId,
597 cb: F,
598 ) -> O {
599 let mut locked = self.adopt(addr_id.deref());
600 let x = cb(&mut locked
601 .write_lock_with::<crate::lock_ordering::IpDeviceAddressData<I>, _>(|c| c.right()));
602 x
603 }
604}
605
606impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceAddresses<Ipv6>>>
607 IpDeviceAddAddressContext<Ipv6, BC> for CoreCtx<'_, BC, L>
608{
609 fn add_ip_address(
610 &mut self,
611 device_id: &Self::DeviceId,
612 addr: AddrSubnet<Ipv6Addr, Ipv6DeviceAddr>,
613 config: Ipv6AddrConfig<BC::Instant>,
614 ) -> Result<Self::AddressId, ExistsError> {
615 let mut state = ip_device_state(self, device_id);
616 let addr_id = state
617 .write_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv6>>()
618 .add(IpAddressEntry::new(addr, DadState::Uninitialized, config));
619 addr_id
620 }
621}
622
623impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceAddresses<Ipv6>>>
624 IpDeviceStateContext<Ipv6, BC> for CoreCtx<'_, BC, L>
625{
626 type IpDeviceAddressCtx<'a> =
627 CoreCtx<'a, BC, WrapLockLevel<crate::lock_ordering::IpDeviceAddresses<Ipv6>>>;
628
629 fn with_ip_device_flags<O, F: FnOnce(&IpDeviceFlags) -> O>(
630 &mut self,
631 device_id: &Self::DeviceId,
632 cb: F,
633 ) -> O {
634 let mut state = ip_device_state(self, device_id);
635 let flags = &*state.lock::<crate::lock_ordering::IpDeviceFlags<Ipv6>>();
636 cb(flags)
637 }
638
639 fn remove_ip_address(
640 &mut self,
641 device_id: &Self::DeviceId,
642 addr: Self::AddressId,
643 ) -> RemoveResourceResultWithContext<AddrSubnet<Ipv6Addr>, BC> {
644 let mut state = ip_device_state(self, device_id);
645 let primary = state
646 .write_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv6>>()
647 .remove(&addr.addr().addr())
648 .expect("should exist when address ID exists");
649 assert!(PrimaryAddressId::ptr_eq(&primary, &addr));
650 core::mem::drop(addr);
651
652 BC::unwrap_or_notify_with_new_reference_notifier(primary.into_inner(), |entry| {
653 entry.addr_sub().to_witness::<SpecifiedAddr<_>>()
654 })
655 }
656
657 fn get_address_id(
658 &mut self,
659 device_id: &Self::DeviceId,
660 addr: SpecifiedAddr<Ipv6Addr>,
661 ) -> Result<Self::AddressId, NotFoundError> {
662 let mut state = ip_device_state(self, device_id);
663 let addr_id = state
664 .read_lock::<crate::lock_ordering::IpDeviceAddresses<Ipv6>>()
665 .iter()
666 .find_map(|a| {
667 let inner: Ipv6Addr = a.addr().get();
668 (inner == *addr).then(|| PrimaryAddressId::clone_strong(a))
669 })
670 .ok_or(NotFoundError);
671 addr_id
672 }
673
674 type AddressIdsIter<'a> = AddressIdIter<'a, Ipv6, BC>;
675 fn with_address_ids<
676 O,
677 F: FnOnce(Self::AddressIdsIter<'_>, &mut Self::IpDeviceAddressCtx<'_>) -> O,
678 >(
679 &mut self,
680 device_id: &Self::DeviceId,
681 cb: F,
682 ) -> O {
683 let mut core_ctx_and_resource = ip_device_state_and_core_ctx(self, device_id);
684 let (state, mut core_ctx) = core_ctx_and_resource
685 .read_lock_with_and::<crate::lock_ordering::IpDeviceAddresses<Ipv6>, _>(|c| c.right());
686 cb(state.strong_iter(), &mut core_ctx.cast_core_ctx())
687 }
688
689 fn with_default_hop_limit<O, F: FnOnce(&NonZeroU8) -> O>(
690 &mut self,
691 device_id: &Self::DeviceId,
692 cb: F,
693 ) -> O {
694 let mut state = ip_device_state(self, device_id);
695 let mut state = state.read_lock::<crate::lock_ordering::IpDeviceDefaultHopLimit<Ipv6>>();
696 cb(&mut state)
697 }
698
699 fn with_default_hop_limit_mut<O, F: FnOnce(&mut NonZeroU8) -> O>(
700 &mut self,
701 device_id: &Self::DeviceId,
702 cb: F,
703 ) -> O {
704 let mut state = ip_device_state(self, device_id);
705 let mut state = state.write_lock::<crate::lock_ordering::IpDeviceDefaultHopLimit<Ipv6>>();
706 cb(&mut state)
707 }
708
709 fn join_link_multicast_group(
710 &mut self,
711 bindings_ctx: &mut BC,
712 device_id: &Self::DeviceId,
713 multicast_addr: MulticastAddr<Ipv6Addr>,
714 ) {
715 join_link_multicast_group(self, bindings_ctx, device_id, multicast_addr)
716 }
717
718 fn leave_link_multicast_group(
719 &mut self,
720 bindings_ctx: &mut BC,
721 device_id: &Self::DeviceId,
722 multicast_addr: MulticastAddr<Ipv6Addr>,
723 ) {
724 leave_link_multicast_group(self, bindings_ctx, device_id, multicast_addr)
725 }
726}
727
728impl<BC: BindingsContext, L: LockBefore<crate::lock_ordering::IpDeviceAddresses<Ipv6>>>
729 Ipv6DeviceContext<BC> for CoreCtx<'_, BC, L>
730{
731 type LinkLayerAddr = Ipv6DeviceLinkLayerAddr;
732
733 fn get_link_layer_addr(
734 &mut self,
735 device_id: &Self::DeviceId,
736 ) -> Option<Ipv6DeviceLinkLayerAddr> {
737 match device_id {
738 DeviceId::Ethernet(id) => {
739 Some(Ipv6DeviceLinkLayerAddr::Mac(ethernet::get_mac(self, &id).get()))
740 }
741 DeviceId::Loopback(LoopbackDeviceId { .. })
742 | DeviceId::Blackhole(BlackholeDeviceId { .. })
743 | DeviceId::PureIp(PureIpDeviceId { .. }) => None,
744 }
745 }
746
747 fn set_link_mtu(&mut self, device_id: &Self::DeviceId, mtu: Mtu) {
748 if mtu < Ipv6::MINIMUM_LINK_MTU {
749 return;
750 }
751
752 match device_id {
753 DeviceId::Ethernet(id) => ethernet::set_mtu(self, &id, mtu),
754 DeviceId::Loopback(LoopbackDeviceId { .. }) => {}
755 DeviceId::PureIp(id) => pure_ip::set_mtu(self, &id, mtu),
756 DeviceId::Blackhole(BlackholeDeviceId { .. }) => {}
757 }
758 }
759
760 fn with_network_learned_parameters<O, F: FnOnce(&Ipv6NetworkLearnedParameters) -> O>(
761 &mut self,
762 device_id: &Self::DeviceId,
763 cb: F,
764 ) -> O {
765 let mut state = ip_device_state(self, device_id);
766 let state = state.read_lock::<crate::lock_ordering::Ipv6DeviceLearnedParams>();
767 cb(&state)
768 }
769
770 fn with_network_learned_parameters_mut<O, F: FnOnce(&mut Ipv6NetworkLearnedParameters) -> O>(
771 &mut self,
772 device_id: &Self::DeviceId,
773 cb: F,
774 ) -> O {
775 let mut state = ip_device_state(self, device_id);
776 let mut state = state.write_lock::<crate::lock_ordering::Ipv6DeviceLearnedParams>();
777 cb(&mut state)
778 }
779}
780
781impl<BT: BindingsTypes, L> DeviceIdContext<EthernetLinkDevice> for CoreCtx<'_, BT, L> {
782 type DeviceId = EthernetDeviceId<BT>;
783 type WeakDeviceId = EthernetWeakDeviceId<BT>;
784}
785
786impl<BT: BindingsTypes> DelegatedOrderedLockAccess<Devices<BT>> for StackState<BT> {
787 type Inner = DeviceLayerState<BT>;
788 fn delegate_ordered_lock_access(&self) -> &Self::Inner {
789 &self.device
790 }
791}
792
793impl<BT: BindingsTypes> LockLevelFor<StackState<BT>> for crate::lock_ordering::DeviceLayerState {
794 type Data = Devices<BT>;
795}
796
797impl<BT: BindingsTypes, L> DeviceIdContext<AnyDevice> for CoreCtx<'_, BT, L> {
798 type DeviceId = DeviceId<BT>;
799 type WeakDeviceId = WeakDeviceId<BT>;
800}
801
802impl<T, BT: BindingsTypes> UnlockedAccess<crate::lock_ordering::UnlockedState>
811 for IpLinkDeviceStateInner<T, BT>
812{
813 type Data = IpLinkDeviceStateInner<T, BT>;
814 type Guard<'l>
815 = &'l IpLinkDeviceStateInner<T, BT>
816 where
817 Self: 'l;
818
819 fn access(&self) -> Self::Guard<'_> {
820 &self
821 }
822}
823
824pub(crate) fn device_state<'a, BT: BindingsTypes, L, D: DeviceStateSpec>(
825 core_ctx: &'a mut CoreCtx<'_, BT, L>,
826 device_id: &'a BaseDeviceId<D, BT>,
827) -> Locked<&'a IpLinkDeviceState<D, BT>, L> {
828 let state = device_id.device_state(
829 &core_ctx.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
830 );
831 core_ctx.replace(state)
832}
833
834pub(crate) fn device_state_and_core_ctx<'a, BT: BindingsTypes, L, D: DeviceStateSpec>(
835 core_ctx: &'a mut CoreCtx<'_, BT, L>,
836 id: &'a BaseDeviceId<D, BT>,
837) -> CoreCtxAndResource<'a, BT, IpLinkDeviceState<D, BT>, L> {
838 let state = id.device_state(
839 &core_ctx.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
840 );
841 core_ctx.adopt(state)
842}
843
844pub(crate) fn ip_device_state<'a, BC: BindingsContext, L>(
845 core_ctx: &'a mut CoreCtx<'_, BC, L>,
846 device: &'a DeviceId<BC>,
847) -> Locked<&'a DualStackIpDeviceState<BC>, L> {
848 for_any_device_id!(
849 DeviceId,
850 device,
851 id => {
852 let state = id.device_state(
853 &core_ctx.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin
854 );
855 core_ctx.replace(state.as_ref())
856 }
857 )
858}
859
860pub(crate) fn ip_device_state_and_core_ctx<'a, BC: BindingsContext, L>(
861 core_ctx: &'a mut CoreCtx<'_, BC, L>,
862 device: &'a DeviceId<BC>,
863) -> CoreCtxAndResource<'a, BC, DualStackIpDeviceState<BC>, L> {
864 for_any_device_id!(
865 DeviceId,
866 device,
867 id => {
868 let state = id.device_state(
869 &core_ctx.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin
870 );
871 core_ctx.adopt(state.as_ref())
872 }
873 )
874}
875
876pub(crate) fn get_mtu<
877 BC: BindingsContext,
878 L: LockBefore<crate::lock_ordering::EthernetDeviceDynamicState>,
879>(
880 core_ctx: &mut CoreCtx<'_, BC, L>,
881 device: &DeviceId<BC>,
882) -> Mtu {
883 match device {
884 DeviceId::Ethernet(id) => ethernet::get_mtu(core_ctx, &id),
885 DeviceId::Loopback(id) => device_state(core_ctx, id).cast_with(|s| &s.link.mtu).copied(),
886 DeviceId::PureIp(id) => pure_ip::get_mtu(core_ctx, &id),
887 DeviceId::Blackhole(_id) => Mtu::no_limit(),
888 }
889}
890
891fn join_link_multicast_group<
892 BC: BindingsContext,
893 A: IpAddress,
894 L: LockBefore<crate::lock_ordering::EthernetDeviceDynamicState>,
895>(
896 core_ctx: &mut CoreCtx<'_, BC, L>,
897 bindings_ctx: &mut BC,
898 device_id: &DeviceId<BC>,
899 multicast_addr: MulticastAddr<A>,
900) {
901 match device_id {
902 DeviceId::Ethernet(id) => ethernet::join_link_multicast(
903 core_ctx,
904 bindings_ctx,
905 &id,
906 MulticastAddr::from(&multicast_addr),
907 ),
908 DeviceId::Loopback(LoopbackDeviceId { .. })
909 | DeviceId::PureIp(PureIpDeviceId { .. })
910 | DeviceId::Blackhole(BlackholeDeviceId { .. }) => {}
911 }
912}
913
914fn leave_link_multicast_group<
915 BC: BindingsContext,
916 A: IpAddress,
917 L: LockBefore<crate::lock_ordering::EthernetDeviceDynamicState>,
918>(
919 core_ctx: &mut CoreCtx<'_, BC, L>,
920 bindings_ctx: &mut BC,
921 device_id: &DeviceId<BC>,
922 multicast_addr: MulticastAddr<A>,
923) {
924 match device_id {
925 DeviceId::Ethernet(id) => ethernet::leave_link_multicast(
926 core_ctx,
927 bindings_ctx,
928 &id,
929 MulticastAddr::from(&multicast_addr),
930 ),
931 DeviceId::Loopback(LoopbackDeviceId { .. })
932 | DeviceId::PureIp(PureIpDeviceId { .. })
933 | DeviceId::Blackhole(BlackholeDeviceId { .. }) => {}
934 }
935}
936
937fn send_ip_frame<BC, S, I, L>(
938 core_ctx: &mut CoreCtx<'_, BC, L>,
939 bindings_ctx: &mut BC,
940 device: &DeviceId<BC>,
941 destination: IpPacketDestination<I, &DeviceId<BC>>,
942 ip_layer_metadata: DeviceIpLayerMetadata<BC>,
943 body: S,
944) -> Result<(), SendFrameError<S>>
945where
946 BC: BindingsContext,
947 S: NetworkSerializer,
948 S::Buffer: BufferMut,
949 I: EthernetIpExt + BroadcastIpExt,
950 L: LockBefore<crate::lock_ordering::IpState<I>>
951 + LockBefore<crate::lock_ordering::LoopbackTxQueue>
952 + LockBefore<crate::lock_ordering::PureIpDeviceTxQueue>,
953 for<'a> CoreCtx<'a, BC, L>: EthernetIpLinkDeviceDynamicStateContext<BC, DeviceId = EthernetDeviceId<BC>>
954 + NudHandler<I, EthernetLinkDevice, BC>
955 + TransmitQueueHandler<EthernetLinkDevice, BC, Meta = BC::TxMetadata>,
956{
957 match device {
958 DeviceId::Ethernet(id) => ethernet::send_ip_frame(
959 core_ctx,
960 bindings_ctx,
961 id,
962 destination,
963 body,
964 ip_layer_metadata.into_tx_metadata(),
965 ),
966 DeviceId::Loopback(id) => loopback::send_ip_frame(
967 core_ctx,
968 bindings_ctx,
969 id,
970 destination,
971 ip_layer_metadata,
972 body,
973 ),
974 DeviceId::PureIp(id) => pure_ip::send_ip_frame(
975 core_ctx,
976 bindings_ctx,
977 id,
978 destination,
979 body,
980 ip_layer_metadata.into_tx_metadata(),
981 ),
982 DeviceId::Blackhole(id) => {
983 debug!("dropping frame in send_ip_frame on blackhole device {id:?}");
985 core_ctx.increment_both(id, DeviceCounters::send_frame::<I>);
986 Ok(())
987 }
988 }
989}
990
991impl<'a, BT, L> DeviceCollectionContext<EthernetLinkDevice, BT> for CoreCtx<'a, BT, L>
992where
993 BT: BindingsTypes,
994 L: LockBefore<crate::lock_ordering::DeviceLayerState>,
995{
996 fn insert(&mut self, device: EthernetPrimaryDeviceId<BT>) {
997 let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
998 let strong = device.clone_strong();
999 assert!(devices.ethernet.insert(strong, device).is_none());
1000 }
1001
1002 fn remove(&mut self, device: &EthernetDeviceId<BT>) -> Option<EthernetPrimaryDeviceId<BT>> {
1003 let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
1004 devices.ethernet.remove(device)
1005 }
1006}
1007
1008impl<'a, BT, L> DeviceCollectionContext<LoopbackDevice, BT> for CoreCtx<'a, BT, L>
1009where
1010 BT: BindingsTypes,
1011 L: LockBefore<crate::lock_ordering::DeviceLayerState>,
1012{
1013 fn insert(&mut self, device: LoopbackPrimaryDeviceId<BT>) {
1014 let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
1015 let prev = devices.loopback.replace(device);
1016 assert!(prev.is_none(), "can't install loopback device more than once");
1021 }
1022
1023 fn remove(&mut self, device: &LoopbackDeviceId<BT>) -> Option<LoopbackPrimaryDeviceId<BT>> {
1024 let mut devices = self.write_lock::<crate::lock_ordering::DeviceLayerState>();
1029 let primary = devices.loopback.take().expect("loopback device not installed");
1030 assert_eq!(device, &primary);
1031 Some(primary)
1032 }
1033}
1034
1035impl<'a, BT: BindingsTypes, L> OriginTrackerContext for CoreCtx<'a, BT, L> {
1036 fn origin_tracker(&mut self) -> OriginTracker {
1037 self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin.clone()
1038 }
1039}
1040
1041impl<'a, BT, L> DeviceConfigurationContext<EthernetLinkDevice> for CoreCtx<'a, BT, L>
1042where
1043 L: LockBefore<crate::lock_ordering::NudConfig<Ipv4>>
1044 + LockBefore<crate::lock_ordering::NudConfig<Ipv6>>,
1045 BT: BindingsTypes,
1046{
1047 fn with_nud_config<I: Ip, O, F: FnOnce(Option<&NudUserConfig>) -> O>(
1048 &mut self,
1049 device_id: &Self::DeviceId,
1050 f: F,
1051 ) -> O {
1052 let state = device_state(self, device_id);
1053 let IpInvariant(o) =
1056 map_ip_twice!(I, IpInvariant((state, f)), |IpInvariant((mut state, f))| {
1057 IpInvariant(f(Some(&*state.read_lock::<crate::lock_ordering::NudConfig<I>>())))
1058 });
1059 o
1060 }
1061
1062 fn with_nud_config_mut<I: Ip, O, F: FnOnce(Option<&mut NudUserConfig>) -> O>(
1063 &mut self,
1064 device_id: &Self::DeviceId,
1065 f: F,
1066 ) -> O {
1067 let state = device_state(self, device_id);
1068 let IpInvariant(o) =
1071 map_ip_twice!(I, IpInvariant((state, f)), |IpInvariant((mut state, f))| {
1072 IpInvariant(f(Some(&mut *state.write_lock::<crate::lock_ordering::NudConfig<I>>())))
1073 });
1074 o
1075 }
1076}
1077
1078impl<'a, BT, L> DeviceConfigurationContext<LoopbackDevice> for CoreCtx<'a, BT, L>
1079where
1080 BT: BindingsTypes,
1081{
1082 fn with_nud_config<I: Ip, O, F: FnOnce(Option<&NudUserConfig>) -> O>(
1083 &mut self,
1084 _device_id: &Self::DeviceId,
1085 f: F,
1086 ) -> O {
1087 f(None)
1089 }
1090
1091 fn with_nud_config_mut<I: Ip, O, F: FnOnce(Option<&mut NudUserConfig>) -> O>(
1092 &mut self,
1093 _device_id: &Self::DeviceId,
1094 f: F,
1095 ) -> O {
1096 f(None)
1098 }
1099}
1100
1101impl<BC: BindingsContext, L> CounterContext<EthernetDeviceCounters> for CoreCtx<'_, BC, L> {
1102 fn counters(&self) -> &EthernetDeviceCounters {
1103 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.ethernet_counters
1104 }
1105}
1106
1107impl<BC: BindingsContext, L> CounterContext<DeviceSocketCounters> for CoreCtx<'_, BC, L> {
1108 fn counters(&self) -> &DeviceSocketCounters {
1109 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.device_socket_counters
1110 }
1111}
1112
1113impl<BC: BindingsContext, L> CounterContext<PureIpDeviceCounters> for CoreCtx<'_, BC, L> {
1114 fn counters(&self) -> &PureIpDeviceCounters {
1115 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.pure_ip_counters
1116 }
1117}
1118
1119impl<'a, BC: BindingsContext, L> ResourceCounterContext<DeviceId<BC>, DeviceCounters>
1120 for CoreCtx<'a, BC, L>
1121{
1122 fn per_resource_counters<'b>(&'b self, device_id: &'b DeviceId<BC>) -> &'b DeviceCounters {
1123 for_any_device_id!(DeviceId, device_id, id => {
1124 let state = id.device_state(
1125 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
1126 );
1127 &state.counters
1128 })
1129 }
1130}
1131
1132impl<'a, BC: BindingsContext, D: DeviceStateSpec, L>
1133 ResourceCounterContext<BaseDeviceId<D, BC>, DeviceCounters> for CoreCtx<'a, BC, L>
1134{
1135 fn per_resource_counters<'b>(
1136 &'b self,
1137 device_id: &'b BaseDeviceId<D, BC>,
1138 ) -> &'b DeviceCounters {
1139 let state = device_id.device_state(
1140 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
1141 );
1142 &state.counters
1143 }
1144}
1145
1146impl<'a, BC: BindingsContext, L, D: WeakDeviceIdentifier>
1147 ResourceCounterContext<DeviceSocketId<D, BC>, DeviceSocketCounters> for CoreCtx<'a, BC, L>
1148{
1149 fn per_resource_counters<'b>(
1150 &'b self,
1151 socket_id: &'b DeviceSocketId<D, BC>,
1152 ) -> &'b DeviceSocketCounters {
1153 socket_id.counters()
1154 }
1155}
1156
1157impl<'a, BC: BindingsContext, L>
1158 ResourceCounterContext<EthernetDeviceId<BC>, EthernetDeviceCounters> for CoreCtx<'a, BC, L>
1159{
1160 fn per_resource_counters<'b>(
1161 &'b self,
1162 device_id: &'b EthernetDeviceId<BC>,
1163 ) -> &'b EthernetDeviceCounters {
1164 let state = device_id.device_state(
1165 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
1166 );
1167 &state.link.counters
1168 }
1169}
1170
1171impl<'a, BC: BindingsContext, L>
1172 ResourceCounterContext<LoopbackDeviceId<BC>, EthernetDeviceCounters> for CoreCtx<'a, BC, L>
1173{
1174 fn per_resource_counters<'b>(
1175 &'b self,
1176 device_id: &'b LoopbackDeviceId<BC>,
1177 ) -> &'b EthernetDeviceCounters {
1178 let state = device_id.device_state(
1179 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
1180 );
1181 &state.link.counters
1182 }
1183}
1184
1185impl<'a, BC: BindingsContext, L> ResourceCounterContext<PureIpDeviceId<BC>, PureIpDeviceCounters>
1186 for CoreCtx<'a, BC, L>
1187{
1188 fn per_resource_counters<'b>(
1189 &'b self,
1190 device_id: &'b PureIpDeviceId<BC>,
1191 ) -> &'b PureIpDeviceCounters {
1192 let state = device_id.device_state(
1193 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.origin,
1194 );
1195 &state.link.counters
1196 }
1197}
1198
1199impl<'a, BC: BindingsContext, L> CounterContext<BlackholeDeviceCounters> for CoreCtx<'a, BC, L> {
1201 fn counters(&self) -> &BlackholeDeviceCounters {
1202 &BlackholeDeviceCounters
1203 }
1204}
1205
1206impl<'a, BC: BindingsContext, L>
1207 ResourceCounterContext<BlackholeDeviceId<BC>, BlackholeDeviceCounters> for CoreCtx<'a, BC, L>
1208{
1209 fn per_resource_counters<'b>(
1210 &'b self,
1211 _device_id: &'b BlackholeDeviceId<BC>,
1212 ) -> &'b BlackholeDeviceCounters {
1213 &BlackholeDeviceCounters
1214 }
1215}
1216
1217impl<T, BT: BindingsTypes> LockLevelFor<IpLinkDeviceStateInner<T, BT>>
1218 for crate::lock_ordering::DeviceSockets
1219{
1220 type Data = HeldDeviceSockets<BT>;
1221}
1222
1223impl<BT: BindingsTypes, L> CounterContext<DeviceCounters> for CoreCtx<'_, BT, L> {
1224 fn counters(&self) -> &DeviceCounters {
1225 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.counters
1226 }
1227}
1228
1229impl<I: IpDeviceIpExt, BC: BindingsContext, L> IpRoutingDeviceContext<I> for CoreCtx<'_, BC, L>
1230where
1231 Self: IpDeviceStateContext<I, BC, DeviceId = DeviceId<BC>>,
1232{
1233 fn get_routing_metric(&mut self, device_id: &Self::DeviceId) -> RawMetric {
1234 let state = ip_device_state(self, device_id);
1235 *state.unlocked_access::<crate::lock_ordering::UnlockedState>().metric()
1236 }
1237
1238 fn is_ip_device_enabled(&mut self, device_id: &Self::DeviceId) -> bool {
1239 IpDeviceStateContext::<I, _>::with_ip_device_flags(
1240 self,
1241 device_id,
1242 |IpDeviceFlags { ip_enabled }| *ip_enabled,
1243 )
1244 }
1245}
1246
1247impl<BT: BindingsTypes, L> CounterContext<ArpCounters> for CoreCtx<'_, BT, L> {
1248 fn counters(&self) -> &ArpCounters {
1249 &self.unlocked_access::<crate::lock_ordering::UnlockedState>().device.arp_counters
1250 }
1251}