37

I need to know how to list the IDs of all route tables. For example, I can run:

ip rule add fwmark 2 table 104
ip route add dev eth0 default via 192.168.3.7 table 104

A call to ip rule list shows:

0:  from all lookup local 
32765:  from all fwmark 0x2 lookup 104 
32766:  from all lookup main 
32767:  from all lookup default

And a call to ip route show table 104 shows:

default via 192.168.3.7 dev eth0

If I then call ip rule del table 104, a subsequent call to ip rule list shows:

0:  from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default

However, a call to ip route show table 104 still shows:

default via 192.168.3.7 dev eth0

I know that I can flush the table using ip route flush table 104. I'd like to be able to flush all tables that are not local, main, and default. Thus I want to be able to list the existing tables.

I've seen people use cat /etc/iproute2/rt_tables, but that only produces:

#
# reserved values
#
255 local
254 main
253 default
0   unspec
#
# local
#
#1  inr.ruhep

What can I do to get all the table names that currently exist? Thanks in advance!

4 Answers 4

54

There exists a way to list all routing entries of all tables. ip route show table all

Using some shell piping magic, you can extract all table names and IDs like this:

ip route show table all | grep "table" | sed 's/.*\(table.*\)/\1/g' | awk '{print $2}' | sort | uniq

or

ip route show table all | grep -Po 'table \K[^\s]+' | sort -u

If you only care about the numeric table names, add some grep filtering:

ip route show table all | grep "table" | sed 's/.*\(table.*\)/\1/g' | awk '{print $2}' | sort | uniq | grep -e "[0-9]"

or

ip route show table all | grep -Po 'table \K[^\s]+' | sort -u | grep -e "[0-9]"
2
  • 1
    use "ip -d route show table all | xxxxx" or "ip -d -N route show table all | xxxxx" is better. Otherwise will lost the main route table. -d, -details Output more detailed information. -N, -Numeric Print the number of protocol, scope, dsfield, etc directly instead of converting it to human readable name.
    – tinyhare
    Jun 24, 2022 at 6:13
  • This mostly works, the MASQUERADE step described in the accepted (but also almost the top) answer from serverfault.com/questions/345111/… is also required.
    – foxx1337
    May 7, 2023 at 10:48
8

What can I do to get all the table names that currently exist?

The file /etc/iproute2/rt_tables is the only source of table names on the system. Internally, routing tables have integer identifiers.

The rest of your question is a bit confusing. If a table is not referenced by a rule, then it is effectively "deleted" because it has no impact on the routing of the system. So you can list all the active routing tables like this:

ip rule list | awk '/lookup/ {print $NF}'

That looks for all lookup action in the routing rules and prints the target.

It looks like routing table are identified by a 64 bit integer. If you really, really wanted to find all routing tables with rules, even the inactive ones that have no impact on your system, you could simple iterate a loop from 1 to 2^64:

seq 0 $(echo '2 64 ^ p' | dc) | xargs -iTABLE sh -c 'echo === TABLE ===; ip route show table TABLE'

...but this will take forever and ever, because 64 bits covers a lot of space.

1
  • 1
    While a table not correlated with rule doesn't get used, it doesn't mean it is "deleted". It still consumes system resources. And yes, looping through 2^64 values is crazy!
    – nic
    Aug 8, 2014 at 16:28
7
(egrep '^\s*[0-9]' /etc/iproute2/rt_tables | awk '{print $2}' | sort -u; ip rule list | awk '/lookup/ {print $NF}' | sort -u; ip route show table all | sed 's/.*\(table.*\)/\1/g' | awk '{if($0 ~ /table/) print $2; else print "main";}' | sort -u) | sort | uniq -c

Gratitude for this thread leading to this combo that shows all the routing tables that currently contain routes, that are referenced by rules, and that are named, with a 3 next to each table that has content, is referenced, and is named or a 2 or a 1 if one or two of the three conditions apply.

1

Here is a script I made based on the info I gathered from this thread. It works on my old Note 5 running Marshmallow 6.0.1 (set up to be easily copy/pasted into an adb shell terminal running su)

# Tested on Samsung Galaxy Note5 running Android Marshmallow 6.0.1 - needs root and termux app installed
# Must be run as root
# Termux app must be installed so column will work. This first line adds termux to the search path for the current console session - probably not necessary if you are typing all this into the termux app on the device
export PATH=$PATH:/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/bin/applets; export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib; \
echo -e "\nRouting table names and where they are present and populated:"; (echo "Table Name,\"ip rule list\",\"ip route show table <name>\",\"/data/misc/net/rt_tables\""; (egrep '^\s*[0-9]' /data/misc/net/rt_tables | awk '{print $2 ",file"}' | sort -u; ip rule list | awk '/lookup/ {print $NF ",rule"}' | sort -u; ip route show table all | sed 's/.*\(table.*\)/\1/g' | awk '{{if($0 ~ /table/) printf $2; else printf "main";}; print ",route"}' | sort -u) | sort | awk 'BEGIN{FS=","} {dnames[$1]=1; if($2=="file"){dfile[$1]=1}; if($2=="rule"){drule[$1]=1}; if($2=="route"){droute[$1]=1};} END {for (name in dnames) {printf name; printf "," ; if(drule[name]==1){printf "rule"}; printf "," ; if(droute[name]==1){printf "route"}; printf "," ; if(dfile[name]==1){printf "file"};print "" }}' |sort )| column -t -s',' -o' | '

Output looks like this:

Routing table names and where they are present and populated:
Table Name     | "ip rule list" | "ip route show table <name>" | "/data/misc/net/rt_tables"
0              |                | route                        | 
1              | rule           | route                        | 
61             | rule           | route                        | 
legacy_network | rule           |                              | file
legacy_system  | rule           | route                        | file
local          | rule           | route                        | file
local_network  | rule           | route                        | file
main           | rule           | route                        | file
rmnet0         | rule           | route                        | file
rmnet1         | rule           | route                        | file

Here is the same script for CentOS 7:

# Tested on CentOS 7
echo -e "\nRouting table names and where they are present and populated:"; (echo "Table Name,\"ip rule list\",\"ip route show table <name>\",\"/etc/iproute2/rt_tables\""; (egrep '^\s*[0-9]' /etc/iproute2/rt_tables | awk '{print $2 ",file"}' | sort -u; ip rule list | awk '/lookup/ {print $NF ",rule"}' | sort -u; ip route show table all | sed 's/.*\(table.*\)/\1/g' | awk '{{if($0 ~ /table/) printf $2; else printf "main";}; print ",route"}' | sort -u) | sort | awk 'BEGIN{FS=","} {dnames[$1]=1; if($2=="file"){dfile[$1]=1}; if($2=="rule"){drule[$1]=1}; if($2=="route"){droute[$1]=1};} END {for (name in dnames) {printf name; printf "," ; if(drule[name]==1){printf "rule"}; printf "," ; if(droute[name]==1){printf "route"}; printf "," ; if(dfile[name]==1){printf "file"};print "" }}' |sort )| column -t -s',' -o' | '

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .