cgnat-demo/fix-vrf-rules.sh

62 lines
2.0 KiB
Bash
Executable File

#!/bin/sh
# Creating a VRF on linux (like `ip link add vrf_foobar type vrf table 10`) automatically inserts a
# `l3mdev` rule (both IPv4 and IPv6) with preference 1000 by default.
#
# Sadly this means that the `lookup local` with preference 0 (the table `local` containing your
# addresses in the "default VRF") is queried before that, which breaks routing of packets from a
# VRF to your non-VRF addresses.
#
# So you actually want the `l3mdev` rule before the `lookup local` rule, and this script helps with
# that.
#
# Your VRF routing table usually is contained completely in the table you specified when creating
# the VRF; this script also creates an "pref 2000 l3mdev unreachable" rule to make sure within VRFs
# no routes "outside" the VRF are used. (As an alternative you could add `unreachable default
# metric 4278198272` routes in both IPv4 and IPv6 VRF tables).
#
# This should still leave enough room to add policy-based routing rules if you need them.
#
# Also see `vrf_prepare()` and `vrf_create()` in linux kernel
# source:tools/testing/selftests/net/forwarding/lib.sh
set -e
has_rule() {
if [ -n "$(ip $family rule list "$@")" ]; then
# echo "Have: ip $family rule $*"
return 0
else
# echo "Have not: ip $family rule $*"
return 1
fi
}
rule() {
# echo "Running: ip $family rule $*"
ip $family rule "$@"
}
run() {
# move lookup local to pref 32765 (from 0)
if ! has_rule pref 32765 lookup local; then
rule add pref 32765 lookup local
fi
if has_rule pref 0 lookup local; then
rule del pref 0 lookup local
fi
# make sure that in VRFs after failed lookup in the VRF specific table nothing else is reached
if ! has_rule pref 1000 l3mdev; then
# this should be added by the kernel when a VRF is created; add it here for completeness
rule add pref 1000 l3mdev protocol kernel
fi
if ! has_rule pref 2000 l3mdev; then # can't search for actions; so can't make sure this is actually using "unreachable"
rule add pref 2000 l3mdev unreachable
fi
}
family=-4
run
family=-6
run