Bug 997573

Summary: udev will not rename ethX to ethY based on MAC address.
Product: [Fedora] Fedora Reporter: Ben Greear <greearb>
Component: systemdAssignee: systemd-maint
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: unspecified    
Version: 19CC: extras-orphan, harald, johannbg, jonathan, lnykryn, msekleta, notting, plautrba, systemd-maint, vpavlin, zbyszek
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-08-15 18:59:22 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Ben Greear 2013-08-15 16:12:10 UTC
Description of problem:

udev in Fedora 19 will not honor an persistent rules file like this:


[root@foo ~]# cat /etc/udev/rules.d/70-persistent-net.rules 

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:e0:ed:1c:ec:e4", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eth2"

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:e0:ed:1c:ec:e5", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eth3"

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:30:48:fc:17:a2", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eth0"

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:30:48:fc:17:a3", ATTR{dev_id}=="0x0", ATTR{type}=="1", NAME="eth1"

It *will* rename them if the name is something like eth0r.

I see no errors in /var/log/messages about failing due to 'File Exists',
but udev *would* have to use something like the old .rename logic in
this case since I have 4 ethernet devices whose names need to be shuffled.

Version-Release number of selected component (if applicable):

[root@foo ~]# rpm -qa|grep systemd
systemd-python-204-9.fc19.x86_64
systemd-204-9.fc19.x86_64
systemd-libs-204-9.fc19.x86_64
systemd-sysv-204-9.fc19.x86_64


How reproducible:

Always.


Steps to Reproduce:
1.  Create persistent rules file
2.  Boot
3.  Interfaces are often not named as requested.  No indication
udev even tried.

Actual results:

Pain and sadness, and mis-named network interfaces.


Expected results:

Properly named network interfaces, like it has been working for years
(up to Fedora 17, at least).


Additional info:

NetworkManager is disabled (need white-list support before it can work on
our systems).

Tried disabling 60-net.rules and that did not have any obvious effect.

Only 'ifcfg-eth0' network script exists (ie, no ifcfg-eth1, eth2, eth3).

Comment 1 Zbigniew Jędrzejewski-Szmek 2013-08-15 18:59:22 UTC
Renaming within the ethX namespace is unsupported, because of the inherent race conditions with the kernel creating ethX devices in parallel with the renaming. Please rename to names outside of this namespace.

Comment 2 Ben Greear 2013-08-15 19:15:29 UTC
That can easily be worked around by detecting the failure to rename due to collision and trying again, moving the colliding netdev name to foo.rename
(or perhaps e[mac] or some of the biosdevname magic names).

You are effectively making it impossible to use 'ethX' interfaces with any
deterministic ordering.  This has been working for years, so I think this is a pretty serious regression.

At the very least, you should document this restriction as well as log warnings to /var/log/messages so that users immediately know why their old udev rules files are silently not working.

Comment 3 Jóhann B. Guðmundsson 2013-08-15 19:36:19 UTC
This is already documented here, Both the reason for this change in behaviour as well as how to disable it... 

1. http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

Comment 4 Ben Greear 2013-08-15 19:49:01 UTC
The documentation is incomplete at best.  It talks about doing a 70-my-net-name.rules file to disable the feature, and that is exactly what I did, but it does NOT work if you use NAME=ethY.  That limitation is a regression, and it is not documented anywhere that I could find.  And, there are no reasons given in the kernel logs about why udev didn't do as requested, so I had to spend way too much time to figure out why my devices were improperly named.

I am fine with the reasons and implementation to create interesting 'persistent' device names automatically.  But, I also want the ability to specify the name based on MAC address if I want to over-ride the default behaviour.

Based on the first comment that closed this bug, it seems the developers decided there is some technical reason they can't rename within a kernel namespace, but I cannot see any reason this should be the case.  The code would have to do some error checking, retrying, and device renaming to rename target device names, but it's not rocket science.

