Home > linux > iproute2 Crib Notes

iproute2 Crib Notes

April 10th, 2013

An aide-memoir from practicing iproute2, the utilities used to control TCP/IP networking and Linux Traffic Control

“ip link list” – shows us our links

[Daren@home Daren]$ ip link list
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100
link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff
3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10
link/ppp

“ip address” – shows us our IP addresses

[Daren@home Daren]$ ip address show
1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
2: dummy: <BROADCAST,NOARP> mtu 1500 qdisc noop
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1400 qdisc pfifo_fast qlen 100
link/ether 48:54:e8:2a:47:16 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/8 brd 10.255.255.255 scope global eth0
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100
link/ether 00:e0:4c:39:24:78 brd ff:ff:ff:ff:ff:ff
3764: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP> mtu 1492 qdisc pfifo_fast qlen 10
link/ppp
inet 10.10.0.251 peer 10.10.0.1/32 scope global ppp0

[Daren@home Daren]$ ip route show
10.10.0.1 dev ppp0 proto kernel scope link src 10.10.0.251
10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1
127.0.0.0/8 dev lo scope link
default via 10.10.0.1 dev ppp0

(For comparison and reference, this is what the old route utility displayed):

[Daren@home Daren]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use
Iface
10.10.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
10.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 eth0
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 10.10.0.1 0.0.0.0 UG 0 0 0 ppp0

ARP
You can view your machines current arp/neighbor cache/table like so:

[root@shimla /home/src/iputils]# ip neigh show
10.5.50.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
10.5.50.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable

As you can see my machine nagios1 (10.5.50.41) knows where to find filer1 (10.5.50.42) and filergateway (10.5.50.1). Now let’s add another machine to the arp cache.

[root@shimla /home/daren/.gnome-desktop]# ping -c 1 Linux-DOM0
PING Linux-DOM0.darenmatthews.com (10.5.50.43) from 10.5.50.41 : 56(84) bytes of data.
64 bytes from 10.5.50.43: icmp_seq=0 ttl=255 time=0.9 ms

— Linux-DOM0.darenmatthews.com ping statistics —
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.9/0.9/0.9 ms

[root@shimla /home/src/iputils]# ip neigh show
10.5.50.43 dev eth0 lladdr 00:06:29:21:80:20 nud reachable
10.5.50.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
10.5.50.1 dev eth0 lladdr 00:06:29:21:73:c8 nud reachable

As a result of nagios1 trying to contact Linux-DOM0, Linux-DOM0’s hardware address/location has now been added to the arp/neighbor cache. So until the entry for Linux-DOM0 times out (as a result of no communication between the two) nagios1 knows where to find Linux-DOM0 and has no need to send an ARP request.

Now let’s delete Linux-DOM0 from our arp cache:

[root@shimla /home/src/iputils]# ip neigh delete 10.5.50.43 dev eth0
[root@shimla /home/src/iputils]# ip neigh show
10.5.50.43 dev eth0 nud failed
10.5.50.42 dev eth0 lladdr 00:60:08:3f:e9:f9 nud reachable
10.5.50.1 dev eth0 lladdr 00:06:29:21:73:c8 nud stale

Now nagios1 has again forgotten where to find Linux-DOM0 and will need to send another ARP request the next time he needs to communicate with Linux-DOM0

Rules – The routing policy database

If you have a large router, you may well cater for the needs of different people, who should be served differently. The routing policy database allows you to do this by having multiple sets of routing tables. (note: If you want to use this feature, make sure that your kernel is compiled with the “IP: advanced router” and “IP: policy routing” features).

When the kernel needs to make a routing decision, it finds out which table needs to be consulted. By default, there are three tables. The old ‘route’ tool modifies the main and local tables, as does the ip tool (by default).

The default rules:

[Daren@home Daren]$ ip rule list
0: from all lookup local
32766: from all lookup main
32767: from all lookup default

This lists the priority of all rules. We see that all rules apply to all packets (‘from all’). We’ve seen the ‘main’ table before, it is output by ip route ls, but the ‘local’ and ‘default’ table are new.

If we want to do fancy things, we generate rules which point to different tables which allow us to override system wide routing rules.

For the exact semantics on what the kernel does when there are more matching rules, see Alexey’s ip-cref documentation.
4.1. Simple source policy routing

Let’s take a real example once again, I have 2 (actually 3, about time I returned them) cable modems, connected to a Linux NAT (‘masquerading’) router. People living here pay me to use the Internet. Suppose one of my house mates only visits hotmail and wants to pay less. This is fine with me, but they’ll end up using the low-end cable modem.

The ‘fast’ cable modem is known as 10.10.0.251 and is a PPP link to 10.10.0.1. The ‘slow’ cable modem is known by various ip addresses, 212.13.50.120 in this example and is a link to 192.168.99.253.

The local table:

[Daren@home Daren]$ ip route list table local
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
local 10.0.0.1 dev eth0 proto kernel scope host src 10.0.0.1
broadcast 10.0.0.0 dev eth0 proto kernel scope link src 10.0.0.1
local 10.10.0.251 dev ppp0 proto kernel scope host src 10.10.0.251
broadcast 10.255.255.255 dev eth0 proto kernel scope link src 10.0.0.1
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 212.13.50.120 dev ppp2 proto kernel scope host src 212.13.50.120
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1

Lots of obvious things, but things that need to be specified somewhere. Well, here they are. The default table is empty.

Let’s view the ‘main’ table:

[Daren@home Daren]$ ip route list table main
192.168.99.253 dev ppp2 proto kernel scope link src 212.13.50.120
10.10.0.1 dev ppp0 proto kernel scope link src 10.10.0.251
10.0.0.0/8 dev eth0 proto kernel scope link src 10.0.0.1
127.0.0.0/8 dev lo scope link
default via 10.10.0.1 dev ppp0

We now generate a new rule which we call ‘TestUser’, for our hypothetical visitor. Although we can work with pure numbers, it’s far easier if we add our tables to /etc/iproute2/rt_tables.

# echo 200 TestUser >> /etc/iproute2/rt_tables
# ip rule add from 10.0.0.10 table TestUser
# ip rule ls
0: from all lookup local
32765: from 10.0.0.10 lookup TestUser
32766: from all lookup main
32767: from all lookup default

Now all that is left is to generate TestUser’s table, and flush the route cache:

# ip route add default via 192.168.99.253 dev ppp2 table TestUser
# ip route flush cache

Categories: linux Tags:
Comments are closed.