Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DHCPv4 client #186

Closed
wants to merge 1 commit into from
Closed

DHCPv4 client #186

wants to merge 1 commit into from

Conversation

astro
Copy link
Contributor

@astro astro commented Apr 5, 2018

Hi

This is an attempt at creating a DHCP client for IPv4. Please give feedback.

Cc: @phil-opp, this PR is uses the work merged in #75.

I've taken a completely different approach compared to #63. UDP sockets don't allow us to send and receive on unspecified/broadcast IPv4 addresses. Therefore IPv4/UDP is parsed/serialized on top of a RawSocket.

There are still two problems with RawSocketBuffer:

  • How do I let the user provide storage? I have tried but failed to accept that as parameters in Client::new(). I've found the proper lifetime relation by now.
  • The RawSocket is getting stuck with Error::Exhausted when contig_window is too small for the DHCP egress packet. Somehow it appears to behave like sent packets don't get dequeued from the tx_buffer. Is that known? What is my code doing wrong regarding RawSocket? See RingBuffer contiguous memory optimization #187

@m-labs-homu
Copy link

☔ The latest upstream changes (presumably 6c36376) made this pull request unmergeable. Please resolve the merge conflicts.

@birkenfeld
Copy link

I'm using this branch (rebased on master, which was mostly painless), and it works fine for me. The only thing I changed was to increase the discover timeout since my DHCP server was too slow in sending replies, and the sequence number of the reply never matched the last request.

@whitequark
Copy link
Contributor

whitequark commented Jul 11, 2018

I'm sorry for the delay in review.

Can you please extract the changes to wire/dhcp.rs first so we can merge that (I don't see anything wrong on the first glance) and then discuss the rest? I think your overall approach is fine but some API consistency changes would be nice.

@robomancer-or
Copy link
Contributor

Would this PR be a suitable starting point for implementing PXE for no_std environments? If so, do we have a estimate of when it may land?

@m-labs-homu
Copy link

☔ The latest upstream changes (presumably 1fbcfb0) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Contributor

@robomancer-or robomancer-or left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Response inline, TLDR, as implemented other uses of DHCP are impossible.


/// Process incoming packets on the contained RawSocket, and send
/// DHCP requests when timeouts are ready.
pub fn poll<DeviceT: for<'d> Device<'d>>(&mut self, iface: &mut Interface<DeviceT>, sockets: &mut SocketSet, now: Instant) -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not returning anything here means that this code can't be used for other types of host configuration (notably: PXE, for network booting). DHCP is designed to do more than just networking parameters. Is there some reason not to return some representation of the response packet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have given it a try to return the DhcpRepr<'a> but that is really cumbersome as it is bound to the lifetime of the packet received by raw_socket.recv() in this function. Check my branch dhcp-return if you would like to work on that.

Proposals are welcome. This is just a as-simple-as-possible implementation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step one I'll get a proof of concept working locally (otherwise my proposal is likely to miss some important details). I'll be back.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any news?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I got put onto a different thing... :-/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you say here that there is genuine commercial interest in smoltcp and embedded Rust?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why wouldn't there be?

@astro astro force-pushed the dhcp branch 3 times, most recently from 5b82cc8 to cd9773d Compare July 31, 2018 20:28
@m-labs-homu
Copy link

☔ The latest upstream changes (presumably 58a5473) made this pull request unmergeable. Please resolve the merge conflicts.

@astro
Copy link
Contributor Author

astro commented Aug 2, 2018

Rebased this one.

@therealprof
Copy link
Contributor

@whitequark Is there anything we (I) can do to move this forward?

@hartytp
Copy link

hartytp commented Dec 29, 2018

@whitequark what's the status of this PR?

@phil-opp
Copy link
Contributor

@astro I just tried this PR and it works great overall! Thanks for your work!

There seems to be an issue with the renew code. It throws a Truncated error for me:

Backtrace
#0  _$LT$smoltcp..wire..ipv4..Packet$LT$T$GT$$GT$::check_len::h704ea3dba9d0fe4d (self=0x2004ddcc) at /home/philipp/.cargo/git/checkouts/smoltcp-ee37870a12a4cf78/d834b20/src/wire/ipv4.rs:283
#1  0x0800ebd4 in _$LT$smoltcp..wire..ipv4..Packet$LT$T$GT$$GT$::new_checked::h81e7878ad05d032a (buffer=0x2004e03c) at /home/philipp/.cargo/git/checkouts/smoltcp-ee37870a12a4cf78/d834b20/src/wire/ipv4.rs:260
#2  0x080111ea in smoltcp::dhcp::clientv4::send_packet::heb7cfda033ccaf55 (iface=0x200008f0, raw_socket=0x200061a8, endpoint=0x2004e354, dhcp_repr=0x2004e368, checksum_caps=0x2004e4b0)
    at /home/philipp/.cargo/git/checkouts/smoltcp-ee37870a12a4cf78/d834b20/src/dhcp/clientv4.rs:412
#3  0x08011b76 in smoltcp::dhcp::clientv4::Client::egress::h61ebcdda26ac545a (self=0x20000980, iface=0x200008f0, raw_socket=0x200061a8, checksum_caps=0x2004e4b0, now=...)
    at /home/philipp/.cargo/git/checkouts/smoltcp-ee37870a12a4cf78/d834b20/src/dhcp/clientv4.rs:319
#4  0x08011452 in smoltcp::dhcp::clientv4::Client::poll::hf5e5a434e6960c04 (self=0x20000980, iface=0x200008f0, sockets=0x200009d0, now=...)
    at /home/philipp/.cargo/git/checkouts/smoltcp-ee37870a12a4cf78/d834b20/src/dhcp/clientv4.rs:128

Seems like the renew packet fails the Ipv4::check_len() test because len < self.total_len().

@astro
Copy link
Contributor Author

astro commented Feb 3, 2019

I wonder if we should temporarily fork smoltcp…

@whitequark
Copy link
Contributor

I'll take a look at this soon.

@astro
Copy link
Contributor Author

astro commented Feb 4, 2019

Rebased and added logging.

There seems to be an issue with the renew code. It throws a Truncated error for me:

Fixed this is in bc498fa and subsequently corrected some fields in the Renew packets.

@whitequark
Copy link
Contributor

As far as I understand there are outstanding issues, so I'm not merging this yet.

@therealprof
Copy link
Contributor

@whitequark It's unclear whether there's a problem or not, it sounds as if @phil-opp might be using it wrong.

Merging "some" version would allow more people to use it and test. I'd never assume a new implementation of a messy protocol like DHCP is going to be perfect from day one but if it is not landed at some point it'll never have a chance to become perfect.

@whitequark
Copy link
Contributor

OK, so at least this'll need to be rebased.

@oli-obk
Copy link

oli-obk commented Apr 12, 2019

I've been experimenting with this and everything but assigning the new IP address seems to work. Even not using the DHCPv4 client I am unable to change the IP address after building an EthernetInterface. We might indeed be using the API wrong, so please don't block this on us if it works for you, I'll figure it out aftewards.

@astro
Copy link
Contributor Author

astro commented Apr 13, 2019

OK, so at least this'll need to be rebased.

Rebased!

Note that #276 added more dst_addr checks to process_ipv4() which were removed in this PR.

@m-labs-homu
Copy link

☔ The latest upstream changes (presumably 5334b93) made this pull request unmergeable. Please resolve the merge conflicts.

@astro
Copy link
Contributor Author

astro commented Apr 20, 2019

Rebased again.

Note that #276 added more dst_addr checks to process_ipv4() which were removed in this PR.

To explain this again: We cannot filter on bound IP addresses as the DHCP responses are targeted at IP addresses that are yet to be bound. Using DHCP would depend on always running in any_ip mode. This is a consequence of moving from RawSocket to UdpSocket, as was desired in code review. Removal of the filtering code also means we would depend on running with a unique mac addr on a switched ethernet link.

I suggest that we revert back to using a RawSocket for the DhcpClient, like it is being done in other implementations on other stacks. That way we can keep dst address filtering. What do you think?

@whitequark
Copy link
Contributor

I suggest that we revert back to using a RawSocket for the DhcpClient, like it is being done in other implementations on other stacks. That way we can keep dst address filtering. What do you think?

I think this is unfortunate but probably a reasonable way forward. Sorry for making you do the work twice.

@astro astro force-pushed the dhcp branch 2 times, most recently from f64eb47 to 2f7efb7 Compare April 28, 2019 13:56
@astro
Copy link
Contributor Author

astro commented Apr 28, 2019

Switched back to raw sockets, rebased, and squashed.

Please review my changes to src/iface/ethernet.rs. I had to prioritize raw sockets so that UDP won't respond with ICMP port-unreachable even when a packet has been handled by a raw socket.

}

