Skip to content

Commit eb82e3c

Browse files
committed
xxx
1 parent 05542af commit eb82e3c

File tree

5 files changed

+331
-59
lines changed

5 files changed

+331
-59
lines changed

Diff for: Cargo.lock

+49-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: uefi-test-runner/Cargo.toml

+10-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ edition = "2021"
88
[dependencies]
99
uefi-raw = { path = "../uefi-raw" }
1010
uefi = { path = "../uefi", features = ["alloc", "global_allocator", "panic_handler", "logger", "qemu"] }
11-
1211
log.workspace = true
13-
1412
qemu-exit = "3.0.0"
1513

14+
[dependencies.smoltcp]
15+
version = "0.12.0"
16+
default-features = false
17+
features = [
18+
"proto-ipv4",
19+
"socket-udp",
20+
# "medium-ip",
21+
"medium-ethernet"
22+
]
23+
1624
[features]
1725
# Enable the debug support protocol test.
1826
debug_support = []

Diff for: uefi-test-runner/src/proto/network/mod.rs

+154-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,161 @@
33
pub fn test() {
44
info!("Testing Network protocols");
55

6-
pxe::test();
7-
snp::test();
6+
// Test idempotence of network stuff
7+
for _ in 0..2 {
8+
#[cfg(feature = "pxe")]
9+
//pxe::test();
10+
snp::test();
11+
}
812
}
913

