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

http server over ethernet? #529

Closed
indexds opened this issue Dec 18, 2024 · 23 comments
Closed

http server over ethernet? #529

indexds opened this issue Dec 18, 2024 · 23 comments

Comments

@indexds
Copy link
Contributor

indexds commented Dec 18, 2024

Hello,

I'm trying to understand what I need to be able to have my ethernet netif speak to the http server running on the esp32.

This code starts an http server,

    let http_config = HttpServerConfig {
        http_port: 80,
        ..Default::default()
    };

    let mut http_server = EspHttpServer::new(&http_config)?;

    let nvs_root = Arc::clone(&nvs);
    http_server.fn_handler("/", Method::Get, move |mut request| {
        let nvs = nvs_root.lock().unwrap();

        let nvs_wg_conf = NvsWireguard::new(&nvs)?;

        let html = index::index_html(&nvs_wg_conf)?;

        let connection = request.connection();

        connection.initiate_response(200, Some("OK"), &[("Content-Type", "text/html")])?;

        connection.write(html.as_bytes())?;

        Ok::<(), Error>(())
    })?;

    // exposes charizhard.local
    let mut mdns = EspMdns::take()?;
    mdns.set_hostname("charizhard")?;
    mdns.add_service(
        Some("charizhard"), // instance_name
        "_http",            // service_type
        "_tcp",             // proto
        80,                 // port
        &[],                // txt
    )?;

And this other part boots an eth netif.

    let eth_driver = EthDriver::new_rmii(
        mac,
        pins.gpio25, // RMII RDX0
        pins.gpio26, // RMII RDX1
        pins.gpio27, // RMII CRS DV
        pins.gpio23, // WT32-ETH01 SMI MDC
        pins.gpio22, // EMII TXD1
        pins.gpio21, // RMII TX EN
        pins.gpio19, // RMII TXD0
        pins.gpio18, // WT32-ETH01 SMI MDIO
        RmiiClockConfig::<gpio::Gpio0, gpio::Gpio16, gpio::Gpio17>::Input(
            pins.gpio0, // WT32-ETH01 external clock
        ),
        Some(pins.gpio16), // WT32-ETH01 PHY reset
        RmiiEthChipset::LAN87XX,
        Some(1), // WT32-ETH01 PHY address
        sysloop,
    )?;

    let mut eth_netif = EspEth::wrap_all(
        eth_driver,
        EspNetif::new_with_conf(&NetifConfiguration {
            ip_configuration: Some(IpConfiguration::Client(IpClientConfiguration::Fixed(IpClientSettings {
                ip: Ipv4Addr::new(192, 168, 1, 100),
                subnet: Subnet {
                    gateway: Ipv4Addr::new(192, 168, 1, 200),
                    mask: Mask(24),
                },
                dns: Some(Ipv4Addr::new(1, 1, 1, 1)),
                secondary_dns: Some(Ipv4Addr::new(1, 0, 0, 1)),
            }))),
            stack: NetifStack::Eth,
            ..NetifConfiguration::eth_default_client()
        })?,
    )?;

Both of these things work just fine, but the only way i've managed to connect to my http server is via setting the wifi in ap mode and connecting to it directly. Plugging ethernet and trying to curl charizhard.local gets me a timeout.

This is probably more a networking issue than a code issue but I'm scratching my head here. Should I be setting everything to DHCP?

What am I missing?

@ivmarkov
Copy link
Collaborator

Patch all of the sys hal and svc crates to GIT master and try again.

@indexds
Copy link
Contributor Author

indexds commented Dec 21, 2024

Did so, updated esp-idf to 5.3.2 as well, that wasn't the issue. I might be stupid really, but when the eth netif on the esp32 receives a packet, does it not try to interpret it for the http server? Do I need to route it there somehow? Because the server is not bound to a specific netif afaik.. I'm a bit confused about this whole thing

@ivmarkov
Copy link
Collaborator

ivmarkov commented Dec 21, 2024

Did so, updated esp-idf to 5.3.2 as well, that wasn't the issue. I might be stupid really, but when the eth netif on the esp32 receives a packet, does it not try to interpret it for the http server? Do I need to route it there somehow? Because the server is not bound to a specific netif afaik.. I'm a bit confused about this whole thing

No it must work.

The reason why I asked you to update to master (please don't update to ESP IDF 5.3.X, this is not officially supported yet) is because we had a bug with assigning static IP to eth that might had been affecting you.

With that said:

  • Have you tried pinging your esp32 on IP 192, 168, 1, 100? Does it work?
  • Do you actually start the EspEth instance? Can't see that in your code?

@indexds
Copy link
Contributor Author

indexds commented Dec 22, 2024

Hi, sorry for the delay. I don't know what I changed, but I get a stack overflow in emac_rx when trying to start the eth netif now, except I can't find the related setting in my Kconfig.. The documentation says it should be CONFIG_EMAC_TASK_STACK_SIZE but even setting it manually seems to have no influence on the result.

@ivmarkov
Copy link
Collaborator

Hi, sorry for the delay. I don't know what I changed, but I get a stack overflow in emac_rx when trying to start the eth netif now, except I can't find the related setting in my Kconfig.. The documentation says it should be CONFIG_EMAC_TASK_STACK_SIZE but even setting it manually seems to have no influence on the result.

OK but were you actually starting the EspEth instance before my suggestion, or not?

@indexds
Copy link
Contributor Author

indexds commented Dec 22, 2024

Yes I was

@ivmarkov
Copy link
Collaborator

ivmarkov commented Dec 22, 2024

Yes I was

Then I have no explanation as to why your eth does not work. Another possibility is that you are not keeping around the eth driver variable, so once you initialize it and start it, you are dropping it immediately does destroying the eth driver.

But this is all speculations. I think it is best if you do a minimal repro case and upload it somewhere. I don't even need your HTTP or mDNS stuff. It should just be the eth stuff - you configure it with a static IP, you start it, then you std::thread:sleep forever in your main - yet - the eth is not ping-able from another machine.

In fact, you can even take this example as a base, adjust it to not use DHCP but a static IP and then upload somewhere. Or just paste the full code of the non-working example here.

As for the stack overflow, as long as you do specify CONFIG_EMAC_TASK_STACK_SIZE=<number of bytes> in your sdkconfig.defaults, and the sdkconfig.defaults is in the root of your binary project, and you don't do any other equilibristics like setting a different target dir, it should work.

@indexds
Copy link
Contributor Author

indexds commented Dec 22, 2024

This might not even be an issue on the esp's side, I'll try to investigate. What's a good value for CONFIG_EMAC_TASK_STACK_SIZE? I'm at 8192 and it's still crashing.. Is there a way to tell at runtime what the stack size is for a specific task? I'm not sure it's even registered the config properly. Thanks for the help either way, it's always appreciated.

@ivmarkov
Copy link
Collaborator

ivmarkov commented Dec 22, 2024

This might not even be an issue on the esp's side, I'll try to investigate. What's a good value for CONFIG_EMAC_TASK_STACK_SIZE? I'm at 8192 and it's still crashing.. Is there a way to tell at runtime what the stack size is for a specific task? I'm not sure it's even registered the config properly. Thanks for the help either way, it's always appreciated.

I have no idea what is a good value, but 8192 should be a good enough value. And then again, if you provide a short repro that does not work or is crashing on stack size (for the latter, I need a full project generated perhaps with esp-idf-template) then I can try to help.

But I don't think me continuing to brainstorm based on incomplete information would be helpful.

Let me know if you plan to provide a repro, then we can keep this open. Otherwise I'll close.

@indexds
Copy link
Contributor Author

indexds commented Dec 24, 2024

Well I think I might have isolated the problem? I don't know really because this is quite different from what I was doing before, but simply using the example seems to timeout on the wait_netif_up() call.

I (493) main_task: Calling app_main()
I (523) esp_idf_svc::eth: Driver initialized
I (523) esp_idf_svc::eth: Initialization complete
I (523) esp_idf_svc::eth: Stopping
E (523) esp_eth: esp_eth_stop(310): driver not started yet      
I (533) esp_idf_svc::eth: Stop requested
I (533) esp_eth.netif.netif_glue: 08:f9:e0:a7:97:7b
I (543) esp_eth.netif.netif_glue: ethernet attached to netif    
I (543) eth: Eth created
I (553) eth: Starting eth...
I (2253) esp_idf_svc::eth: Start requested
I (2253) eth: Waiting for DHCP lease...
I (17263) esp_idf_svc::eth: Stopping
I (17263) esp_idf_svc::eth: Stop requested
I (17263) esp_idf_svc::eth: EspEth dropped
I (17263) esp_idf_svc::netif: Dropped
I (17263) esp_idf_svc::eth: Stopping
E (17273) esp_eth: esp_eth_stop(310): driver not started yet    
I (17273) esp_idf_svc::eth: Stop requested
I (17283) esp_idf_svc::eth: Driver deinitialized
I (17283) esp_idf_svc::eth: EthDriver dropped
I (17293) esp_idf_svc::eventloop: System event loop dropped     
Error: ESP_ERR_TIMEOUT
I (17303) main_task: Returned from app_main()

Here's the repository: https://github.com/indexds/eth

I might be stupid really, but you just have to start it and then it's supposed to do its thing right?

@ivmarkov
Copy link
Collaborator

Just don't call wait_netif_up when you use a static ip and the example should work.

@ivmarkov
Copy link
Collaborator

If you use it with a dhcp and it times out that means either your pins are wrong or your eth is not properly connected with a cable.

@indexds
Copy link
Contributor Author

indexds commented Dec 25, 2024

If you use it with a dhcp and it times out that means either your pins are wrong or your eth is not properly connected with a cable.

I'm using dhcp, my pins should be fine since I remember using this exact setup with this bridge and I just double checked my cable, it's all the way in. This is very strange. I'd like to think it's a config issue but since this is a blank project there isn't anything configured at all.

@indexds
Copy link
Contributor Author

indexds commented Dec 25, 2024

Actually, I might just have oyster brain, my pc wasn't getting an ip because of course it wasn't since the esp wasn't acting as a dhcp server; with these configs I can now ping 192.168.1.1.

    let mut eth_netif = EspEth::wrap_all(
        eth_driver,
        EspNetif::new_with_conf(&NetifConfiguration {
            ip_configuration: Some(IpConfiguration::Router( <-- Culprit
                IpRouterConfiguration {
                    subnet: Subnet{
                        gateway: Ipv4Addr::new(192, 168, 1, 1),
                        mask: Mask(30),
                    },
                    dhcp_enabled: true,
                    dns: None,
                    secondary_dns: None,
                }
            )),
            stack: NetifStack::Eth,
            ..NetifConfiguration::eth_default_router()
        })?,
    )?;

Yet I still can't ping charizhard.local..

@ivmarkov
Copy link
Collaborator

ivmarkov commented Dec 25, 2024

I'm a bit lost honestly as to what exactly you are doing.

  • Like, two hours ago you complained the example itself does not work
  • You originally opened the issue with a setup with a static IP and client settings
  • Now you are pasting some other piece of code where eth is configured as a router

Why don't you start with the absolute simplest example of all, which is this example. Unchanged. And connect your esp32 to a super-standard router and check that that setup works. Only then try to complicate it, and step by step then.

@indexds
Copy link
Contributor Author

indexds commented Dec 25, 2024

  • Like, two hours ago you complained the example itself does not work

Because I'm dumb. It didn't work because I was connecting it to another dhcp client (my pc) so both of them were waiting for the other to give them an ip (i think). That's why the timeout occurred.

  • Why don't you start with the absolute simplest example of all, which is this example. Unchanged. And connect your esp32 to a super-standard router and check that that setup works. Only then try to complicate it, and step by step then.

As you said, connecting directly to a router works fine

  • You originally opened the issue with a setup with a static IP and client settings

That would be the oyster brain in question.

What I need to do is have a setup like this: PC <-RJ45-> ESP ETH NETIF <-> ESP HTTP SERVER

Now that I make the esp act as the dhcp server in the equation, PC <-RJ45-> ESP ETH NETIF this part works.

The esp has address 192.168.1.1 and is assigning my computer's eth card 192.168.1.2. Pinging 192.168.1.1 from the computer works just fine.

So now I can ping the esp but the http server running on said esp is still not pingable (ESP ETH NETIF <-> ESP HTTP SERVER).

This might honestly be oyster brain syndrome striking again.

@indexds
Copy link
Contributor Author

indexds commented Dec 25, 2024

It's an mdns issue, curl 192.168.1.1 works

@ivmarkov
Copy link
Collaborator

It's an mdns issue, curl 192.168.1.1 works

I've not used the IDF mDNS since forever, so not sure what is going on.
For one, if you just want your Esp to be findable by charizhard.local it is not necessary to do the

    mdns.add_service(
        Some("charizhard"), // instance_name
        "_http",            // service_type
        "_tcp",             // proto
        80,                 // port
        &[],                // txt
    )?;

... thing.

mdns.set_hostname("charizhard")?;

should be enough, and then of course you MUST keep around the mdns var forever without dropping it.

With that said, you are running an Esp server, you probably should look into the source code of the mDns IDF component if it is intelligent enough to actually figure out what IP to advertise (in your case it should be your fixed ip 192.168.1.1).

I would not be surprised if they take some shortcuts, and their code only works if the network is configured with client / DHCP settings. But then again, without actually looking into their code, I'm speculating.

@ivmarkov
Copy link
Collaborator

ivmarkov commented Dec 25, 2024

btw best is to do avahi browse -a quickly after starting the Esp. This way, even if the Esp advertises a wrong IP address (so ping times out) you'll at least see if the Esp is publishing the initial mDns broadcast record.

Also the message you get when trying to do ping chr...local will tell you what is going on. If the reply is "name or service not known" then even the first mdns broadcast fails. If it replies with the wrong IP address (and ping is timing out) then the Esp is advertising the wrong IP address.

@indexds
Copy link
Contributor Author

indexds commented Dec 25, 2024

Alright thanks for all the info i'll look into it!

@indexds
Copy link
Contributor Author

indexds commented Dec 27, 2024

So yeah, using wireshark I saw.. nothing. The esp isn't advertising at all. It's whatever, I'll just use the ip, I can't be bothered to sift through the 5k lines of mdns lib to see how they do it and do it statically x)

@indexds indexds closed this as completed Dec 27, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in esp-rs Dec 27, 2024
@ivmarkov
Copy link
Collaborator

So yeah, using wireshark I saw.. nothing. The esp isn't advertising at all. It's whatever, I'll just use the ip, I can't be bothered to sift through the 5k lines of mdns lib to see how they do it and do it statically x)

@indexds: I remembered something: actually, if you haven't switched yet to a patched esp-idf-svc from master (a new release is really really close, but still), perhaps you should, as this might fix your issues: #502 (comment)

Also since you are using a "router" eth, you might want to set the IF name of your netif to ETH_DEF, if you follow the conversation in that thread ^^^.

Also and as per here you might want to put CONFIG_MDNS_PREDEF_NETIF_ETH=y and CONFIG_ETH_ENABLED=y in your sdkconfig.defaults.

@indexds
Copy link
Contributor Author

indexds commented Dec 27, 2024

So yeah, using wireshark I saw.. nothing. The esp isn't advertising at all. It's whatever, I'll just use the ip, I can't be bothered to sift through the 5k lines of mdns lib to see how they do it and do it statically x)

@indexds: I remembered something: actually, if you haven't switched yet to a patched esp-idf-svc from master (a new release is really really close, but still), perhaps you should, as this might fix your issues: #502 (comment)

Also since you are using a "router" eth, you might want to set the IF name of your netif to ETH_DEF, if you follow the conversation in that thread ^^^.

Also and as per here you might want to put CONFIG_MDNS_PREDEF_NETIF_ETH=y and CONFIG_ETH_ENABLED=y in your sdkconfig.defaults.

  • I'm on esp-idf-svc master branch
  • I set the key and descriptions to the client defaults
  • Put those configs in the kconfig file

Still not working for ethernet. But mdns itself is working fine as connecting both my pc and the esp to my phone's ap allow the pc to resolve charizhard.local, so it's advertising. Just not on the right interface.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

No branches or pull requests

2 participants