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

Failing test due to layer 3 device having all-zero MAC address #9

Open
weskoerber opened this issue Jun 19, 2024 · 4 comments · May be fixed by #13
Open

Failing test due to layer 3 device having all-zero MAC address #9

weskoerber opened this issue Jun 19, 2024 · 4 comments · May be fixed by #13
Labels
bug Something isn't working

Comments

@weskoerber
Copy link
Owner

The get_first_no_loopback test looks like this:

test "get_first_no_loopback" {
    const addr = try getFirstNoLoopback(testing.allocator);

    try testing.expectEqual(false, addr.is_loopback);
    try testing.expect(!std.mem.eql(u8, &addr.data, &.{ 0, 0, 0, 0, 0, 0 }));
}

It calls the getFirstNoLoopback function to -- you guessed it -- get the first interface that is not a loopback device. What identifies a loopback device is the is_loopback field in the MacAddress struct (related: #8). However, I assumed that only a loopback interface would have a MAC address with all zeroes, but that's not the case.

I use tailscale, which runs at layer 312. At this level, the tailscale0 device cannot be assigned a MAC address. Therefore, the data field in the MacAddress struct was all zeroes, which caused the test to fail.

This has 2 implications:

  1. The test for non-loopback devices should not assume only loopback devices have a MAC address of all zeroes.
  2. I may not want to remove the is_loopback field from the MacAddress struct (again, see Remove is_loopback field from MacAddress struct #8); otherwise, there will be no way to differentiate true loopback devices from devices on layer 3.

An alternative to item 2 in the preceding list is to include the IP address in the MacAddress struct- that way 127.0.0.1 can be the identifier for loopback devices.

I'm not sure what I want to do here. I still want to have loopback device identification but I do not want to encode more information than necessary in the MacAddress struct -- I think even the is_loopback field is too much. I want to keep the scope of this library relatively narrow.

Footnotes

  1. https://www.reddit.com/r/Tailscale/comments/v2renw/linux_mac_address_for_interface/

  2. https://en.wikipedia.org/wiki/OSI_model#Layer_architecture

@weskoerber weskoerber added the bug Something isn't working label Jun 19, 2024
weskoerber added a commit that referenced this issue Jun 21, 2024
weskoerber added a commit that referenced this issue Jun 21, 2024
@weskoerber
Copy link
Owner Author

I added e9ca243 that addresses this, in one way or another.

It removes is_loopback from MacAddress.

If we encounter a loopback device in getFirstNoLoopback as reported by the SIOCGIFFLAGS request, we recursively call next() on the iterator which will either return null if there are no more devices or the next device.

@thafer30
Copy link

I'm curious if other "virtual" network interfaces such as docker networks show up with a Mac address of all zeros as well

@weskoerber
Copy link
Owner Author

I'm curious if other "virtual" network interfaces such as docker networks show up with a Mac address of all zeros as well

Interestingly, I got a MAC address from a Docker virtual network that was not all zeroes... I'm not sure why though; I don't know how docker manages it's virtual networks.

weskoerber added a commit that referenced this issue Sep 12, 2024
weskoerber added a commit that referenced this issue Sep 12, 2024
weskoerber added a commit that referenced this issue Sep 12, 2024
* refactor!: remove is_loopback from MacAddress

related: #9

* fix: inverted test

'get_first_no_loopback' was actually expecting the MAC address was a
loopback (all zeroes).

* chore: remove references to 'is_loopback' field

chore: remove print message in linux if iterator

* chore: remove unused struct

* chore: update version
@weskoerber
Copy link
Owner Author

I don't know how docker manages it's virtual networks.

https://stackoverflow.com/questions/42946453/how-does-the-docker-assign-mac-addresses-to-containers

Additionally, Docker's network interface is a bridge, whereas Tailscale's is a user-space TUN adapter:

❯ ethtool -i tailscale0
driver: tun
version: 1.6
firmware-version: 
expansion-rom-version: 
bus-info: tun
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

❯ ethtool -i docker0
driver: bridge
version: 2.3
firmware-version: N/A
expansion-rom-version: 
bus-info: N/A
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

Some additional info on the topic from the interwebs:

So it seems the answer to this is that network bridges (Docker) operate on Layer 2 - which is why they have MAC addresses - and Tailscale's TUN adapters operate on Layer 3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants