# HOWTO: Statically map and/or rename network devices

## danomac

Howto: Statically map and/or rename network devices

I suppose the first thing that comes to mind is Why? For one, if you have a lot of network adaptors, it's easier to manage. You can name an adaptor related to the task it performs: this way, if you need to stop it for whatever reason, you can simply stop eth_database instead of eth2 - you don't need to remember which is which. Second, if something changes in the kernel, such as the loading order of the modules, or you add a new adaptor, your existing interfaces will not get renumbered on you. That can save some headaches as well.

I've created this thread in response to this thread.

The example will be based on what I was trying to do: set up a new server that has 3 network adaptors doing various things:

NIC 0: LAN (Static IP)

NIC 1: WAN (Dynamic IP, this always retrieves me my 'public' IP address for the server.)

NIC 2: DBMS (Static IP, crossover cabled to a database server - figured this was the best way... less points of failure [i.e. a switch])

Keep in mind that you can name these devices however you want, just remember to change the names in this example to suit your needs.

Step 1: Identify your network devices

First, you need figure out what physical port is which MAC address. In my case, I unplugged all the cables, and plugged each interface in one at a time to figure out what exactly udev has done with the mapping. What I did after plugging in and starting/stopping the net.eth* scripts was I made myself a little chart:

```

Current

udev                        Physical Location

Device   MAC ADDRESS        (back of PC)          New Mapping

--------  -----------------  -------------------  ---------------

eth0     00:30:BD:BB:25:E8  Bottom                eth_dbms

eth1     00:20:ED:68:45:EC  Top                   eth_lan

eth2     00:50:BF:AE:E9:DC  Middle                eth_wan

```

Now, you need to get information from udev - time to use the udevinfo command:

```

# udevinfo -a -p /sys/class/net/eth0 | grep address

    SYSFS{address}=="00:30:bd:bb:25:e8"

# udevinfo -a -p /sys/class/net/eth1 | grep address

    SYSFS{address}=="00:20:ed:68:45:ec"

# udevinfo -a -p /sys/class/net/eth2 | grep address

    SYSFS{address}=="00:50:bf:ae:e9:dc"

```

There we have it, the MAC addresses of the NICs that we can use with udev to statically map a device name.

Step 2: Setting up udev for static / custom name mapping

Now that we have the MAC addresses, and what I want to name them in the nifty chart I made for myself earlier, time to go set up a rules file:

/etc/udev/rules.d/10-local.rules:

```

SUBSYSTEM=="net", ATTR{address}=="00:20:ed:68:45:ec", NAME="eth_lan"

SUBSYSTEM=="net", ATTR{address}=="00:50:bf:ae:e9:dc", NAME="eth_wan"

SUBSYSTEM=="net", ATTR{address}=="00:30:bd:bb:25:e8", NAME="eth_dbms"

```

Note: You need to use exactly what udevinfo reports in the previous step! If you mix up the case of the address udev will NOT work!!

Now, udev knows how we want to map devices.

Step 3: Changing initscripts to reflect device name changes

Next we need to tell the gentoo initscripts to follow suit:

/etc/conf.d/net:

```

# This blank configuration will automatically use DHCP for any net.*

# scripts in /etc/init.d.  To create a more complete configuration,

# please review /etc/conf.d/net.example and save your configuration

# in /etc/conf.d/net (this file :]!).

config_eth_wan=( "dhcp" )

config_eth_lan=( "192.168.247.80/24" )

routes_eth_lan=( "default via 192.168.247.1" )

config_eth_dbms=( "192.168.240.100/24" )

```

OK, now the configuration is done - now we need to "reset" the old net.eth* scripts, remove them, then recreate them:

```

# /etc/init.d/net.eth0 stop

# /etc/init.d/net.eth0 zap

# /etc/init.d/net.eth1 stop

# /etc/init.d/net.eth1 zap

# /etc/init.d/net.eth2 stop

# /etc/init.d/net.eth2 zap

# rc-update del net.eth0 default

# rc-update del net.eth1 default

# rc-update del net.eth2 default

# rm /etc/init.d/net.eth0

# rm /etc/init.d/net.eth1

# rm /etc/init.d/net.eth2

# cd /etc/init.d

# ln -s net.lo net.eth_lan

# ln -s net.lo net.eth_wan

# ln -s net.lo net.eth_dbms

```

Step 4: Testing the new configuration

After this, the system is now reconfigured! Reboot to test the new udev mapping. Once the system is back up, run ifconfig to see if everything was moved over:

