Sort out buffer lengths.
This commit is contained in:
parent
9c922d0306
commit
f86fac2223
|
@ -21,7 +21,6 @@ The only supported medium is Ethernet.
|
|||
* ARP packets (including gratuitous requests and replies) are supported.
|
||||
* 802.3 and 802.1Q are **not** supported.
|
||||
* Jumbo frames are **not** supported.
|
||||
* Frame check sequence calculation is **not** supported.
|
||||
|
||||
### IP layer
|
||||
|
||||
|
|
|
@ -216,10 +216,10 @@ impl<'a, 'b: 'a,
|
|||
_ => return Err(Error::Unrecognized)
|
||||
}
|
||||
|
||||
let tx_size = self.device.mtu();
|
||||
match response {
|
||||
Response::Arp(repr) => {
|
||||
let mut tx_buffer = try!(self.device.transmit(tx_size));
|
||||
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len());
|
||||
let mut tx_buffer = try!(self.device.transmit(tx_len));
|
||||
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||
frame.set_src_addr(self.hardware_addr);
|
||||
frame.set_dst_addr(match repr {
|
||||
|
@ -239,14 +239,16 @@ impl<'a, 'b: 'a,
|
|||
Some(hardware_addr) => hardware_addr
|
||||
};
|
||||
|
||||
let mut tx_buffer = try!(self.device.transmit(tx_size));
|
||||
let tx_len = EthernetFrame::<&[u8]>::buffer_len(ip_repr.buffer_len() +
|
||||
icmp_repr.buffer_len());
|
||||
let mut tx_buffer = try!(self.device.transmit(tx_len));
|
||||
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||
frame.set_src_addr(self.hardware_addr);
|
||||
frame.set_dst_addr(dst_hardware_addr);
|
||||
frame.set_ethertype(EthernetProtocolType::Ipv4);
|
||||
|
||||
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
|
||||
ip_repr.emit(&mut ip_packet, icmp_repr.len());
|
||||
ip_repr.emit(&mut ip_packet, icmp_repr.buffer_len());
|
||||
|
||||
let mut icmp_packet = try!(Icmpv4Packet::new(ip_packet.payload_mut()));
|
||||
icmp_repr.emit(&mut icmp_packet);
|
||||
|
@ -261,19 +263,6 @@ impl<'a, 'b: 'a,
|
|||
|
||||
for socket in self.sockets.borrow_mut() {
|
||||
let result = socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
|
||||
let dst_hardware_addr =
|
||||
match arp_cache.lookup(*dst_addr) {
|
||||
None => return Err(Error::Unaddressable),
|
||||
Some(hardware_addr) => hardware_addr
|
||||
};
|
||||
|
||||
let mut tx_buffer = try!(device.transmit(tx_size));
|
||||
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||
frame.set_src_addr(src_hardware_addr);
|
||||
frame.set_dst_addr(dst_hardware_addr);
|
||||
frame.set_ethertype(EthernetProtocolType::Ipv4);
|
||||
|
||||
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
|
||||
let ip_repr =
|
||||
match (src_addr, dst_addr) {
|
||||
(&InternetAddress::Ipv4(src_addr),
|
||||
|
@ -286,7 +275,24 @@ impl<'a, 'b: 'a,
|
|||
},
|
||||
_ => unreachable!()
|
||||
};
|
||||
ip_repr.emit(&mut ip_packet, payload.len());
|
||||
|
||||
let dst_hardware_addr =
|
||||
match arp_cache.lookup(*dst_addr) {
|
||||
None => return Err(Error::Unaddressable),
|
||||
Some(hardware_addr) => hardware_addr
|
||||
};
|
||||
|
||||
let tx_len = EthernetFrame::<&[u8]>::buffer_len(ip_repr.buffer_len() +
|
||||
payload.buffer_len());
|
||||
let mut tx_buffer = try!(device.transmit(tx_len));
|
||||
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||
frame.set_src_addr(src_hardware_addr);
|
||||
frame.set_dst_addr(dst_hardware_addr);
|
||||
frame.set_ethertype(EthernetProtocolType::Ipv4);
|
||||
|
||||
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
|
||||
ip_repr.emit(&mut ip_packet, payload.buffer_len());
|
||||
|
||||
payload.emit(src_addr, dst_addr, ip_packet.payload_mut());
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -38,7 +38,8 @@ impl Device for RawSocket {
|
|||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = vec![0; self.mtu];
|
||||
lower.recv(&mut buffer[..]).unwrap();
|
||||
let size = lower.recv(&mut buffer[..]).unwrap();
|
||||
buffer.resize(size, 0);
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ impl Device for TapInterface {
|
|||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = vec![0; self.mtu];
|
||||
lower.recv(&mut buffer[..]).unwrap();
|
||||
let size = lower.recv(&mut buffer[..]).unwrap();
|
||||
buffer.resize(size, 0);
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ pub use self::tcp::Buffer as TcpBuffer;
|
|||
/// This interface abstracts the various types of packets layered under the IP protocol,
|
||||
/// and serves as an accessory to [trait Socket](trait.Socket.html).
|
||||
pub trait PacketRepr {
|
||||
/// Return the length required to serialize this high-level representation.
|
||||
fn len(&self) -> usize;
|
||||
/// Return the length of the buffer required to serialize this high-level representation.
|
||||
fn buffer_len(&self) -> usize;
|
||||
|
||||
/// Emit this high-level representation into a sequence of octets.
|
||||
fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]);
|
||||
|
|
|
@ -201,8 +201,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
|
|||
}
|
||||
|
||||
impl<'a> PacketRepr for UdpRepr<'a> {
|
||||
fn len(&self) -> usize {
|
||||
self.len()
|
||||
fn buffer_len(&self) -> usize {
|
||||
self.buffer_len()
|
||||
}
|
||||
|
||||
fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]) {
|
||||
|
|
|
@ -263,6 +263,14 @@ impl Repr {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return the length of a packet that will be emitted from this high-level representation.
|
||||
pub fn buffer_len(&self) -> usize {
|
||||
match self {
|
||||
&Repr::EthernetIpv4 { .. } => field::TPA(6, 4).end,
|
||||
&Repr::__Nonexhaustive => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit a high-level representation into an Address Resolution Protocol packet.
|
||||
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
|
||||
match self {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::cmp;
|
||||
use core::fmt;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
|
||||
use Error;
|
||||
|
||||
enum_with_unknown! {
|
||||
|
@ -95,6 +97,14 @@ impl<T: AsRef<[u8]>> Frame<T> {
|
|||
self.buffer
|
||||
}
|
||||
|
||||
/// Return the length of a buffer required to hold a packet with the payload
|
||||
/// of a given length.
|
||||
pub fn buffer_len(payload_len: usize) -> usize {
|
||||
// Minimal frame size is 64, but that includes FCS, which the network device
|
||||
// is taking care of for us.
|
||||
cmp::max(field::PAYLOAD.start + payload_len, 60)
|
||||
}
|
||||
|
||||
/// Return the destination address field.
|
||||
#[inline(always)]
|
||||
pub fn dst_addr(&self) -> Address {
|
||||
|
|
|
@ -332,7 +332,7 @@ impl<'a> Repr<'a> {
|
|||
}
|
||||
|
||||
/// Return the length of a packet that will be emitted from this high-level representation.
|
||||
pub fn len(&self) -> usize {
|
||||
pub fn buffer_len(&self) -> usize {
|
||||
match self {
|
||||
&Repr::EchoRequest { data, .. } |
|
||||
&Repr::EchoReply { data, .. } => {
|
||||
|
@ -384,10 +384,12 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
|
|||
impl<'a> fmt::Display for Repr<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Repr::EchoRequest { ident, seq_no, .. } =>
|
||||
write!(f, "ICMPv4 Echo Request id={} seq={}", ident, seq_no),
|
||||
&Repr::EchoReply { ident, seq_no, .. } =>
|
||||
write!(f, "ICMPv4 Echo Reply id={} seq={}", ident, seq_no),
|
||||
&Repr::EchoRequest { ident, seq_no, data } =>
|
||||
write!(f, "ICMPv4 Echo Request id={} seq={} len={}",
|
||||
ident, seq_no, data.len()),
|
||||
&Repr::EchoReply { ident, seq_no, data } =>
|
||||
write!(f, "ICMPv4 Echo Reply id={} seq={} len={}",
|
||||
ident, seq_no, data.len()),
|
||||
&Repr::__Nonexhaustive => unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,6 +382,12 @@ impl Repr {
|
|||
})
|
||||
}
|
||||
|
||||
/// Return the length of a header that will be emitted from this high-level representation.
|
||||
pub fn buffer_len(&self) -> usize {
|
||||
// We never emit any options.
|
||||
field::DST_ADDR.end
|
||||
}
|
||||
|
||||
/// Emit a high-level representation into an Internet Protocol version 4 packet.
|
||||
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>,
|
||||
payload_len: usize) {
|
||||
|
|
|
@ -197,7 +197,7 @@ impl<'a> Repr<'a> {
|
|||
}
|
||||
|
||||
/// Return the length of a packet that will be emitted from this high-level representation.
|
||||
pub fn len(&self) -> usize {
|
||||
pub fn buffer_len(&self) -> usize {
|
||||
field::CHECKSUM.end + self.payload.len()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue