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

Fix MPS2 CM3DS ethernet driver #15284

Merged
merged 4 commits into from
May 13, 2022
Merged

Fix MPS2 CM3DS ethernet driver #15284

merged 4 commits into from
May 13, 2022

Conversation

ramielkhatibPQS
Copy link

Summary of changes

The ethernet driver for the target MPS2 CM3DS has several issues. Some of these issues are severe for this target as the high level API function won't function properly. Here is the summary of changes in this PR:

  • Bug 1: Heap allocation for the received packet is set to maximum frame size instead of message size.
  • Bug 2: Receive packet function is reading one less word that required.
  • Improvement: Packet receiving and sending functions use words instead of bytes
  • Deprecation fix: Updated function calls to not use deprecated functions.

Impact of changes

This PR will only affect users who are using MPS2 CM3DS. There is no implication for any other target. The current driver doesn't function properly, so this PR should actually fix ethernet issues for users of this target.

Migration actions required

Fix bugs for the ethernet driver of MPS2 CM3DS.

Documentation

Bug 1:
The function SMSC9220_EMAC::low_level_input should create a heap for the packet equal to the size of the message (most of which are couple hundred bytes). The current code uses maximum frame size (1522 bytes) for each packet. This will cause the heap to quickly fill up. In fact, the default memory size (lwip.mem-size) used for this heap is 1600 bytes. This means that once you have one other packet allocated (extremely common), the heap allocation will always fails.

Also, I recommend increasing the default lwip.mem-size because that amount is very small especially if you send or receive a few large packets in the network. This is NOT done in current PR

Bug 2:
The function smsc9220_receive_by_chunks loads data from the Ethernet port. It is expected to return the Ethernet frame without the 4 CRC bytes. However, you are required to call the Ethernet data port register (32-bit) an amount equal to the number of frame words (including the 4 CRC bytes) to pop all frame words. The current code doesn't call the register for the last word (which has CRC data). This causes subsequent calls to have this missed word at the beginning. The impact of this is huge as the high level API is getting fed wrong data. I added a fix by adding one additional call. The function is also updated because of the improvement below.

Improvement:
The functions smsc9220_receive_by_chunks and smsc9220_send_by_chunks are supposed to implement receiving and sending packets by chunks. However, the functions SMSC9220_EMAC::low_level_input and SMSC9220_EMAC::link_out, which call them respectively, already require or assemble the full packet. Also, smsc9220_receive_by_chunks doesn't implement the "chunks" part.

I renamed the functions to smsc9220_receive_packet and smsc9220_send_packet. The functions now do their operations by word instead of by bytes. The functions SMSC9220_EMAC::low_level_input and SMSC9220_EMAC::link_out already handle allocation, continuity and word alignment of the packet buffer. Some of the change ideas are taken from here.

Deprecation fix:

I updated the function calls for sleep_for to use the chrono time arguments since the regular ones are deprecated.


Pull request type

[X] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[X] No Tests required for this change (E.g docs only update)
[] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers


@ciarmcom ciarmcom added the release-type: patch Indentifies a PR as containing just a patch label May 11, 2022
@ciarmcom ciarmcom requested a review from a team May 11, 2022 07:00
@ciarmcom
Copy link
Member

@ramielkhatibPQS, thank you for your changes.
@ARMmbed/mbed-os-maintainers please review.

@0xc0170
Copy link
Contributor

0xc0170 commented May 11, 2022

Can you create 4 commits based on the description your provided?

Each of the item in the list you have should be own commit (it will be helpful and simplify our review).

@ramielkhatibPQS
Copy link
Author

I updated the PR to use 4 commits as requested. Please review. Thank you!

@0xc0170
Copy link
Contributor

0xc0170 commented May 12, 2022

Thank you, easier to review now. What we are missing are the details from here in the commit messages (the subjects are there but can you add additional info from the description in this pull request to the commit messages?). it's best to have them along the code than only here on Github.

@0xc0170
Copy link
Contributor

0xc0170 commented May 12, 2022

Did you run any networking tests or how was this tested?

@0xc0170 0xc0170 added needs: review release-type: patch Indentifies a PR as containing just a patch labels May 12, 2022
Rami Elkhatib added 4 commits May 12, 2022 18:18
The sleep_for function is updated to use the chrono time arguments since
the regular ones are deprecated.
The function SMSC9220_EMAC::low_level_input should create a heap for the
packet equal to the size of the message (most of which are couple hundred
bytes). The current code uses maximum frame size (1522 bytes) for each
packet. This will cause the heap to quickly fill up. In fact, the default
memory size (lwip.mem-size) used for this heap is 1600 bytes. This means
that once you have one other packet allocated (extremely common), the
heap allocation will always fails.

Also, it is recommend to increase the default lwip.mem-size because that
amount is very small especially if you send or receive a few large packets
in the network. This is NOT done in current commit.
The function smsc9220_receive_by_chunks loads data from the Ethernet port.
It is expected to return the Ethernet frame without the 4 CRC bytes.
However, it is required to call the Ethernet data port register (32-bit)
an amount equal to the number of frame words (including the 4 CRC bytes)
to pop all frame words. The current code doesn't call the register for the
last word (which has CRC data). This causes subsequent calls to have this
missed word at the beginning. The impact of this is huge as the high level
API is getting fed wrong data. The fix adds one additional call to the data
port register.
The functions smsc9220_receive_by_chunks and smsc9220_send_by_chunks are
supposed to implement receiving and sending packets by chunks. However,
the functions SMSC9220_EMAC::low_level_input and SMSC9220_EMAC::link_out,
which call them respectively, already require or assemble the full packet.
Also, smsc9220_receive_by_chunks doesn't implement the "chunks" part.

This commit renames the functions to smsc9220_receive_packet and
smsc9220_send_packet. The functions now do their operations by word
instead of by bytes. The functions SMSC9220_EMAC::low_level_input and
SMSC9220_EMAC::link_out already handle allocation, continuity and word
alignment of the packet buffer.
@ramielkhatibPQS
Copy link
Author

ramielkhatibPQS commented May 12, 2022

I updated the commits with the description.

For the tests, here is my setup:

I connected a PC and the MPS2+ directly through an Ethernet cable to isolate their network.

For the PC side:

  • I had a DHCP server running on the PC side using dnsmasq.
  • I had wireshark running on the PC for that interface to monitor the traffic.
  • I also used Scapy library in python to send packets. It helped me to discover the initial bugs. However, this is optional because the bugs can easily be detected with the DHCP packets.

For the MPS2+ side:

I had the CM3DS flashed on the FPGA. I ran this simple code which should link the two devices and attempt to acquire an IP address through DHCP.

#include "mbed.h"
#include "EthernetInterface.h"

EthernetInterface net;

int main()
{
    int ret;
    // Bring up the ethernet interface
    printf("Ethernet socket example\n");
    ret = net.connect();
    printf("net.connect returned: %x\n", ret);

    // Bring down the ethernet interface
    ret = net.disconnect();
    printf("net.disconnect returned: %x\n", ret);
    return 0;
}

To reproduce bug 1 (heap):

The MPS2+ will send a DHCP discover and almost immediately get a DHCP offer. The heap allocation line (cbfda0e) will fail for the DHCP offer because there will not be 1522 bytes available in the heap memory (1600 bytes by default). Also, notice that the variable message_length is there but not used.

To reproduce bug 2 (packet one word short):

Print the data variable after empty_rx_fifo (f7aca62).

for(uint32_t i = 0; i < packet_length_byte; i++)
    printf("%02x", data[i]);
printf("\n");

The DHCP protocol should work as follows

  1. MPS2+ sends DHCP DISCOVER
  2. PC sends DHCP OFFER
  3. MPS2+ sends DHCP REQUEST
  4. PC sends DHCP ACK

The first packet DHCP OFFER will show up exactly like in wireshark. However the DHCP ACK packet will be off by 4 bytes in comparison with wireshark.

@mergify mergify bot added needs: CI and removed needs: review labels May 13, 2022
@mbed-ci
Copy link

mbed-ci commented May 13, 2022

Jenkins CI Test : ✔️ SUCCESS

Build Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & Artifacts

CLICK for Detailed Summary

jobs Status
jenkins-ci/mbed-os-ci_build-cloud-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-ARM ✔️
jenkins-ci/mbed-os-ci_unittests ✔️
jenkins-ci/mbed-os-ci_build-cloud-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-greentea-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_build-example-ARM ✔️
jenkins-ci/mbed-os-ci_build-example-GCC_ARM ✔️
jenkins-ci/mbed-os-ci_greentea-test ✔️

@0xc0170 0xc0170 merged commit 15d1b93 into ARMmbed:master May 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants