Linux – IP vs Ifconfig Commands Pros and Cons

ifconfigiplinuxnetworking

At some point, in some teaching material (from Linux Foundation) on Linux that I came across, the following is mentioned:

ip command is more versatile and more efficient than ifconfig because it uses netlink sockets rather than ioctl system calls.

Can anyone elaborate a bit on this because I cannot understand what's going on under the hood?

P.S. I am aware of this topic on those tools but it does not address this specific difference on how they operate

Best Answer

The ifconfig command on operating systems such as FreeBSD and OpenBSD was updated in line with the rest of the operating system. It nowadays can configure all sorts of network interface settings on those operating systems, and handle a range of network protocols. The BSDs provide ioctl() support for these things.

This did not happen in the Linux world. There are, today, three ifconfig commands:

  • ifconfig from GNU inetutils
    jdebp % inetutils-ifconfig -l
    enp14s0 enp15s0 lo
    jdebp % inetutils-ifconfig lo
    lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Bcast:0.0.0.0  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:9087 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9087 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:51214341  TX bytes:51214341
    jdebp %
  • ifconfig from NET-3 net-tools
    jdebp % ifconfig -l
    ifconfig: option -l' not recognised.
    ifconfig:--help' gives usage information.
    jdebp % ifconfig lo
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        inet6 ::2  prefixlen 128  scopeid 0x80<compat,global>
        inet6 fe80::  prefixlen 10  scopeid 0x20<link>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 9087  bytes 51214341 (48.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9087  bytes 51214341 (48.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    jdebp %
  • ifconfig from (version 1.40 of) the nosh toolset
    jdebp % ifconfig -l
    enp14s0 enp15s0 lo
    jdebp % ifconfig lo
    lo
        link up loopback running
        link address 00:00:00:00:00:00 bdaddr 00:00:00:00:00:00 
        inet4 address 127.0.0.1 prefixlen 8 bdaddr 127.0.0.1 
        inet4 address 127.53.0.1 prefixlen 8 bdaddr 127.255.255.255 
        inet6 address ::2 scope 0 prefixlen 128 
        inet6 address fe80:: scope 1 prefixlen 10 
        inet6 address ::1 scope 0 prefixlen 128
    jdebp % sudo ifconfig lo inet4 127.1.0.2 alias
    jdebp % sudo ifconfig lo inet6 ::3/128 alias
    jdebp % ifconfig lo
    lo
        link up loopback running
        link address 00:00:00:00:00:00 bdaddr 00:00:00:00:00:00 
        inet4 address 127.0.0.1 prefixlen 8 bdaddr 127.0.0.1 
        inet4 address 127.1.0.2 prefixlen 32 bdaddr 127.1.0.2 
        inet4 address 127.53.0.1 prefixlen 8 bdaddr 127.255.255.255 
        inet6 address ::3 scope 0 prefixlen 128 
        inet6 address ::2 scope 0 prefixlen 128 
        inet6 address fe80:: scope 1 prefixlen 10 
        inet6 address ::1 scope 0 prefixlen 128 
    jdebp % 

As you can see, the GNU inetutils and NET-3 net-tools ifconfigs have some marked deficiencies, with respect to IPv6, with respect to interfaces that have multiple addresses, and with respect to functionality like -l.

The IPv6 problem is in part some missing code in the tools themselves. But in the main it is caused by the fact that Linux does not (as other operating systems do) provide IPv6 functionality through the ioctl() interface. It only lets programs see and manipulate IPv4 addresses through the networking ioctl()s.

Linux instead provides this functionality through a different interface, send() and recv() on a special, and somewhat odd, address family of sockets, AF_NETLINK.

The GNU and NET-3 ifconfigs could have been adjusted to use this new API. The argument against doing so was that it was not portable to other operating systems, but these programs were in practice already not portable anyway so that was not much of an argument.

But they weren't adjusted, and remain as aforeshown to this day. (Some people worked on them at various points over the years, but the improvements, sad to say, never made it into the programs. For example: Bernd Eckenfels never accepted a patch that added some netlink API capability to NET-3 net-tools ifconfig, 4 years after the patch had been written.)

Instead, some people completely reinvented the toolset as an ip command, which used the new Linux API, had a different syntax, and combined several other functions behind a fashionable command subcommand-style interface.

I needed an ifconfig that had the command-line syntax and output style of the FreeBSD ifconfig (which neither the GNU nor the NET-3 ifconfig has, and which ip most certainly does not have). So I wrote one. As proof that one could write an ifconfig that uses the netlink API on Linux, it does.

So the received wisdom about ifconfig, such as what you quote, is not really true any more. It is now untrue to say that "ifconfig does not use netlink.". The blanket that covered two does not cover three.

It has always been untrue to say that "netlink is more efficient". For the tasks that one does with ifconfig, there isn't really much in it when it comes to efficiency between the netlink API and the ioctl() API. One makes pretty much the same number of API calls for any given task.

Indeed, each API call is two system calls in the netlink case, as opposed to one in the ioctl() system. And arguably the netlink API has the disadvantage that on a heavily-used system it explicitly incorporates the possibility of the tool never receiving an acknowledgement message informing it of the result of the API call.

It is, furthermore, untrue to say that ip is "more versatile" than the GNU and NET-3 ifconfigs because it uses netlink. It is more versatile because it does more tasks, doing things in one big program that one would do with separate programs other than ifconfig. It is not more versatile simply by dint of the API that it uses internally for performing those extra tasks. There's nothing inherent to the API about this. One could write an all-in-one tool that used the FreeBSD ioctl() API, for example, and equally well state that it is "more versatile" than the individual ifconfig, route, arp, and ndp commands.

One could write route, arp, and ndp commands for Linux that used the netlink API, too.

Further reading

Related Question