14+
#[cfg(feature = "pxe")]
1015
mod pxe;
1116
mod snp;
17+
18+
/// This module provides helpers to work directly on UDP, IPv4, and Ethernet
19+
/// packets.
20+
mod wire_helper {
21+
use alloc::vec::Vec;
22+
use smoltcp::wire;
23+
use smoltcp::wire::{EthernetAddress, EthernetFrame, EthernetProtocol, EthernetRepr, IpProtocol, Ipv4Packet, UdpPacket, ETHERNET_HEADER_LEN, IPV4_HEADER_LEN, UDP_HEADER_LEN};
24+
25+
/// Creates a minimal yet valid UDP packet in the provided buffer together
26+
/// with the payload.
27+
fn create_udp_packet<'a>(
28+
buffer: &'a mut [u8],
29+
src_addr: wire::Ipv4Address,
30+
dst_addr: wire::Ipv4Address,
31+
src_port: u16,
32+
dst_port: u16,
33+
payload: &[u8],
34+
) -> UdpPacket<&'a mut [u8]> {
35+
let mut packet = UdpPacket::new_unchecked(buffer);
36+
packet.set_src_port(src_port);
37+
packet.set_dst_port(dst_port);
38+
packet.set_len((UDP_HEADER_LEN + payload.len()) as u16);
39+
packet.payload_mut().copy_from_slice(payload);
40+
41+
packet.fill_checksum(&src_addr.into(), &dst_addr.into());
42+
packet.verify_checksum(&src_addr.into(), &dst_addr.into());
43+
packet.check_len().unwrap();
44+
packet
45+
}
46+
47+
/// Creates a minimal yet valid IPv4 packet in the provided buffer together
48+
/// with the payload. The IPv4 packet that contains all data in a single
49+
/// packet (not fragmented).
50+
fn create_ipv4_packet<'a>(
51+
buffer: &'a mut [u8],
52+
src_addr: smoltcp::wire::Ipv4Address,
53+
dst_addr: smoltcp::wire::Ipv4Address,
54+
payload: &[u8],
55+
) -> Ipv4Packet<&'a mut [u8]> {
56+
let mut packet = Ipv4Packet::new_unchecked(buffer);
57+
packet.set_version(4);
58+
packet.set_header_len(IPV4_HEADER_LEN as u8);
59+
packet.set_dscp(0 /* QOS */);
60+
packet.set_total_len((IPV4_HEADER_LEN + payload.len()) as u16);
61+
packet.set_ident(42);
62+
packet.set_dont_frag(true);
63+
packet.set_frag_offset(0);
64+
packet.set_hop_limit(42 /*TTL */);
65+
packet.set_next_header(IpProtocol::Udp);
66+
packet.set_src_addr(src_addr);
67+
packet.set_dst_addr(dst_addr);
68+
packet.payload_mut().copy_from_slice(payload);
69+
70+
packet.fill_checksum();
71+
packet.verify_checksum();
72+
packet.check_len().unwrap();
73+
packet
74+
}
75+
76+
/// Creates a minimal yet valid Ethernet frame (packet) in the provided
77+
/// buffer together with the payload.
78+
fn create_ethernet_frame<'a>(
79+
buffer: &'a mut [u8],
80+
src_addr: EthernetAddress,
81+
dst_addr: EthernetAddress,
82+
payload: &[u8],
83+
) -> EthernetFrame<&'a mut [u8]> {
84+
let mut packet = EthernetFrame::new_unchecked(buffer);
85+
packet.set_src_addr(src_addr);
86+
packet.set_dst_addr(dst_addr);
87+
packet.set_ethertype(EthernetProtocol::Ipv4);
88+
packet.payload_mut().copy_from_slice(payload);
89+
90+
packet.check_len().unwrap();
91+
packet
92+
}
93+
94+
/// Embeds an arbitrary payload into a minimal yet valid
95+
/// `EthernetFrame(IPv4Packet(UdpPacket(Payload)))` packet structure.
96+
///
97+
/// The encoded structure is returned as [`Vec`].
98+
pub fn create_udp_ipv4_ethernet_packet(
99+
src_addr_ipv4: wire::Ipv4Address,
100+
dst_addr_ipv4: wire::Ipv4Address,
101+
src_addr_mac: EthernetAddress,
102+
dst_addr_mac: EthernetAddress,
103+
payload: &[u8],
104+
) -> Vec<u8> {
105+
let total_len = ETHERNET_HEADER_LEN + IPV4_HEADER_LEN + UDP_HEADER_LEN + payload.len();
106+
assert!(total_len <= 1500 /* default Max Ethernet frame size */);
107+
108+
// udp packet with embedded payload
109+
let udp_packet = {
110+
let len = UDP_HEADER_LEN + payload.len();
111+
let mut buf = vec![0_u8; len];
112+
create_udp_packet(
113+
&mut buf,
114+
src_addr_ipv4.clone(),
115+
dst_addr_ipv4.clone(),
116+
0x1337,
117+
0x1337,
118+
&payload,
119+
);
120+
buf
121+
};
122+
123+
// ipv4 packet with embedded udp packet
124+
let ipv4_packet = {
125+
let len = IPV4_HEADER_LEN + udp_packet.len();
126+
let mut buf = vec![0_u8; len];
127+
create_ipv4_packet(
128+
&mut buf,
129+
src_addr_ipv4.clone(),
130+
dst_addr_ipv4.clone(),
131+
&udp_packet,
132+
);
133+
buf
134+
};
135+
136+
// ethernet frame with embedded ipv4 packet
137+
let ethernet_frame = {
138+
let len = ETHERNET_HEADER_LEN + ipv4_packet.len();
139+
let mut buf = vec![0_u8; len];
140+
log::debug!("ethernet frame before: {:#?}", &buf);
141+
create_ethernet_frame(&mut buf, src_addr_mac.clone(), dst_addr_mac, &ipv4_packet);
142+
log::debug!("ethernet frame after: {:#?}", &buf);
143+
buf
144+
};
145+
assert_eq!(ethernet_frame.len(), total_len);
146+
let repr = EthernetRepr::parse(&EthernetFrame::new_unchecked(&ethernet_frame)).unwrap();
147+
log::debug!("ethernet repr: {:#?}", repr);
148+
149+
ethernet_frame
150+
}
151+
152+
/// Returns the actual payload from a UDP packet.
153+
pub fn get_payload_from_udp_ipv4_frame(frame: &[u8]) -> &[u8] {
154+
log::debug!("frame lan = {}", frame.len());
155+
let frame = EthernetFrame::new_checked(frame).unwrap();
156+
log::debug!("payload = {:?}", &frame.payload()[0..30]);
157+
let ipv4_packet = Ipv4Packet::new_unchecked(&frame.payload()[1..]);
158+
log::debug!("ipv4: {}", ipv4_packet);
159+
log::debug!("total_len={}", ipv4_packet.total_len());
160+
let udp_packet = UdpPacket::new_checked(ipv4_packet.payload()).unwrap();
161+
udp_packet.payload()
162+
}
163+
}

0 commit comments

Comments
 (0)