```

# ifconfig -a

eth_dbms  Link encap:Ethernet  HWaddr 00:30:BD:BB:25:E8

          BROADCAST MULTICAST  MTU:1500  Metric:1

          RX packets:0 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

          Interrupt:12 Base address:0xe800

eth_lan   Link encap:Ethernet  HWaddr 00:20:ED:68:45:EC

          BROADCAST MULTICAST  MTU:1500  Metric:1

          RX packets:0 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

          Interrupt:10 Base address:0xd400

eth_wan   Link encap:Ethernet  HWaddr 00:50:BF:AE:E9:DC

          BROADCAST NOTRAILERS RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:1898 errors:0 dropped:0 overruns:0 frame:0

          TX packets:711 errors:1 dropped:0 overruns:0 carrier:2

          collisions:0 txqueuelen:1000

          RX bytes:134086 (130.9 Kb)  TX bytes:79642 (77.7 Kb)

          Interrupt:10 Base address:0xec00

lo        Link encap:Local Loopback

          inet addr:127.0.0.1  Mask:255.0.0.0

          UP LOOPBACK RUNNING  MTU:16436  Metric:1

          RX packets:0 errors:0 dropped:0 overruns:0 frame:0

          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:0

          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

```

So far, the system seems to be fine, now time to test the initscripts themselves:

```

# /etc/init.d/net.eth_wan start

 * Starting eth_wan

 *   Bringing up eth_wan

 *     dhcp

 *       Running dhcpcd ...                 

 *       eth_wan received address 192.168.247.12

# /etc/init.d/net.eth_lan start

 * Starting eth_lan

 *   Bringing up eth_lan

 *     192.168.247.80/24           

 *   Adding routes

 *     default gw 192.168.247.1 ...

# /etc/init.d/net.dbms start

 * Starting eth_dbms

 *   Bringing up eth_dbms

 *     192.168.240.100/24

```

Looks like the reconfiguration is working!

Step 5: Adding the new scripts to the appropriate runlevel[s]

If your configuration is working correctly, all you need to do is add the initscripts to the appropriate runlevel so they start at boot time (this step is optional if you are using netplug/ifplug/a daemon to run scripts when a cord is plugged in):

```

# rc-update add net.eth_wan default

# rc-update add net.eth_lan default

# rc-update add net.eth_dbms default

```

Step 6: Miscellaneous stuff

Now you should be able to use the new device names with other tools:

```

# ifconfig eth_wan

eth_wan   Link encap:Ethernet  HWaddr 00:50:BF:AE:E9:DC

          inet addr:192.168.247.12  Bcast:192.168.247.255  Mask:255.255.255.0

          UP BROADCAST NOTRAILERS RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:2494 errors:0 dropped:0 overruns:0 frame:0

          TX packets:966 errors:1 dropped:0 overruns:0 carrier:2

          collisions:0 txqueuelen:1000

          RX bytes:180146 (175.9 Kb)  TX bytes:114621 (111.9 Kb)

          Interrupt:10 Base address:0xec00

```

As far iptables is concerned, you should be able to refer to the interfaces with their new names. (Use the -o or -i switches.)

Step 7: Conclusion

There you have it, a nifty little guide that details what you need to statically map (or rename) your ethernet devices. Hopefully people will find this useful; I know I sure did!Last edited by danomac on Thu Jan 25, 2007 6:23 pm; edited 6 times in total

----------

## danomac

Still adding some other details to it... done!

----------

## Pandor

usefull tip you got there, thx!

I was having some trouble with eth0 and eth1 switching some times because i build them as modules.

Now that they have names mapped to their MAC's it's all good.

I believe step 5 is optional if you use netplug/ifplug, is it not?

----------

## danomac

Yes, if you use a daemon to detect if a cord is plugged in for autoconfiguration, step 5 is optional. I'll change the howto.

----------

## PaulBredbury

In udev-103, this works for me to remap net.eth0 and net.eth1

/etc/udev/rules.d/10-local.rules (named 10 so it runs before 70-persistent-net.rules to be the first to set the NAME)

```
SUBSYSTEM=="net", ATTR{address}=="00:14:f2:64:8d:82", NAME="lan"

SUBSYSTEM=="net", ATTR{address}=="00:14:f2:64:6b:c4", NAME="inet"
```

This is useful to run:

```
grep eth /etc/udev/rules.d/*
```

----------

## AdmiralNemo

Why does udev have such a hard time renaming eth# devices to other eth#s?  For example:

I have four network interfaces--eth0, eth1, eth2, eth3--each performs a specific function and has for about a year now.  Lately, the numbers have changed, respectively now eth2, eth3, eth0, eth1.  When I put definitions to rename them back to their original numbers as above in 70-persistent-net.rules (as I read somewhere before I found this thread), sometimes they don't all get renamed properly.  Sometimes I get left with something on the lines of eth1_rename and no eth3.  I have tried compiling the drivers as modules and directly into the kernel.  I have not tried putting the rules in 10-local.rules, could that make a difference?  Why does this only happen sometimes, after several reboots, it works fine?

Am I doing something wrong?  If so, what can I change?  Is it just a problem with trying to rename devices to a name already taken by another device?  If so, is there a way to work around this?

It may also be of interest that ifrename refuses to even attempt to rename the devices as I specify.

Any insight would be appreciated.

----------

## PaulBredbury

 *AdmiralNemo wrote:*   

> Why does this only happen sometimes

 

Because it's a race condition, AIUI. 

See above. Use 10-local.rules. If ifconfig shows e.g. "HWaddr 00:18:F3:64:8A:82", then that's the MAC address for the rule - but make sure you enter it into the rules file in lower-case.

----------

## evildick

Is there a way to do this based solely on modules?  For example lets say I have a bunch of Gentoo workstations where the mac address is going to be different and I need certain brands of network cards to be set up on certain network interfaces.

To give you more details, . . .  I have:

- ndiswrapper, handles two wireless cards, a Netgear WG511v2 and a Linksys WUSB54Gv2.  Both of these need to be on wlan0 so that I can configure the wireless AP for them.

- ipw2200 handles one card, this needs to be on eth1 so I can configure the wireless AP for it.

- rt2500pci handles one card which needs to be on ra0 so i can also configure the AP for it.

I tried setting up an alias in /etc/modules.d/aliases but that does not work.  Is there a way to map modules for certain interfaces no matter what the mac address is?

----------

## PaulBredbury

 *evildick wrote:*   

> I need certain brands of network cards to be set up on certain network interfaces.

 

See what useful info this gives (change eth0 to whatever interface it is currently):

```
udevinfo -a -p /sys/class/net/eth0/
```

Perhaps you can match based on ATTRS{vendor}

 *Quote:*   

> Both of these need to be on wlan0 so that I can configure the wireless AP for them.

 

I think they have to be two separate devices in /dev - I don't see how they could share wlan0.

----------

## evildick

 *Quote:*   

> I think they have to be two separate devices in /dev - I don't see how they could share wlan0.

 

Apologies, they are two separate devices on separate machines, both using wlan0.

I just sucked up the extra work and added all the MAC addresses to the udev rules.

----------

## Akhouk

 *Quote:*   

> 
> 
> ```
> KERNEL="eth*", SYSFS{address}="00:20:ed:68:45:ec", NAME="eth_lan"
> 
> ...

 

This bit is wrong, there should be double == for the matching parts and single = for the setting part. So it should read...

```
KERNEL=="eth*", SYSFS{address}=="00:20:ed:68:45:ec", NAME="eth_lan"

KERNEL=="eth*", SYSFS{address}=="00:50:bf:ae:e9:dc", NAME="eth_wan"

KERNEL=="eth*", SYSFS{address}=="00:30:bd:bb:25:e8", NAME="eth_dbms"
```

That is why some people are getting strange things like eth0_rename

----------

## danomac

 *Akhouk wrote:*   

>  *Quote:*   
> 
> ```
> KERNEL="eth*", SYSFS{address}="00:20:ed:68:45:ec", NAME="eth_lan"
> 
> ...

 

Corrected. I just updated the PC I had done this on, so I'd better change the rules while I'm thinking about it.

Edit: Crap, it was a typo. Sorry if it caused some frustration...   :Embarassed: Last edited by danomac on Mon Jan 08, 2007 5:47 pm; edited 2 times in total

----------

## danomac

 *evildick wrote:*   

>  *Quote:*   I think they have to be two separate devices in /dev - I don't see how they could share wlan0. 
> 
> Apologies, they are two separate devices on separate machines, both using wlan0.
> 
> I just sucked up the extra work and added all the MAC addresses to the udev rules.

 

I don't know udev that well, but setting the rules might work... just don't put both cards in the same PC, or you might get some weird results.

Edit: Nevermind, I misread your original post. You meant by module. I don't know if udev is able to do that...

----------

## Gentree

 *danomac wrote:*   

>  *Akhouk wrote:*    *Quote:*   
> 
> ```
> KERNEL="eth*", SYSFS{address}="00:20:ed:68:45:ec", NAME="eth_lan"
> 
> ...

 

So how about going back and correcting the other syntax error as well ?

Thanks for a good guide (E&OE). Wasted me a bit of time with the second card not responding to the changes when the first one did.   :Rolling Eyes: 

All working now. 

What I'd like to do is have the second one automatic like before since I have a bunch of PCI NICs and I dont want to have to fart around chasing MAC addresses and editing a bunch of config files everytime I change a NIC.

I have tied down the onboard device that I now use for inet. That way next time they rework udev pkg I wont go down like a blind man in pub brawl and be left with not connection to the forums.   :Evil or Very Mad:  (Always seem to need an independant system to back up Gentoo.)

So having assured a fixed connection I'd like to let the other NIC, whatever it may be, get autodetected as eth0 and hence get the lan address.

Ideas?

BTW udevstart is a bit quicker than a reboot.   :Wink: 

----------

## danomac

 *Gentree wrote:*   

> 
> 
> So how about going back and correcting the other syntax error as well ?
> 
> Thanks for a good guide (E&OE). Wasted me a bit of time with the second card not responding to the changes when the first one did.  
> ...

 

I didn't realize there was another typo. I did write this back in August, and apparently a lot has changed since then.

----------

## Gentree

 *Akhouk wrote:*   

>  *Quote:*   
> 
> ```
> KERNEL="eth*", SYSFS{address}="00:20:ed:68:45:ec", NAME="eth_lan"
> 
> ...

 

note the first two parts of each line are tests requiring == only the last part is an assignment: NAME=....

 :Wink: 

----------

## danomac

 *Gentree wrote:*   

> 
> 
> note the first two parts of each line are tests requiring == only the last part is an assignment: NAME=....
> 
> 

 

OMFG, that's what I get for editing stuff while half-asleep.   :Confused: 

Fixed now I hope...

----------

## null__

This does not seem to work for me. Can anyone help?

/etc/udev/rules.d/10-local.rules

```
SUBSYSTEM=="net", ATTR{address}=="00:12:3f:70:8a:6f", NAME="eth0"

SUBSYSTEM=="net", ATTR{address}=="00:60:b0:cd:4e:22", NAME="eth1"

SUBSYSTEM=="net", ATTR{address}=="00:10:5a:26:a3:ff", NAME="eth2"
```

ifconfig

```
eth0      Link encap:Ethernet  HWaddr 00:10:5A:26:A3:FF

          inet addr:192.168.1.113  Bcast:192.168.1.225  Mask:255.255.255.0

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:10013 errors:0 dropped:0 overruns:0 frame:0

          TX packets:3396 errors:0 dropped:0 overruns:0 carrier:0

          collisions:205 txqueuelen:1000

          RX bytes:6721623 (6.4 Mb)  TX bytes:577769 (564.2 Kb)

          Interrupt:16 Base address:0xe780

eth2      Link encap:Ethernet  HWaddr 00:12:3F:70:8A:6F

          inet addr:192.168.1.115  Bcast:192.168.1.225  Mask:255.255.255.0

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:678 errors:0 dropped:0 overruns:0 frame:0

          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:80002 (78.1 Kb)  TX bytes:84 (84.0 b)
```

As you can see, the MAC addresses and interface names of eth0 and eth2 are swapped.

----------

## PaulBredbury

 *null__ wrote:*   

> ATTR{address}

 

In old udev versions, ATTR has to be SYSFS. Otherwise, debug it.

----------

## null__

Thanks for your time.

Changing ATTR{address} to SYSFS{address} did not solve the issue; udevinfo reports it as ATTR{address}, besides.

I ran udevtest on my network devices as your link suggested, but I'm not sure how to interpret the output to pinpoint the source of the problem. It shows the undesired renaming occurring, but not, as far as I can see, what is causing it. Here's the output:

udevtest /class/net/eth0

```
parse_file: reading '/etc/udev/rules.d/05-udev-early.rules' as rules file

parse_file: reading '/etc/udev/rules.d/10-local.rules' as rules file

parse_file: reading '/etc/udev/rules.d/30-svgalib.rules' as rules file

parse_file: reading '/etc/udev/rules.d/50-udev.rules' as rules file

parse_file: reading '/etc/udev/rules.d/60-persistent-input.rules' as rules file

parse_file: reading '/etc/udev/rules.d/60-persistent-storage.rules' as rules file

parse_file: reading '/etc/udev/rules.d/70-persistent-cd.rules' as rules file

parse_file: reading '/etc/udev/rules.d/75-cd-aliases-generator.rules' as rules file

parse_file: reading '/etc/udev/rules.d/75-persistent-net-generator.rules' as rules file

parse_file: reading '/etc/udev/rules.d/90-hal.rules' as rules file

parse_file: reading '/etc/udev/rules.d/95-net.rules' as rules file

This program is for debugging only, it does not create any node,

or run any program specified by a RUN key. It may show incorrect results,

if rules match against subsystem specfic kernel event variables.

main: looking at device '/class/net/eth0' from subsystem 'net'

wait_for_sysfs: file '/sys/class/net/eth0/address' appeared after 0 loops

udev_rules_get_name: rule applied, 'eth0' becomes 'eth2'

rename_netif: changing net interface name from 'eth0' to 'eth2'

udev_device_event: renamed netif to 'eth2'

main: run: 'udev_run_devd net'

main: run: 'socket:/org/kernel/udev/monitor'

main: run: 'socket:/org/freedesktop/hal/udev_event'

main: run: 'net.sh eth2 start'
```

