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