fn egress<DeviceT: for<'d> Device<'d>>(&mut self, iface: &mut Interface<DeviceT>, raw_socket: &mut RawSocket, checksum_caps: &ChecksumCapabilities, now: Instant) -> Result<Option<Config>> {
println!("DHCP egress");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you remove these debugging statements? They are hard to use on no_std ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops, thanks for the find!

Nice talk on saturday, btw.

@m-labs-homu
Copy link

☔ The latest upstream changes (presumably e7e267f) made this pull request unmergeable. Please resolve the merge conflicts.

@astro
Copy link
Contributor Author

astro commented May 8, 2019

After #292, #293/#295, rebased once again.

@whitequark
Copy link
Contributor

I think this is basically okay, and there is no reason to have it drag on any longer even if it's imperfect in minor ways. I apologize that this took so long in the first place.

@m-labs-homu r+

@m-labs-homu
Copy link

📌 Commit 14695c1 has been approved by whitequark

@m-labs-homu
Copy link

⌛ Testing commit 14695c1 with merge 657c9aa...

@m-labs-homu
Copy link

☀️ Test successful - status-travis
Approved by: whitequark
Pushing 657c9aa to master...

@astro
Copy link
Contributor Author

astro commented May 13, 2019

Wow, after 13 months!

it's imperfect in minor ways

I agree. It's meant to be a basic implementation to get DHCP capabilities started.

I don't believe in code ownership, so anyone is invited to overhaul this code. Mention @astro in the issues/PRs so that I know where I can help.

@phil-opp phil-opp mentioned this pull request Mar 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants