Skip to content

Commit 2420db1

Browse files
add datalink trait for arp
1 parent 36ff6ae commit 2420db1

File tree

4 files changed

+66
-66
lines changed

4 files changed

+66
-66
lines changed

core/src/packets/arp.rs

Lines changed: 27 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
2121
use crate::ensure;
2222
use crate::net::MacAddr;
23-
use crate::packets::ethernet::{EtherTypes, Ethernet};
23+
use crate::packets::ethernet::{EtherType, EtherTypes, Ethernet};
2424
use crate::packets::types::u16be;
25-
use crate::packets::{Internal, Packet, SizeOf};
25+
use crate::packets::{Datalink, Internal, Packet, SizeOf};
2626
use anyhow::{anyhow, Result};
2727
use std::fmt;
2828
use std::net::Ipv4Addr;
@@ -84,13 +84,13 @@ use std::ptr::NonNull;
8484
/// defined by *P Length*.
8585
///
8686
/// [IETF RFC 826]: https://tools.ietf.org/html/rfc826
87-
pub struct Arp<H: HardwareAddr, P: ProtocolAddr> {
88-
envelope: Ethernet,
87+
pub struct Arp<E: Datalink, H: HardwareAddr, P: ProtocolAddr> {
88+
envelope: E,
8989
header: NonNull<ArpHeader<H, P>>,
9090
offset: usize,
9191
}
9292

93-
impl<H: HardwareAddr, P: ProtocolAddr> Arp<H, P> {
93+
impl<E: Datalink, H: HardwareAddr, P: ProtocolAddr> Arp<E, H, P> {
9494
#[inline]
9595
fn header(&self) -> &ArpHeader<H, P> {
9696
unsafe { self.header.as_ref() }
@@ -114,14 +114,20 @@ impl<H: HardwareAddr, P: ProtocolAddr> Arp<H, P> {
114114
}
115115

116116
/// Returns the protocol type.
117+
///
118+
/// [IANA] assigned Protocol type numbers share the same space as
119+
/// [`EtherTypes`].
120+
///
121+
/// [IANA]: https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-3
122+
/// [`EtherTypes`]: crate::packets::ethernet::EtherTypes
117123
#[inline]
118-
pub fn protocol_type(&self) -> ProtocolType {
119-
ProtocolType::new(self.header().protocol_type.into())
124+
pub fn protocol_type(&self) -> EtherType {
125+
EtherType::new(self.header().protocol_type.into())
120126
}
121127

122128
/// Sets the protocol type.
123129
#[inline]
124-
fn set_protocol_type(&mut self, protocol_type: ProtocolType) {
130+
fn set_protocol_type(&mut self, protocol_type: EtherType) {
125131
self.header_mut().protocol_type = protocol_type.0.into()
126132
}
127133

@@ -210,7 +216,7 @@ impl<H: HardwareAddr, P: ProtocolAddr> Arp<H, P> {
210216
}
211217
}
212218

213-
impl<H: HardwareAddr, P: ProtocolAddr> fmt::Debug for Arp<H, P> {
219+
impl<E: Datalink, H: HardwareAddr, P: ProtocolAddr> fmt::Debug for Arp<E, H, P> {
214220
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215221
f.debug_struct("arp")
216222
.field("hardware_type", &format!("{}", self.hardware_type()))
@@ -241,9 +247,8 @@ impl<H: HardwareAddr, P: ProtocolAddr> fmt::Debug for Arp<H, P> {
241247
}
242248
}
243249

244-
impl<H: HardwareAddr, P: ProtocolAddr> Packet for Arp<H, P> {
245-
/// The preceding type for ARP must be `Ethernet`.
246-
type Envelope = Ethernet;
250+
impl<E: Datalink, H: HardwareAddr, P: ProtocolAddr> Packet for Arp<E, H, P> {
251+
type Envelope = E;
247252

248253
#[inline]
249254
fn envelope(&self) -> &Self::Envelope {
@@ -274,7 +279,7 @@ impl<H: HardwareAddr, P: ProtocolAddr> Packet for Arp<H, P> {
274279
}
275280
}
276281

277-
/// Parses the Ethernet payload as an ARP packet.
282+
/// Parses the payload as an ARP packet.
278283
///
279284
/// # Errors
280285
///
@@ -292,7 +297,7 @@ impl<H: HardwareAddr, P: ProtocolAddr> Packet for Arp<H, P> {
292297
#[inline]
293298
fn try_parse(envelope: Self::Envelope, _internal: Internal) -> Result<Self> {
294299
ensure!(
295-
envelope.ether_type() == EtherTypes::Arp,
300+
envelope.protocol_type() == EtherTypes::Arp,
296301
anyhow!("not an ARP packet.")
297302
);
298303

@@ -362,7 +367,7 @@ impl<H: HardwareAddr, P: ProtocolAddr> Packet for Arp<H, P> {
362367
mbuf.extend(offset, ArpHeader::<H, P>::size_of())?;
363368
let header = mbuf.write_data(offset, &ArpHeader::<H, P>::default())?;
364369

365-
envelope.set_ether_type(EtherTypes::Arp);
370+
envelope.set_protocol_type(EtherTypes::Arp);
366371

367372
let mut packet = Arp {
368373
envelope,
@@ -427,49 +432,6 @@ impl fmt::Display for HardwareType {
427432
}
428433
}
429434

430-
/// [IANA] assigned protocol type.
431-
///
432-
/// See [`ProtocolTypes`] for which are current supported.
433-
///
434-
/// [IANA]: https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml#arp-parameters-3
435-
/// [`ProtocolTypes`]: crate::packets::arp::ProtocolTypes
436-
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
437-
#[repr(C, packed)]
438-
pub struct ProtocolType(u16);
439-
440-
impl ProtocolType {
441-
/// Creates a new protocol type.
442-
pub fn new(value: u16) -> Self {
443-
ProtocolType(value)
444-
}
445-
}
446-
447-
/// Supported protocol types.
448-
#[allow(non_snake_case)]
449-
#[allow(non_upper_case_globals)]
450-
pub mod ProtocolTypes {
451-
use super::ProtocolType;
452-
453-
/// Internet protocol version 4.
454-
pub const Ipv4: ProtocolType = ProtocolType(0x0800);
455-
}
456-
457-
impl fmt::Display for ProtocolType {
458-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459-
write!(
460-
f,
461-
"{}",
462-
match *self {
463-
ProtocolTypes::Ipv4 => "IPv4".to_string(),
464-
_ => {
465-
let t = self.0;
466-
format!("0x{:04x}", t)
467-
}
468-
}
469-
)
470-
}
471-
}
472-
473435
/// [IANA] assigned operation code.
474436
///
475437
/// See [`OperationCodes`] for which are current supported.
@@ -547,7 +509,7 @@ impl HardwareAddr for MacAddr {
547509
/// A trait implemented by ARP protocol address types.
548510
pub trait ProtocolAddr: SizeOf + Copy + fmt::Display {
549511
/// Returns the associated protocol type of the given address.
550-
fn addr_type() -> ProtocolType;
512+
fn addr_type() -> EtherType;
551513

552514
/// Returns the default value.
553515
///
@@ -557,17 +519,17 @@ pub trait ProtocolAddr: SizeOf + Copy + fmt::Display {
557519
}
558520

559521
impl ProtocolAddr for Ipv4Addr {
560-
fn addr_type() -> ProtocolType {
561-
ProtocolTypes::Ipv4
522+
fn addr_type() -> EtherType {
523+
EtherTypes::Ipv4
562524
}
563525

564526
fn default() -> Self {
565527
Ipv4Addr::UNSPECIFIED
566528
}
567529
}
568530

569-
/// A type alias for an IPv4 ARP packet.
570-
pub type Arp4 = Arp<MacAddr, Ipv4Addr>;
531+
/// A type alias for an Ethernet IPv4 ARP packet.
532+
pub type Arp4 = Arp<Ethernet, MacAddr, Ipv4Addr>;
571533

572534
/// ARP header.
573535
#[allow(missing_debug_implementations)]
@@ -635,7 +597,7 @@ mod tests {
635597
let arp4 = ethernet.parse::<Arp4>().unwrap();
636598

637599
assert_eq!(HardwareTypes::Ethernet, arp4.hardware_type());
638-
assert_eq!(ProtocolTypes::Ipv4, arp4.protocol_type());
600+
assert_eq!(EtherTypes::Ipv4, arp4.protocol_type());
639601
assert_eq!(6, arp4.hardware_addr_len());
640602
assert_eq!(4, arp4.protocol_addr_len());
641603
assert_eq!(OperationCodes::Request, arp4.operation_code());
@@ -655,7 +617,7 @@ mod tests {
655617

656618
// make sure types are set properly
657619
assert_eq!(HardwareTypes::Ethernet, arp4.hardware_type());
658-
assert_eq!(ProtocolTypes::Ipv4, arp4.protocol_type());
620+
assert_eq!(EtherTypes::Ipv4, arp4.protocol_type());
659621
assert_eq!(6, arp4.hardware_addr_len());
660622
assert_eq!(4, arp4.protocol_addr_len());
661623

core/src/packets/ethernet.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use crate::ensure;
2222
use crate::net::MacAddr;
2323
use crate::packets::types::u16be;
24-
use crate::packets::{Internal, Mbuf, Packet, SizeOf};
24+
use crate::packets::{Datalink, Internal, Mbuf, Packet, SizeOf};
2525
use anyhow::{anyhow, Result};
2626
use std::fmt;
2727
use std::ptr::NonNull;
@@ -331,6 +331,18 @@ impl Packet for Ethernet {
331331
}
332332
}
333333

334+
impl Datalink for Ethernet {
335+
#[inline]
336+
fn protocol_type(&self) -> EtherType {
337+
self.ether_type()
338+
}
339+
340+
#[inline]
341+
fn set_protocol_type(&mut self, ether_type: EtherType) {
342+
self.set_ether_type(ether_type)
343+
}
344+
}
345+
334346
/// The protocol identifier of the Ethernet frame payload.
335347
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
336348
#[repr(C, packed)]

core/src/packets/ip/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,9 @@ mod tests {
273273
assert_eq!("TCP", ProtocolNumbers::Tcp.to_string());
274274
assert_eq!("UDP", ProtocolNumbers::Udp.to_string());
275275
assert_eq!("IPv6 Route", ProtocolNumbers::Ipv6Route.to_string());
276+
assert_eq!("IPv6 Frag", ProtocolNumbers::Ipv6Frag.to_string());
276277
assert_eq!("ICMPv6", ProtocolNumbers::Icmpv6.to_string());
278+
assert_eq!("ICMPv4", ProtocolNumbers::Icmpv4.to_string());
277279
assert_eq!("0x00", ProtocolNumber::new(0).to_string());
278280
}
279281
}

core/src/packets/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub use self::mbuf::*;
3333
pub use self::size_of::*;
3434
pub use capsule_macros::SizeOf;
3535

36+
use crate::packets::ethernet::EtherType;
3637
use anyhow::{Context, Result};
3738
use std::fmt;
3839
use std::marker::PhantomData;
@@ -301,6 +302,29 @@ pub trait Packet {
301302
}
302303
}
303304

305+
/// A trait datalink layer protocol can implement.
306+
///
307+
/// A datalink protocol must implement this trait if it needs to encapsulate
308+
/// network protocols like IP or ARP. Otherwise, it should not implement this
309+
/// trait.
310+
pub trait Datalink: Packet {
311+
/// Gets the encapsulated packet type.
312+
///
313+
/// Returns the ethernet protocol type codes because ethernet is the most
314+
/// ubiquitous datalink protocol. Other datalink like InfiniBand adopted
315+
/// the ethernet type codes. When implementing a datalink with its own
316+
/// type codes, a translation from ether type is needed.
317+
fn protocol_type(&self) -> EtherType;
318+
319+
/// Sets the protocol type of the encapsulated packet.
320+
///
321+
/// Uses the ethernet protocol type codes because ethernet is the most
322+
/// ubiquitous datalink protocol. Other datalink like InfiniBand adopted
323+
/// the ethernet type codes. When implementing a datalink with its own
324+
/// type codes, a translation from ether type is needed.
325+
fn set_protocol_type(&mut self, ether_type: EtherType);
326+
}
327+
304328
/// Immutable smart pointer to a struct.
305329
///
306330
/// A smart pointer that prevents the struct from being modified. The main

0 commit comments

Comments
 (0)