“Understanding Genmask vs Netmask: Routing Table Mask Naming Conventions in Linux”


3 views


When examining Linux routing tables with route -n, you'll encounter the term "Genmask" instead of the more familiar "netmask". This isn't a typo - it's a deliberate design choice dating back to early Unix implementations.

The term "Genmask" stands for "generation mask", a legacy term from BSD-derived networking code. Early routing implementations used this terminology to:

  • Differentiate between interface netmasks and routing masks
  • Handle classful routing (pre-CIDR era)
  • Support route generation algorithms

Functionally, Genmask and netmask serve identical purposes in modern Linux routing tables:

# Compare these functionally identical commands:
route -n
ip route show table all

# Sample output demonstrating equivalence:
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.5
10.0.0.0     0.0.0.0     255.255.255.0   U     0      0        0 eth0

The variance appears in different tools:

Tool Term Used
route -n Genmask
ip route Prefix Length
ifconfig Netmask
netstat -rn Genmask

When writing scripts that parse routing information, you need to handle both formats:

# Bash example handling both formats
get_netmask() {
    if [[ "$1" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        echo "$1"  # Genmask/netmask format
    else
        # Convert prefix length to netmask
        perl -MSocket -e 'print inet_ntoa(pack("N", 0xffffffff << (32-$ARGV[0])))' "$1"
    fi
}

Current Linux distributions using iproute2 tools have largely standardized on CIDR notation:

# Preferred modern syntax
ip route add 192.168.1.0/24 via 10.0.0.1

# Legacy equivalent
route add -net 192.168.1.0 netmask 255.255.255.0 gw 10.0.0.1

The "Genmask" terminology persists in legacy tools for backward compatibility, but modern implementations should use ip command instead of route.


When examining Linux routing tables using route -n, you'll encounter the term "Genmask" instead of the more familiar "netmask" found elsewhere in networking. This column header has puzzled many system administrators and network engineers over the years.

The term "Genmask" is actually shorthand for "generation mask," a concept rooted in early Unix networking implementations. The BSD-derived networking stack in Linux maintains this terminology for backward compatibility. While functionally identical to a netmask, the name reflects its original purpose in route generation.

Here's how the kernel actually processes these values in the routing table:

struct rtable {
    struct dst_entry dst;
    int rt_genid;
    unsigned rt_flags;
    __be32 rt_gateway;
    /* The mask we actually use for route lookup */
    __be32 rt_genmask;
    /* Original netmask for the route */
    __be32 rt_netmask;
};

Let's examine some common routing scenarios:

# Default route with 0.0.0.0 genmask
Destination: 0.0.0.0
Gateway:     192.168.1.1
Genmask:     0.0.0.0

# Local network route
Destination: 192.168.1.0  
Gateway:     0.0.0.0
Genmask:     255.255.255.0

# Host-specific route
Destination: 10.0.0.5
Gateway:     0.0.0.0  
Genmask:     255.255.255.255

Newer tools like ip route have standardized on "netmask" terminology:

$ ip route show
default via 10.0.0.1 dev eth0 
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2

The CIDR notation (like /24) makes the netmask concept even clearer in modern implementations.

While Genmask and netmask serve the same purpose in route selection, understanding this terminology helps when:

  • Debugging legacy systems
  • Interpreting older documentation
  • Writing cross-version compatible scripts

Here's a Python example that parses both formats:

import re
import ipaddress

def parse_route_line(line):
    if line.startswith('0.0.0.0'):
        # Handle default route
        parts = line.split()
        return {
            'destination': parts[0],
            'gateway': parts[1],
            'genmask': parts[2],
            'netmask': parts[2]  # Aliased
        }
    elif '/' in line:
        # Handle CIDR notation
        net = ipaddress.ip_network(line.split()[0])
        return {
            'destination': str(net.network_address),
            'netmask': str(net.netmask),
            'genmask': str(net.netmask)
        }