udevtest /class/net/eth2

```
parse_file: reading '/etc/udev/rules.d/05-udev-early.rules' as rules file

parse_file: reading '/etc/udev/rules.d/10-local.rules' as rules file

parse_file: reading '/etc/udev/rules.d/30-svgalib.rules' as rules file

parse_file: reading '/etc/udev/rules.d/50-udev.rules' as rules file

parse_file: reading '/etc/udev/rules.d/60-persistent-input.rules' as rules file

parse_file: reading '/etc/udev/rules.d/60-persistent-storage.rules' as rules file

parse_file: reading '/etc/udev/rules.d/70-persistent-cd.rules' as rules file

parse_file: reading '/etc/udev/rules.d/75-cd-aliases-generator.rules' as rules file

parse_file: reading '/etc/udev/rules.d/75-persistent-net-generator.rules' as rules file

parse_file: reading '/etc/udev/rules.d/90-hal.rules' as rules file

parse_file: reading '/etc/udev/rules.d/95-net.rules' as rules file

This program is for debugging only, it does not create any node,

or run any program specified by a RUN key. It may show incorrect results,

if rules match against subsystem specfic kernel event variables.

main: looking at device '/class/net/eth2' from subsystem 'net'

wait_for_sysfs: file '/sys/class/net/eth2/address' appeared after 0 loops

udev_rules_get_name: rule applied, 'eth2' becomes 'eth0'

rename_netif: changing net interface name from 'eth2' to 'eth0'

udev_device_event: renamed netif to 'eth0'

main: run: 'udev_run_devd net'

main: run: 'socket:/org/kernel/udev/monitor'

main: run: 'socket:/org/freedesktop/hal/udev_event'

main: run: 'net.sh eth0 start'
```

----------

## PaulBredbury

 *null__ wrote:*   

> parse_file: reading '/etc/udev/rules.d/05-udev-early.rules' as rules file
> 
> parse_file: reading '/etc/udev/rules.d/10-local.rules' as rules file

 

Check whether a rule in the 05 file is setting the NAME, and thus taking precedence over the 10 file.

eth{0,1,2} are horrible names, especially for debugging - use e.g. lan, inet, wlan - something meaningful and not a default of the standard udev rules.

----------

## `VL

Also check this link:http://gentoo-wiki.com/TIP_Rename_Network_Interfaces

----------

## danomac

That link on the wiki is slightly different. I didn't bother to see how the scripts rename devices, but it seems to me that it just creates an alias, whereas this howto tells udev directly to map the device. The net configuration in gentoo doesn't do anything.

----------

## `VL

yes, udev is the logical place to name devices. 

But, what if you want to rename non-physical interfaces, such as ppp,tap or something else? 

Then you need iproute2 utilities: they allow interface renaming:

/sbin/ip link set ppp0 down

/sbin/ip link set ppp0 name yourname

/sbin/ip link set yourname up

but you have to re-setup routing after pushing interface down & up... 

if anybody knows how to make pppd create interface with name other than ppp0, please write..

----------

## danomac

 *`VL wrote:*   

> if anybody knows how to make pppd create interface with name other than ppp0, please write..

 

It may be possible for udev to still map these to something else, at the minimum alias the interface to something else.

generally the kernel reports a ppp device and udev will map it - so use udevinfo on the existing class and see what is reported. You can likely use a different method other than a hardware address. Then all you have to do is write up a rules file to change the name. No idea about changing other scripts that use it though, so use caution.  :Wink: 

As an example, find the device in /sys:

```

$ find /sys -name ppp*

```

and then use udevinfo to get its properties:

```

$ udevinfo -a -p /sys/class/example   ##replace with the find result above

```

You can use the properties displayed with udev, just make sure one uniquely identifies it.

----------

## burger

But how do I conf my two onboard nic's what has the same mac adress?

----------