Comment 5 Zbigniew Jędrzejewski-Szmek 2013-08-15 20:05:04 UTC
(In reply to Ben Greear from comment #4)
> The documentation is incomplete at best.  It talks about doing a
> 70-my-net-name.rules file to disable the feature, and that is exactly what I
> did, but it does NOT work if you use NAME=ethY.  That limitation is a
> regression, and it is not documented anywhere that I could find.  And, there
> are no reasons given in the kernel logs about why udev didn't do as
> requested, so I had to spend way too much time to figure out why my devices
> were improperly named.
> 
> I am fine with the reasons and implementation to create interesting
> 'persistent' device names automatically.  But, I also want the ability to
> specify the name based on MAC address if I want to over-ride the default
> behaviour.
>
> Based on the first comment that closed this bug, it seems the developers
> decided there is some technical reason they can't rename within a kernel
> namespace, but I cannot see any reason this should be the case.  The code
> would have to do some error checking, retrying, and device renaming to
> rename target device names, but it's not rocket science.
Renaming of interfaces inside the kernel namespace was always broken. But because the bootup and discovery of devices was slower in general, it didn't show up very often. It happens more often as the boot gets faster. As you say,
it would be possible to implement some hacky workarounds, but they would be always that, and it is encouraged to simply use a different, illustrative, namespace like 'lan', 'external', or whatever fits.

This choice has been documented in the wiki page linked by Jóhann, the change is mentioned in the NEWS file for systemd, and has been subject of many discussions/flamewars. If you think that it should be mentioned in other places, please provide concrete suggestions or even better patches.

Comment 6 Kay Sievers 2013-08-15 20:17:06 UTC
While we tried to free the name to rename our interface to it, the kernel
frequenly loaded a new driver an stole our "freed" name. It's not as simple
as it sounds to make all that work reliably.

An all that happens in parallel with potentially many interfaces all asking
and fighting for a new name (which is already busy) in the same namespace.

It's all possible "rocket-science-wise", sure, but we just have given up adding
more and more hack and more global cross-event semaphores in udev to work
around all these issues. It's the kernel's namespace and should stay as that,
userspace should not try to fiddle in it at the same time.

The only viable option to get back ethX names would probably be to tell
the kernel it should start with eth1000+ upwards, instead of starting at 0.

Comment 7 Ben Greear 2013-08-15 20:30:26 UTC
I would consider fixing udev to be able to rename and deal with races.  Where is a good place to discuss doing this?

Please add documentation to the "I don't like this, how do I disable this?" section right where it talks about using a custom rules file, to let them know that the kernel name spaces are reserved and will not work.

With regard to the kernel taking the 'freed' name, why could you not just retry in a loop:  The kernel can't steal it forever if you have a finite number of networkd evices.  I don't even see why you would need any locking in user-space:  Just try the rename, check the results, and try again if it did not work.

As for kernel space, I'll post a patch to allow renaming the default kernel space (to the netdev mailing list).  Assuming udev hard-codes it's name-space definitions, please make that configurable.  Then it could all work again even if you don't make udev smart enough to deal with netdev name collisions.

Comment 8 Harald Hoyer 2013-08-20 11:37:31 UTC
Say you want to have MAC A renamed to eth0.

Say the kernel discovered:

eth0 -> MAC B
eth1 -> MAC A

What name should udev give eth0, which is blocking eth1 from getting renamed to eth0?

What, if eth0 is already UP? You cannot even rename it then?

Comment 9 Ben Greear 2013-08-20 15:51:47 UTC
eth0 becomes eth0.[rnd-ascii-hex]
  Try multiple times if eth0.[rnd-ascii-hex] is already taken, or
  eth0 exists again after renaming the first eth0.
  If eth0 is up, configure it down before attempting rename.
    Could try 'ifdown foo' first, but don't worry if that fails.
    Use 'ip link set dev foo down' to make certain it's down.
  Keep a list of all devices that were renamed and whether they were
  admin-up when we took them down.

  Because of races with the kernel, you have to keep
  trying the rename until it works and don't freak out
  if it fails a few times.

Once the target device is properly renamed to eth0, go through the
list of interfaces you renamed and find first free ethX and name
them thus.  You have to retry this in a loop as well in case ethX is
taken due to race with kernel.  If interface was originally down,
admin it back up again with 'ifup foo'.

If multiple udev processes can be attempting renames at the same time,
you would probably want a global udev mutex lock to keep renames from
stepping on each other.

Downing interfaces and such can be disruptive, but you should only have
to do this if you have conflicts.  It is much less disruptive to do this
in udev than with a fixup script after udev has completed.

For the retry loops, put an upper limit (maybe 1000 tries) so that it
cannot spin forever if there are some unforseen bugs or interfaces just
cannot be renamed for whatever reason.

Renaming used to work (in Fedora 17 and earlier), so this should not be
new..perhaps the code already mostly exists, or you could find whatever
patch disabled the old behaviour and resurrect it.

Comment 10 Zbigniew Jędrzejewski-Szmek 2013-08-21 02:54:25 UTC
Sorry, no.