You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a proc macro which defines the #[specialize_ip_addr] macro. Here's an example of its usage:
/// Set the IP address associated with this device.#[specialize_ip_addr]pubfnset_ip_addr<D:EventDispatcher,A:IpAddr>(ctx:&mutContext<D>,device_id:u64,addr:A,subnet:Subnet<A>,){#[ipv4addr]get_device_state(ctx, device_id).ipv4_addr = Some((addr, subnet));#[ipv6addr]get_device_state(ctx, device_id).ipv6_addr = Some((addr, subnet));}
Rustfmt behaves weirdly when it encounters this function - it successfully parses it, but it duplicates the #[ipv6addr] attribute when formatting, resulting in this:
/// Set the IP address associated with this device.#[specialize_ip_addr]pubfnset_ip_addr<D:EventDispatcher,A:IpAddr>(ctx:&mutContext<D>,device_id:u64,addr:A,subnet:Subnet<A>,){#[ipv4addr]get_device_state(ctx, device_id).ipv4_addr = Some((addr, subnet));#[ipv6addr]#[ipv6addr]get_device_state(ctx, device_id).ipv6_addr = Some((addr, subnet));}
This is the only function on which it happens, and I have a number of different functions using this proc macro, so it's fairly dependent on details of the way the function is structured, although I'm not sure how. Here are the functions I have where rustfmt does the right thing:
receive_icmp_packet
/// Receive an ICMP message in an IP packet.
#[specialize_ip_addr]
pub fn receive_icmp_packet<D: EventDispatcher, A: IpAddr, B: BufferMut>(
ctx: &mut Context<D>,
src_ip: A,
dst_ip: A,
mut buffer: B,
) -> bool {
trace!("receive_icmp_packet({}, {})", src_ip, dst_ip);
#[ipv4addr]
{
// TODO(joshlf): Add ICMP extension trait which has an associated packet
// type so that we can pull packet parsing into the common part rather
// than having to do it once for IPv4 and once for IPv6.
let packet =
match buffer.parse_with::<_, Icmpv4Packet<_>>(IcmpParseArgs::new(src_ip, dst_ip)) {
Ok(packet) => packet,
Err(err) => return false,
};
match packet {
Icmpv4Packet::EchoRequest(echo_request) => {
let req = *echo_request.message();
let code = echo_request.code();
// drop packet so we can re-use the underlying buffer
mem::drop(echo_request);
increment_counter!(ctx, "receive_icmp_packet::echo_request");
// we're responding to the sender, so these are flipped
let (src_ip, dst_ip) = (dst_ip, src_ip);
send_ip_packet(ctx, dst_ip, IpProto::Icmp, |src_ip| {
BufferSerializer::new_vec(buffer).encapsulate(
IcmpPacketBuilder::<Ipv4, &[u8], _>::new(src_ip, dst_ip, code, req.reply()),
)
});
true
}
Icmpv4Packet::EchoReply(echo_reply) => {
increment_counter!(ctx, "receive_icmp_packet::echo_reply");
trace!("receive_icmp_packet: Received an EchoReply message");
true
}
_ => log_unimplemented!(
false,
"ip::icmp::receive_icmp_packet: Not implemented for this packet type"
),
}
}
#[ipv6addr]
{
let packet =
match buffer.parse_with::<_, Icmpv6Packet<_>>(IcmpParseArgs::new(src_ip, dst_ip)) {
Ok(packet) => packet,
Err(err) => return false,
};
match packet {
Icmpv6Packet::EchoRequest(echo_request) => {
let req = *echo_request.message();
let code = echo_request.code();
// drop packet so we can re-use the underlying buffer
mem::drop(echo_request);
increment_counter!(ctx, "receive_icmp_packet::echo_request");
// we're responding to the sender, so these are flipped
let (src_ip, dst_ip) = (dst_ip, src_ip);
send_ip_packet(ctx, dst_ip, IpProto::Icmp, |src_ip| {
BufferSerializer::new_vec(buffer).encapsulate(
IcmpPacketBuilder::<Ipv6, &[u8], _>::new(src_ip, dst_ip, code, req.reply()),
)
});
true
}
Icmpv6Packet::EchoReply(echo_reply) => {
increment_counter!(ctx, "receive_icmp_packet::echo_reply");
trace!("receive_icmp_packet: Received an EchoReply message");
true
}
_ => log_unimplemented!(
false,
"ip::icmp::receive_icmp_packet: Not implemented for this packet type"
),
}
}
}
deliver
// Should we deliver this packet locally?
// deliver returns true if:
// - dst_ip is equal to the address set on the device
// - dst_ip is equal to the broadcast address of the subnet set on the device
// - dst_ip is equal to the global broadcast address
#[specialize_ip_addr]
fn deliver<D: EventDispatcher, A: IpAddr>(
ctx: &mut Context<D>,
device: DeviceId,
dst_ip: A,
) -> bool {
// TODO(joshlf):
// - This implements a strict host model (in which we only accept packets
// which are addressed to the device over which they were received). This
// is the easiest to implement for the time being, but we should actually
// put real thought into what our host model should be (NET-1011).
#[ipv4addr]
return crate::device::get_ip_addr::<D, _>(ctx, device)
.map(|(addr, subnet)| dst_ip == addr || dst_ip == subnet.broadcast())
.unwrap_or(dst_ip == Ipv4::BROADCAST_ADDRESS);
#[ipv6addr]
return log_unimplemented!(false, "ip::deliver: Ipv6 not implemeneted");
}
forward
// Should we forward this packet, and if so, to whom?
#[specialize_ip_addr]
fn forward<D: EventDispatcher, A: IpAddr>(
ctx: &mut Context<D>,
dst_ip: A,
) -> Option<Destination<A::Version>> {
let ip_state = &ctx.state().ip;
#[ipv4addr]
let forward = ip_state.v4.forward;
#[ipv6addr]
let forward = ip_state.v6.forward;
if forward {
lookup_route(ip_state, dst_ip)
} else {
None
}
}
lookup_route
// Look up the route to a host.
#[specialize_ip_addr]
fn lookup_route<A: IpAddr>(state: &IpLayerState, dst_ip: A) -> Option<Destination<A::Version>> {
#[ipv4addr]
return state.v4.table.lookup(dst_ip);
#[ipv6addr]
return state.v6.table.lookup(dst_ip);
}
add_device_route
/// Add a route to the forwarding table.
#[specialize_ip_addr]
pub fn add_device_route<D: EventDispatcher, A: IpAddr>(
ctx: &mut Context<D>,
subnet: Subnet<A>,
device: DeviceId,
) {
let state = &mut ctx.state().ip;
#[ipv4addr]
state.v4.table.add_device_route(subnet, device);
#[ipv6addr]
state.v6.table.add_device_route(subnet, device);
}
I have a proc macro which defines the
#[specialize_ip_addr]
macro. Here's an example of its usage:Rustfmt behaves weirdly when it encounters this function - it successfully parses it, but it duplicates the
#[ipv6addr]
attribute when formatting, resulting in this:This is the only function on which it happens, and I have a number of different functions using this proc macro, so it's fairly dependent on details of the way the function is structured, although I'm not sure how. Here are the functions I have where rustfmt does the right thing:
receive_icmp_packet
deliver
forward
lookup_route
add_device_route
get_inner_state
cc @cramertj
The text was updated successfully, but these errors were encountered: