Why is delay after ifconfig down needed before up if changing MAC address?

5,132

Solution 1

The delay in bringing down the interface is likely related to the driver and/or hardware for the interface. If that is correct, then there is no standard way to know when the driver or hardware have truly put the interface down.

Reading through the rest of the troubleshooting more, it sounds like there could be a competing process in play - especially the part about the interface coming back up "on its own". Perhaps there is a tool that runs and puts the interface back up after the attempt to take it down?

That would be a little tricky to detect, but not impossible. I can't think of any quick and easy way to suggest that you could detect it.

Solution 2

I don't think a delay is required. Before putting the interface down, you should be able to physically disconnect from the old MAC address. I'm on wireless at the moment, so I can't test this out right now, but look at the ifconfig --help. Something like this?:

ifconfig <interface> del <address>

On wireless, when I disconnect, I run a little script that clears everything, including the AP's MAC address:

sudo dhcpcd --release "$INTERFACE"
sudo iwconfig "$INTERFACE" essid off
sudo iwconfig "$INTERFACE" ap off
sudo ifconfig "$INTERFACE" down
Share:
5,132

Related videos on Youtube

piotrekkr
Author by

piotrekkr

Updated on September 18, 2022

Comments

  • piotrekkr
    piotrekkr over 1 year

    Hi I made bash script to put down my interface, change MAC address and get it up again.

    #!/bin/bash
    
    INTERFACE_STATUS=$( cat /sys/class/net/eth0/operstate )
    
    echo "$INTERFACE_STATUS"
    
    if [ "$INTERFACE_STATUS" == "up" ]
    then
        echo  "Putting down eth0"
        sudo ifconfig eth0 down
        # putting down eth0 works only when I sleep 10 seconds after using command
        #sleep 10
        echo "$( cat /sys/class/net/eth0/operstate )"
    #     TRIES=0
    #     while [ "$( cat /sys/class/net/eth0/operstate )" == "up" ]
    #     do
    #         sleep 1
    #         TRIES=$(($TRIES + 1))
    #         if [ "$TRIES" == "7" ]
    #         then
    #             echo Could not put down eth0
    #             exit 1
    #         fi
    #     done
    fi
    
    sudo ifconfig eth0 hw ether "91:91:91:91:91:91"
    
    sudo ifconfig eth0 up
    

    The problem is that it does not work. Immediately after putting down eth0 /sys/class/net/eth0/operstate changes to down but it seems like it isn't down yet. I takes like 10 seconds to put down interface eth0 so only way to make it work is to add sleep 10 after putting down eth0.

    So my question is how to check if eht0 is really down?

    //EDIT

    It's like command ifconfig eth0 up is used to early because it never gets up with new MAC address. I need to put it down, wait 10 s, change MAC and put it back again. I suspect that putting down eth0 takes few seconds and putting it up again too early does not work.

    //EDIT 2

    I checked MAC address again and it seems that it's changed, so now I think that it could be something with DNS because when I'm using ping on google I get unknown host. But same method with sleep 10 does work.

    // EDIT 3

    After using script without sleep 10 I tried using ping:

    piotrek@piotrek-Vostro-2520:~$ ping 212.77.100.101
    connect: Network is unreachable
    piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
    connect: Network is unreachable
    piotrek@piotrek-Vostro-2520:~$ ifconfig 
    eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
            inet addr:10.36.253.122  Bcast:10.36.253.255  Mask:255.255.255.0
            inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
            RX packets:74297 errors:0 dropped:0 overruns:0 frame:0
            TX packets:38597 errors:0 dropped:0 overruns:0 carrier:0                                                                                           
            collisions:0 txqueuelen:1000                                                                                                                       
            RX bytes:32417366 (32.4 MB)  TX bytes:5201537 (5.2 MB)0                                                                                           
          collisions:0 txqueuelen:1000                                                                                                                       
          RX bytes:32417366 (32.4 MB)  TX bytes:5201537 (5.2 MB)
    

    //EDIT 4 SUM UP

    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
    piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
    connect: Network is unreachable
    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sleep 10; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
    piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
    PING 212.77.100.101 (212.77.100.101) 56(84) bytes of data.
    64 bytes from 212.77.100.101: icmp_req=1 ttl=246 time=8.91 ms
    64 bytes from 212.77.100.101: icmp_req=2 ttl=246 time=8.76 ms
    64 bytes from 212.77.100.101: icmp_req=3 ttl=246 time=8.52 ms
    ^C
    --- 212.77.100.101 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2003ms
    rtt min/avg/max/mdev = 8.523/8.734/8.917/0.194 ms
    

    Why sleep 10 matters?

    // EDIT 5

    Its getting quite weird. When I use sleep it works fine. When I try without sleep it looks like IP is ok, interface is up, but network does not work. When I try put down eth0 with sudo ifconfig eth0 down after few seconds my OS (ubuntu 12.10) reconects me automaticly with my old MAC address and I get new IP. With second use of sudo ifconfig eth0 down I'm able to fully put down eth0.

    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sleep 10; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig
    eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
            inet addr:10.36.253.241  Bcast:10.36.253.255  Mask:255.255.255.0
            inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
            RX packets:439341 errors:0 dropped:0 overruns:0 frame:0
            TX packets:224187 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000 
            RX bytes:400718780 (400.7 MB)  TX bytes:26246307 (26.2 MB)
    
    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down; sudo ifconfig eth0 hw ether 08:3e:8e:2d:36:55 ; sudo ifconfig eth0 up
    piotrek@piotrek-Vostro-2520:~$ ping -n 212.77.100.101
    connect: Network is unreachable
    piotrek@piotrek-Vostro-2520:~$ ifconfig
    eth0      Link encap:Ethernet  HWaddr 08:3e:8e:2d:36:55  
            inet addr:10.36.253.241  Bcast:10.36.253.255  Mask:255.255.255.0
            inet6 addr: fe80::a3e:8eff:fe2d:3655/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
            RX packets:439656 errors:0 dropped:0 overruns:0 frame:0
            TX packets:224321 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000 
            RX bytes:400827185 (400.8 MB)  TX bytes:26267012 (26.2 MB)
    
    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down
    piotrek@piotrek-Vostro-2520:~$ ifconfig
    eth0      Link encap:Ethernet  HWaddr e0:db:55:97:de:cc  
            inet addr:10.36.253.122  Bcast:10.36.253.255  Mask:255.255.255.0
            inet6 addr: fe80::e2db:55ff:fe97:decc/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
            RX packets:440302 errors:0 dropped:0 overruns:0 frame:0
            TX packets:224862 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000 
            RX bytes:401129508 (401.1 MB)  TX bytes:26323176 (26.3 MB)
    
    piotrek@piotrek-Vostro-2520:~$ sudo ifconfig eth0 down
    piotrek@piotrek-Vostro-2520:~$ ifconfig eth0
    eth0      Link encap:Ethernet  HWaddr e0:db:55:97:de:cc  
            BROADCAST MULTICAST  MTU:1500  Metric:1
            RX packets:440437 errors:0 dropped:0 overruns:0 frame:0
            TX packets:224881 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:1000 
            RX bytes:401147424 (401.1 MB)  TX bytes:26326068 (26.3 MB)
    

    //EDIT 6

    I've tried solution suggested by @Moreaki but the same thing happens. Script runs around one second but my network is unreachable after using it. This is the code from @Moreaki:

    #!/usr/bin/env bash
    
    INTF=eth0
    INTERFACE_STATUS=$(cat /sys/class/net/${INTF}/operstate)
    echo "$INTERFACE_STATUS"
    
    if [ "$INTERFACE_STATUS" == "up" ]; then
        echo "Putting down ${INTF}"
        # if you need to remove all IP addresses associated with ${INTF}
        sudo ip addr flush dev ${INTF}
        # set the interface status down
        sudo ip link set dev ${INTF} down
        # flush neighbour cache
        sudo ip neigh flush dev ${INTF}
        # flush routing cache entries pertaining to ${INTF}
        sudo ip route flush table cache dev ${INTF}
        echo "New state: $(cat /sys/class/net/${INTF}/operstate)"
    fi
    
    sudo ip link set dev ${INTF} address "08:3e:8e:2d:36:55"
    sudo ip link set dev ${INTF} up
    

    After using it I get:

    piotrek@piotrek-Vostro-2520:~$ ./mac_test.sh 
    up
    Putting down eth0
    New state: down
    

    And after trying ping:

    piotrek@piotrek-Vostro-2520:~$ ping google.com
    ping: unknown host google.com
    piotrek@piotrek-Vostro-2520:~$ ping 8.8.8.8
    connect: Network is unreachable
    

    //EDIT 7

    Using routing script from @Moreaki my routing before changing mac address looks like this:

    piotrek@piotrek-Vostro-2520:~$ ./routing.sh 
    Destination        Gateway         Source             Iface    R_Type RT_table  
    default            10.36.253.1     10.36.253.122      eth0            main      
    10.36.253.0/24     0.0.0.0         10.36.253.122      eth0            main      
    169.254.0.0/16     0.0.0.0         10.36.253.122      eth0            main
    

    And after changing MAC address using my script with 10s delay:

    piotrek@piotrek-Vostro-2520:~$ ./routing.sh 
    Destination        Gateway         Source             Iface    R_Type RT_table  
    default            10.36.253.1     10.36.253.241      eth0            main      
    10.36.253.0/24     0.0.0.0         10.36.253.241      eth0            main      
    169.254.0.0/16     0.0.0.0         10.36.253.241      eth0            main
    

    Routing after using @Moreaki script:

    piotrek@piotrek-Vostro-2520:~$ ./routing.sh
    Destination        Gateway         Source             Iface    R_Type RT_table
    

    @Moreaki also suggested to comment line sudo ip addr flush dev ${INTF} but I still get connect: Network is unreachable. My routing after using his script with commented line looks like this:

    piotrek@piotrek-Vostro-2520:~$ ./routing.sh
    Destination        Gateway         Source             Iface    R_Type RT_table  
    10.36.253.0/24     0.0.0.0         10.36.253.122      eth0
    
    • user
      user over 10 years
      In what way do you mean that the interface is not down when sysfs reports it as down? ifconfig eth0 down almost certainly makes a call to the kernel to effect the change, and sysfs reads the internal kernel data structures, so I don't see how sysfs could report the interface being down when it really is not. Maybe you are referring to something related but different?
    • piotrekkr
      piotrekkr over 10 years
      It's like command ifconfig eth0 up is used to early because it never gets up with new MAC address. I need to put it down, wait 10 s, change MAC and put it back again. See my edited post
    • user
      user over 10 years
      So your question is really "why does the sequence ifconfig eth0 down, ifconfig eth0 hw ether ..., ifconfig eth0 up with no intervening delays not change the MAC address on eth0, when adding a delay between down and ether does?", correct?
    • Marek Zakrzewski
      Marek Zakrzewski over 10 years
      Use grep -q "up" /sys/class/net/eth0/operstate && sudo ifdown eth0 This is a more accurate way of doing checks in bash. Also use ifdown eth0 instead. This uses ifconfig to configure the interfaces.
    • piotrekkr
      piotrekkr over 10 years
      @MichaelKjörling I check MAC again and it seems like it is changed so now I think it's more like DNS problem than interface. I get like unknown host when trying to ping google.
    • user
      user over 10 years
      My guess given the newly added information would be in the direction of the ARP cache. Try to ping an IP address (without name resolution on the response, so ping -n) rather than something which requires DNS resolution.
    • piotrekkr
      piotrekkr over 10 years
      @MichaelKjörling ping does not work. I get network unreachable but ifconfig seems ok. See my edit
    • user
      user over 10 years
      Now we're getting somewhere. I don't have an answer, but this looks like it's answerable. I gave the question a better title, too, which hopefully summarizes what the question is about.
    • Raphael Ahrens
      Raphael Ahrens over 10 years
      Do you use DHCP to get your IP?
    • piotrekkr
      piotrekkr over 10 years
      @RaphaelAhrens Yes, IP is from DHCP.
    • Raphael Ahrens
      Raphael Ahrens over 10 years
      @piotrekkr could it then be that the exchange between the DHCP server and your machine takes up to 10 seconds?
    • piotrekkr
      piotrekkr over 10 years
      @RaphaelAhrens It might take like 10 seconds. Maby I'm wrong but isn't it ifconfig eth0 up that take new IP from DHCP, not ifconfig eth0 down? Sleep 10 is after ifconfig eth0 down.
    • Raphael Ahrens
      Raphael Ahrens over 10 years
      @piotrekkr You have the DHCPRELEASE commando so the DHCP server knows that it can reuse the IP address. You could try it without DHCP.
    • Raphael Ahrens
      Raphael Ahrens over 10 years
      @piotrekkr mhh but it will not be the only thing.
    • piotrekkr
      piotrekkr over 10 years
      @RaphaelAhrens I updated my post. After using command without sleep it looks like working but network is unreachable. So I tried to just put down eth0 and I was surprised because after ifconfig eth0 down I've got reconnected with my old MAC address and with old IP. I could fully put down eth0 after using ifconfig eth0 down second time.
    • BatchyX
      BatchyX over 10 years
      What hardware is this ? it could be a driver bug.
  • wchargin
    wchargin over 10 years
    If ifconfig is deprecated, what should we use instead?
  • Moreaki
    Moreaki over 10 years
    The iproute2 framework that was introduced in kernel 2.1.x. You can find more documentation here.
  • piotrekkr
    piotrekkr over 10 years
    @Moreaki Thanks for your suggestion but It didn't work. See my last edit. Your script works for like one second and after using it my network is unreachable.
  • Moreaki
    Moreaki over 10 years
    Well, from what I see, unless you add an IP address when you fire you device up again (after flushing all IP addresses), things won't work. So, either add an IP address into the script or do not execute the line sudo ip addr flush dev ${INTF} in my snippet, as I hinted in my comment.
  • Moreaki
    Moreaki over 10 years
    Judging from your new output (though I believe you have mixed the explanation with the actual output in the last two comment paragraphs), you are missing your default route and it seems that you are also running a dhclient. So, disable this client and add the default route as follows: sudo ip route add default via 10.36.253.1 dev ${INTF}. You can add it at the end of the script. If you decide to flush the IP address(es), you also have to add your IP address again: sudo ip addr add 10.36.253.241/24 brd + dev eth0 label eth0 before the default route setup.
  • Moreaki
    Moreaki over 10 years
    So far I didn't have enough information to know if you needed DHCP or not, I only judged based on the output you provided, and there you have the routing entry 169.254.0.0/16. This means that DHCP didn't get an IP address. I don't recall the exact inner workings of the DHCP client when interface state changes occur. Now, besides this, have you tried my suggestion to add the default route as suggested in my last comment? From what I can see, there's really nothing special in you setup and it should just work.
  • piotrekkr
    piotrekkr over 10 years
    I'll try adding default route on monday when I'm back to work. So after I use your script with or without sudo ip addr flush dev ${INTF}, it seams that I don't get new IP? How can I force DHCP to give me new IP?
  • ash
    ash over 10 years
    Disagree on deprecation of ifconfig. Sometimes, the old tools are fine just the way they are.