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

Unable to set Ethernet mac address from qemu command line (QEMU-225) #107

Open
3 tasks done
mzakharocsc opened this issue Nov 27, 2024 · 6 comments
Open
3 tasks done

Comments

@mzakharocsc
Copy link

Checklist

  • Checked the issue tracker for similar issues to ensure this is not a duplicate
  • Read the documentation to confirm the issue is not addressed there and your configuration is set correctly
  • Tested with the latest version to ensure the issue hasn't been fixed

How often does this bug occurs?

always

Expected behavior

when specifying custom mac on qemu command line like this: -nic user,model=open_eth,mac=00:00:00:00:00:05 , the value does not reflect expected bytes when read using the following api:
esp_read_mac(mac_addr, ESP_MAC_ETH)

Actual behavior (suspected bug)

mac_addr always shows up as "00:00:00:00:00:03", regardless of what qemu's parameter 'mac=XX:XX;XX:XX:XX:XX' is set to.

Error logs or terminal output

No response

Steps to reproduce the behavior

idf.py qemu monitor

Project release version

latest

System architecture

Intel/AMD 64-bit (modern PC, older Mac)

Operating system

Linux

Operating system version

Ubuntu 20.04

Shell

Bash

Additional context

No response

@github-actions github-actions bot changed the title Unable to set Ethernet mac address from qemu command line Unable to set Ethernet mac address from qemu command line (QEMU-225) Nov 27, 2024
@igrr
Copy link
Member

igrr commented Nov 27, 2024

@mzakharocsc That's right, IDF's esp_read_mac doesn't query the MAC address from the network device, instead it derives the address from the base MAC address stored in eFuse. Therefore setting the MAC address on the network device side doesn't affect the result returned by esp_read_mac.

To extract the MAC address from the network device you can use esp_eth_ioctl with ETH_CMD_G_MAC_ADDR argument:

esp_err_t get_addr(esp_eth_handle_t eth_handle, uint8_t eth_mac[6]) {
    return esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, eth_mac)
}

Or, directly from the esp_eth_mac_t MAC instance, if you have that instead of esp_eth_handle_t:

esp_err_t get_addr(esp_eth_mac_t *mac_handle, uint8_t eth_mac[6]) {
    return mac_handle->read_addr(mac_handle, eth_mac);
}

Once you have read the address from the device, you either use it to configure your base MAC address (which is absent from eFuses) or just set the custom MAC address for the interface.

Edit: I'll also see if we can provide reasonable behavior (to use the MAC address configured via QEMU arguments) at least in IDF examples (which rely on examples/common_components/protocol_examples_common/eth_connect.c) or if we can add a --mac-addr argument to idf.py qemu which will pre-set the MAC address in eFuse.

@mzakharocsc
Copy link
Author

mzakharocsc commented Nov 27, 2024

Running examples/ethernet/basic, which does esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); returns '00:00:00:00:00:03' also, thats because I suspect in static esp_err_t emac_opencores_init(esp_eth_mac_t *mac in esp_eth_mac_openeth.c it also uses esp_read_mac() to set mac address of the interface.

Please confirm

@igrr
Copy link
Member

igrr commented Nov 27, 2024

Ah yes, you are totally right, I have missed that part.

I see two things we could do here:

  1. Modify emac_opencores_init, adding more complex logic around the selection of the MAC address:
    • Get the base MAC address. If it is non-zero, then use esp_read_mac to obtain the address derived for the Ethernet interface. This would handle the case when the emulated eFuses do contain a valid MAC address.
    • If the base MAC address is zero, try to get the address from the (emulated) ethernet MAC. If non-zero, use that address. This would allow setting the address via -nic user,model=open_eth,mac=.... argument.
    • If both are zero, fall back to some default address.
  2. Add --mac-addr option in idf.py qemu wrapper to allow setting the base address in eFuses.

Does that sound reasonable to you?

(If we do the above, we also need to fix the ifdef in protocols_examples_common so that the address doesn't get overridden in the example projects which use this component. Currently we check for !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET which includes the openeth case.)

@mzakharocsc
Copy link
Author

mzakharocsc commented Nov 27, 2024

  1. is the preferred option in my opinion

I tried to read the MAC address like so:

    // Initialize the MAC
    openeth_reset();
    openeth_set_tx_desc_cnt(TX_BUF_COUNT);

    uint32_t mac0 = REG_READ(OPENETH_MAC_ADDR0_REG);
    uint32_t mac1 = REG_READ(OPENETH_MAC_ADDR1_REG);

    printf("MAC0=%#lx  MAC1=%#lx\n", mac0, mac1);

inside esp_eth_mac_openeth.c, however I am getting all 0's even when -nic user,model=open_eth,mac=00:00:00:00:00:05 is set on QEMU parameters

Please advise.

Edit. it looks like MAC_ADDR0 and MAC_ADDR1 are never set on init inside QEMU emulator: opencores_eth.c . How else would one retreive the mac address set by QEMU parameters?

@igrr
Copy link
Member

igrr commented Nov 27, 2024

Looks like openeth emulation doesn't call qemu_macaddr_default_if_unset to initialize the MAC address, like other ethernet adapter emulations in QEMU do, for example

qemu_macaddr_default_if_unset(&s->c.macaddr);

Will fix that as well.

(And we have to copy the MAC address from NICInfo into the registers.)

@igrr
Copy link
Member

igrr commented Dec 11, 2024

QEMU part of the fix merged in b726cfe, IDF part of the fix is in review and will be linked here once merged.

espressif-bot pushed a commit to espressif/esp-idf that referenced this issue Dec 20, 2024
The intention of the code block was to set MAC address for SPI
Ethernet modules, however !CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET also
affected the case of CONFIG_EXAMPLE_USE_OPENETH.
This commit corrects the code to match the original intention.

Related to espressif/qemu#107
espressif-bot pushed a commit to espressif/esp-idf that referenced this issue Dec 20, 2024
Openeth driver did not consider the possibility that the MAC address
was specified when launching QEMU, and would always overwrite that
address with the address obtained from esp_read_mac.
When running QEMU, setting the MAC address via QEMU arguments is more
convenient than crafting an eFuse file with the correct MAC address.
This change modifies openeth driver to first check if an address has
been set in QEMU and uses it if so. Otherwise it falls back to the
address obtained from esp_read_mac.

As part of this change, also removed the unnecessary variable
emac_opencores_t::addr, the address is only kept in the registers of
the emulated peripheral now.

For full effect this also requires changes in QEMU, see
espressif/qemu#107 for background. Without
changes in QEMU, this commit keeps the same behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants