Skip to content

Commit 951b59b

Browse files
committed
change(socket/icmp): split ICMPv4/v6 processing
Splitting the accept and process functions into separate functions for IPv4 and IPv6 allows us to avoid the `IpRepr` enum and instead use the `Ipv4Repr` and `Ipv6Repr` structs directly. This reduces the binary size by 1.5 KiB.
1 parent 5ee728a commit 951b59b

File tree

18 files changed

+333
-327
lines changed

18 files changed

+333
-327
lines changed

examples/ping.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,8 @@ fn main() {
187187
remote_addr
188188
);
189189
icmp_repr.emit(
190-
&iface
191-
.get_source_address_ipv6(&address)
192-
.unwrap()
193-
.into_address(),
194-
&remote_addr,
190+
&iface.get_source_address_ipv6(&address).unwrap(),
191+
&address,
195192
&mut icmp_packet,
196193
&device_caps.checksum,
197194
);
@@ -223,11 +220,8 @@ fn main() {
223220
IpAddress::Ipv6(address) => {
224221
let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap();
225222
let icmp_repr = Icmpv6Repr::parse(
226-
&remote_addr,
227-
&iface
228-
.get_source_address_ipv6(&address)
229-
.unwrap()
230-
.into_address(),
223+
&address,
224+
&iface.get_source_address_ipv6(&address).unwrap(),
231225
&icmp_packet,
232226
&device_caps.checksum,
233227
)

src/iface/interface/ipv4.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,13 @@ impl InterfaceInner {
166166
if udp_packet.src_port() == dhcp_socket.server_port
167167
&& udp_packet.dst_port() == dhcp_socket.client_port
168168
{
169-
let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
170169
let udp_repr = check!(UdpRepr::parse(
171170
&udp_packet,
172-
&src_addr,
173-
&dst_addr,
171+
&ipv4_repr.src_addr.into(),
172+
&ipv4_repr.dst_addr.into(),
174173
&self.caps.checksum
175174
));
176-
let udp_payload = udp_packet.payload();
177-
178-
dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_payload);
175+
dhcp_socket.process(self, &ipv4_repr, &udp_repr, udp_packet.payload());
179176
return None;
180177
}
181178
}
@@ -200,7 +197,7 @@ impl InterfaceInner {
200197
}
201198

202199
match ipv4_repr.next_header {
203-
IpProtocol::Icmp => self.process_icmpv4(sockets, ip_repr, ip_payload),
200+
IpProtocol::Icmp => self.process_icmpv4(sockets, ipv4_repr, ip_payload),
204201

205202
#[cfg(feature = "proto-igmp")]
206203
IpProtocol::Igmp => self.process_igmp(ipv4_repr, ip_payload),
@@ -298,7 +295,7 @@ impl InterfaceInner {
298295
pub(super) fn process_icmpv4<'frame>(
299296
&mut self,
300297
_sockets: &mut SocketSet,
301-
ip_repr: IpRepr,
298+
ip_repr: Ipv4Repr,
302299
ip_payload: &'frame [u8],
303300
) -> Option<Packet<'frame>> {
304301
let icmp_packet = check!(Icmpv4Packet::new_checked(ip_payload));
@@ -312,8 +309,8 @@ impl InterfaceInner {
312309
.items_mut()
313310
.filter_map(|i| icmp::Socket::downcast_mut(&mut i.socket))
314311
{
315-
if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
316-
icmp_socket.process(self, &ip_repr, &icmp_repr.into());
312+
if icmp_socket.accepts_v4(self, &ip_repr, &icmp_repr) {
313+
icmp_socket.process_v4(self, &ip_repr, &icmp_repr);
317314
handled_by_icmp_socket = true;
318315
}
319316
}
@@ -331,11 +328,7 @@ impl InterfaceInner {
331328
seq_no,
332329
data,
333330
};
334-
match ip_repr {
335-
IpRepr::Ipv4(ipv4_repr) => self.icmpv4_reply(ipv4_repr, icmp_reply_repr),
336-
#[allow(unreachable_patterns)]
337-
_ => unreachable!(),
338-
}
331+
self.icmpv4_reply(ip_repr, icmp_reply_repr)
339332
}
340333

341334
// Ignore any echo replies.

src/iface/interface/ipv6.rs

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ impl InterfaceInner {
260260
ip_payload: &'frame [u8],
261261
) -> Option<Packet<'frame>> {
262262
match nxt_hdr {
263-
IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr.into(), ip_payload),
263+
IpProtocol::Icmpv6 => self.process_icmpv6(sockets, ipv6_repr, ip_payload),
264264

265265
#[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
266266
IpProtocol::Udp => self.process_udp(
@@ -296,13 +296,13 @@ impl InterfaceInner {
296296
pub(super) fn process_icmpv6<'frame>(
297297
&mut self,
298298
_sockets: &mut SocketSet,
299-
ip_repr: IpRepr,
299+
ip_repr: Ipv6Repr,
300300
ip_payload: &'frame [u8],
301301
) -> Option<Packet<'frame>> {
302302
let icmp_packet = check!(Icmpv6Packet::new_checked(ip_payload));
303303
let icmp_repr = check!(Icmpv6Repr::parse(
304-
&ip_repr.src_addr(),
305-
&ip_repr.dst_addr(),
304+
&ip_repr.src_addr,
305+
&ip_repr.dst_addr,
306306
&icmp_packet,
307307
&self.caps.checksum,
308308
));
@@ -317,8 +317,8 @@ impl InterfaceInner {
317317
.items_mut()
318318
.filter_map(|i| IcmpSocket::downcast_mut(&mut i.socket))
319319
{
320-
if icmp_socket.accepts(self, &ip_repr, &icmp_repr.into()) {
321-
icmp_socket.process(self, &ip_repr, &icmp_repr.into());
320+
if icmp_socket.accepts_v6(self, &ip_repr, &icmp_repr) {
321+
icmp_socket.process_v6(self, &ip_repr, &icmp_repr);
322322
handled_by_icmp_socket = true;
323323
}
324324
}
@@ -330,35 +330,27 @@ impl InterfaceInner {
330330
ident,
331331
seq_no,
332332
data,
333-
} => match ip_repr {
334-
IpRepr::Ipv6(ipv6_repr) => {
335-
let icmp_reply_repr = Icmpv6Repr::EchoReply {
336-
ident,
337-
seq_no,
338-
data,
339-
};
340-
self.icmpv6_reply(ipv6_repr, icmp_reply_repr)
341-
}
342-
#[allow(unreachable_patterns)]
343-
_ => unreachable!(),
344-
},
333+
} => {
334+
let icmp_reply_repr = Icmpv6Repr::EchoReply {
335+
ident,
336+
seq_no,
337+
data,
338+
};
339+
self.icmpv6_reply(ip_repr, icmp_reply_repr)
340+
}
345341

346342
// Ignore any echo replies.
347343
Icmpv6Repr::EchoReply { .. } => None,
348344

349345
// Forward any NDISC packets to the ndisc packet handler
350346
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
351-
Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr {
352-
IpRepr::Ipv6(ipv6_repr) => match self.caps.medium {
353-
#[cfg(feature = "medium-ethernet")]
354-
Medium::Ethernet => self.process_ndisc(ipv6_repr, repr),
355-
#[cfg(feature = "medium-ieee802154")]
356-
Medium::Ieee802154 => self.process_ndisc(ipv6_repr, repr),
357-
#[cfg(feature = "medium-ip")]
358-
Medium::Ip => None,
359-
},
360-
#[allow(unreachable_patterns)]
361-
_ => unreachable!(),
347+
Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit == 0xff => match self.caps.medium {
348+
#[cfg(feature = "medium-ethernet")]
349+
Medium::Ethernet => self.process_ndisc(ip_repr, repr),
350+
#[cfg(feature = "medium-ieee802154")]
351+
Medium::Ieee802154 => self.process_ndisc(ip_repr, repr),
352+
#[cfg(feature = "medium-ip")]
353+
Medium::Ip => None,
362354
},
363355

364356
// Don't report an error if a packet with unknown type

src/iface/interface/sixlowpan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ impl InterfaceInner {
508508
match &mut packet.payload {
509509
IpPayload::Icmpv6(icmp_repr) => {
510510
icmp_repr.emit(
511-
&packet.header.src_addr.into(),
512-
&packet.header.dst_addr.into(),
511+
&packet.header.src_addr,
512+
&packet.header.dst_addr,
513513
&mut Icmpv6Packet::new_unchecked(&mut buffer[..icmp_repr.buffer_len()]),
514514
checksum_caps,
515515
);

src/iface/interface/tests/ipv4.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,6 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
565565
payload_len: 24,
566566
hop_limit: 64,
567567
};
568-
let ip_repr = IpRepr::Ipv4(ipv4_repr);
569568

570569
// Open a socket and ensure the packet is handled due to the listening
571570
// socket.
@@ -583,7 +582,9 @@ fn test_icmpv4_socket(#[case] medium: Medium) {
583582
..ipv4_repr
584583
};
585584
assert_eq!(
586-
iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
585+
iface
586+
.inner
587+
.process_icmpv4(&mut sockets, ipv4_repr, icmp_data),
587588
Some(Packet::new_ipv4(ipv4_reply, IpPayload::Icmpv4(echo_reply)))
588589
);
589590

src/iface/interface/tests/ipv6.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ fn parse_ipv6(data: &[u8]) -> crate::wire::Result<Packet<'_>> {
1616
IpProtocol::IpSecAh => todo!(),
1717
IpProtocol::Icmpv6 => {
1818
let icmp = Icmpv6Repr::parse(
19-
&ipv6.src_addr.into(),
20-
&ipv6.dst_addr.into(),
19+
&ipv6.src_addr,
20+
&ipv6.dst_addr,
2121
&Icmpv6Packet::new_checked(ipv6_header.payload())?,
2222
&Default::default(),
2323
)?;
@@ -707,8 +707,8 @@ fn test_handle_valid_ndisc_request(#[case] medium: Medium) {
707707
frame.set_ethertype(EthernetProtocol::Ipv6);
708708
ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
709709
solicit.emit(
710-
&remote_ip_addr.into(),
711-
&local_ip_addr.solicited_node().into(),
710+
&remote_ip_addr,
711+
&local_ip_addr.solicited_node(),
712712
&mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
713713
&ChecksumCapabilities::default(),
714714
);

src/iface/neighbor.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ impl Cache {
163163
#[cfg(test)]
164164
mod test {
165165
use super::*;
166-
use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
166+
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
167+
use crate::wire::ipv4::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
168+
#[cfg(feature = "proto-ipv6")]
169+
use crate::wire::ipv6::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
167170

168171
use crate::wire::EthernetAddress;
169172

@@ -177,45 +180,45 @@ mod test {
177180
let mut cache = Cache::new();
178181

179182
assert!(!cache
180-
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
183+
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
181184
.found());
182185
assert!(!cache
183-
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
186+
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
184187
.found());
185188

186-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
189+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
187190
assert_eq!(
188-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
191+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
189192
Answer::Found(HADDR_A)
190193
);
191194
assert!(!cache
192-
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
195+
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
193196
.found());
194197
assert!(!cache
195198
.lookup(
196-
&MOCK_IP_ADDR_1,
199+
&MOCK_IP_ADDR_1.into(),
197200
Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
198201
)
199202
.found(),);
200203

201-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
204+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
202205
assert!(!cache
203-
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
206+
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
204207
.found());
205208
}
206209

207210
#[test]
208211
fn test_expire() {
209212
let mut cache = Cache::new();
210213

211-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
214+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
212215
assert_eq!(
213-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
216+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
214217
Answer::Found(HADDR_A)
215218
);
216219
assert!(!cache
217220
.lookup(
218-
&MOCK_IP_ADDR_1,
221+
&MOCK_IP_ADDR_1.into(),
219222
Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
220223
)
221224
.found(),);
@@ -225,14 +228,14 @@ mod test {
225228
fn test_replace() {
226229
let mut cache = Cache::new();
227230

228-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
231+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
229232
assert_eq!(
230-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
233+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
231234
Answer::Found(HADDR_A)
232235
);
233-
cache.fill(MOCK_IP_ADDR_1, HADDR_B, Instant::from_millis(0));
236+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_B, Instant::from_millis(0));
234237
assert_eq!(
235-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
238+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
236239
Answer::Found(HADDR_B)
237240
);
238241
}
@@ -241,23 +244,23 @@ mod test {
241244
fn test_evict() {
242245
let mut cache = Cache::new();
243246

244-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(100));
245-
cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50));
246-
cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(200));
247+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(100));
248+
cache.fill(MOCK_IP_ADDR_2.into(), HADDR_B, Instant::from_millis(50));
249+
cache.fill(MOCK_IP_ADDR_3.into(), HADDR_C, Instant::from_millis(200));
247250
assert_eq!(
248-
cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)),
251+
cache.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000)),
249252
Answer::Found(HADDR_B)
250253
);
251254
assert!(!cache
252-
.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000))
255+
.lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000))
253256
.found());
254257

255-
cache.fill(MOCK_IP_ADDR_4, HADDR_D, Instant::from_millis(300));
258+
cache.fill(MOCK_IP_ADDR_4.into(), HADDR_D, Instant::from_millis(300));
256259
assert!(!cache
257-
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000))
260+
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(1000))
258261
.found());
259262
assert_eq!(
260-
cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)),
263+
cache.lookup(&MOCK_IP_ADDR_4.into(), Instant::from_millis(1000)),
261264
Answer::Found(HADDR_D)
262265
);
263266
}
@@ -267,17 +270,17 @@ mod test {
267270
let mut cache = Cache::new();
268271

269272
assert_eq!(
270-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
273+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
271274
Answer::NotFound
272275
);
273276

274277
cache.limit_rate(Instant::from_millis(0));
275278
assert_eq!(
276-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)),
279+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(100)),
277280
Answer::RateLimited
278281
);
279282
assert_eq!(
280-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)),
283+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(2000)),
281284
Answer::NotFound
282285
);
283286
}
@@ -286,21 +289,21 @@ mod test {
286289
fn test_flush() {
287290
let mut cache = Cache::new();
288291

289-
cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
292+
cache.fill(MOCK_IP_ADDR_1.into(), HADDR_A, Instant::from_millis(0));
290293
assert_eq!(
291-
cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
294+
cache.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0)),
292295
Answer::Found(HADDR_A)
293296
);
294297
assert!(!cache
295-
.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
298+
.lookup(&MOCK_IP_ADDR_2.into(), Instant::from_millis(0))
296299
.found());
297300

298301
cache.flush();
299302
assert!(!cache
300-
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
303+
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
301304
.found());
302305
assert!(!cache
303-
.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
306+
.lookup(&MOCK_IP_ADDR_1.into(), Instant::from_millis(0))
304307
.found());
305308
}
306309
}

0 commit comments

Comments
 (0)