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.
|
* ARP packets (including gratuitous requests and replies) are supported.
|
||||||
* 802.3 and 802.1Q are **not** supported.
|
* 802.3 and 802.1Q are **not** supported.
|
||||||
* Jumbo frames are **not** supported.
|
* Jumbo frames are **not** supported.
|
||||||
* Frame check sequence calculation is **not** supported.
|
|
||||||
|
|
||||||
### IP layer
|
### IP layer
|
||||||
|
|
||||||
|
|
|
@ -216,10 +216,10 @@ impl<'a, 'b: 'a,
|
||||||
_ => return Err(Error::Unrecognized)
|
_ => return Err(Error::Unrecognized)
|
||||||
}
|
}
|
||||||
|
|
||||||
let tx_size = self.device.mtu();
|
|
||||||
match response {
|
match response {
|
||||||
Response::Arp(repr) => {
|
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));
|
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||||
frame.set_src_addr(self.hardware_addr);
|
frame.set_src_addr(self.hardware_addr);
|
||||||
frame.set_dst_addr(match repr {
|
frame.set_dst_addr(match repr {
|
||||||
|
@ -239,14 +239,16 @@ impl<'a, 'b: 'a,
|
||||||
Some(hardware_addr) => hardware_addr
|
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));
|
let mut frame = try!(EthernetFrame::new(&mut tx_buffer));
|
||||||
frame.set_src_addr(self.hardware_addr);
|
frame.set_src_addr(self.hardware_addr);
|
||||||
frame.set_dst_addr(dst_hardware_addr);
|
frame.set_dst_addr(dst_hardware_addr);
|
||||||
frame.set_ethertype(EthernetProtocolType::Ipv4);
|
frame.set_ethertype(EthernetProtocolType::Ipv4);
|
||||||
|
|
||||||
let mut ip_packet = try!(Ipv4Packet::new(frame.payload_mut()));
|
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()));
|
let mut icmp_packet = try!(Icmpv4Packet::new(ip_packet.payload_mut()));
|
||||||
icmp_repr.emit(&mut icmp_packet);
|
icmp_repr.emit(&mut icmp_packet);
|
||||||
|
@ -261,19 +263,6 @@ impl<'a, 'b: 'a,
|
||||||
|
|
||||||
for socket in self.sockets.borrow_mut() {
|
for socket in self.sockets.borrow_mut() {
|
||||||
let result = socket.dispatch(&mut |src_addr, dst_addr, protocol, payload| {
|
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 =
|
let ip_repr =
|
||||||
match (src_addr, dst_addr) {
|
match (src_addr, dst_addr) {
|
||||||
(&InternetAddress::Ipv4(src_addr),
|
(&InternetAddress::Ipv4(src_addr),
|
||||||
|
@ -286,7 +275,24 @@ impl<'a, 'b: 'a,
|
||||||
},
|
},
|
||||||
_ => unreachable!()
|
_ => 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());
|
payload.emit(src_addr, dst_addr, ip_packet.payload_mut());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -38,7 +38,8 @@ impl Device for RawSocket {
|
||||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||||
let mut lower = self.lower.borrow_mut();
|
let mut lower = self.lower.borrow_mut();
|
||||||
let mut buffer = vec![0; self.mtu];
|
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)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ impl Device for TapInterface {
|
||||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||||
let mut lower = self.lower.borrow_mut();
|
let mut lower = self.lower.borrow_mut();
|
||||||
let mut buffer = vec![0; self.mtu];
|
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)
|
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,
|
/// This interface abstracts the various types of packets layered under the IP protocol,
|
||||||
/// and serves as an accessory to [trait Socket](trait.Socket.html).
|
/// and serves as an accessory to [trait Socket](trait.Socket.html).
|
||||||
pub trait PacketRepr {
|
pub trait PacketRepr {
|
||||||
/// Return the length required to serialize this high-level representation.
|
/// Return the length of the buffer required to serialize this high-level representation.
|
||||||
fn len(&self) -> usize;
|
fn buffer_len(&self) -> usize;
|
||||||
|
|
||||||
/// Emit this high-level representation into a sequence of octets.
|
/// Emit this high-level representation into a sequence of octets.
|
||||||
fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]);
|
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> {
|
impl<'a> PacketRepr for UdpRepr<'a> {
|
||||||
fn len(&self) -> usize {
|
fn buffer_len(&self) -> usize {
|
||||||
self.len()
|
self.buffer_len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&self, src_addr: &Address, dst_addr: &Address, payload: &mut [u8]) {
|
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.
|
/// Emit a high-level representation into an Address Resolution Protocol packet.
|
||||||
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
|
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use core::cmp;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
|
|
||||||
use Error;
|
use Error;
|
||||||
|
|
||||||
enum_with_unknown! {
|
enum_with_unknown! {
|
||||||
|
@ -95,6 +97,14 @@ impl<T: AsRef<[u8]>> Frame<T> {
|
||||||
self.buffer
|
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.
|
/// Return the destination address field.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn dst_addr(&self) -> Address {
|
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.
|
/// 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 {
|
match self {
|
||||||
&Repr::EchoRequest { data, .. } |
|
&Repr::EchoRequest { data, .. } |
|
||||||
&Repr::EchoReply { 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> {
|
impl<'a> fmt::Display for Repr<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&Repr::EchoRequest { ident, seq_no, .. } =>
|
&Repr::EchoRequest { ident, seq_no, data } =>
|
||||||
write!(f, "ICMPv4 Echo Request id={} seq={}", ident, seq_no),
|
write!(f, "ICMPv4 Echo Request id={} seq={} len={}",
|
||||||
&Repr::EchoReply { ident, seq_no, .. } =>
|
ident, seq_no, data.len()),
|
||||||
write!(f, "ICMPv4 Echo Reply id={} seq={}", ident, seq_no),
|
&Repr::EchoReply { ident, seq_no, data } =>
|
||||||
|
write!(f, "ICMPv4 Echo Reply id={} seq={} len={}",
|
||||||
|
ident, seq_no, data.len()),
|
||||||
&Repr::__Nonexhaustive => unreachable!()
|
&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.
|
/// 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>,
|
pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>,
|
||||||
payload_len: usize) {
|
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.
|
/// 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()
|
field::CHECKSUM.end + self.payload.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue