Add support for MTU Lock

When adding a route with "mtu lock <mtu>" path MTU discovery (PMTUD)
will not be tried and packets will be sent without DF bit set. Upon
receiving an ICMP needs frag due to PMTUD, the kernel will not install a
cached route and lower the MTU.

Signed-off-by: Tim Rozet <trozet@redhat.com>
This commit is contained in:
Tim Rozet
2025-03-25 21:52:00 -04:00
committed by Alessandro Boch
parent 0e7078ed04
commit 9b61d26766
3 changed files with 66 additions and 1 deletions

View File

@@ -45,7 +45,7 @@ type Encap interface {
Equal(Encap) bool
}
//Protocol describe what was the originator of the route
// Protocol describe what was the originator of the route
type RouteProtocol int
// Route represents a netlink route.
@@ -70,6 +70,7 @@ type Route struct {
Via Destination
Realm int
MTU int
MTULock bool
Window int
Rtt int
RttVar int

View File

@@ -1072,6 +1072,10 @@ func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.R
if route.MTU > 0 {
b := nl.Uint32Attr(uint32(route.MTU))
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
if route.MTULock {
b := nl.Uint32Attr(uint32(1 << unix.RTAX_MTU))
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_LOCK, b))
}
}
if route.Window > 0 {
b := nl.Uint32Attr(uint32(route.Window))
@@ -1440,6 +1444,8 @@ func deserializeRoute(m []byte) (Route, error) {
switch metric.Attr.Type {
case unix.RTAX_MTU:
route.MTU = int(native.Uint32(metric.Value[0:4]))
case unix.RTAX_LOCK:
route.MTULock = native.Uint32(metric.Value[0:4]) == uint32(1<<unix.RTAX_MTU)
case unix.RTAX_WINDOW:
route.Window = int(native.Uint32(metric.Value[0:4]))
case unix.RTAX_RTT:

View File

@@ -2260,6 +2260,64 @@ func TestMTURouteAddDel(t *testing.T) {
}
}
func TestMTULockRouteAddDel(t *testing.T) {
_, err := RouteList(nil, FAMILY_V4)
if err != nil {
t.Fatal(err)
}
tearDown := setUpNetlinkTest(t)
defer tearDown()
// get loopback interface
link, err := LinkByName("lo")
if err != nil {
t.Fatal(err)
}
// bring the interface up
if err := LinkSetUp(link); err != nil {
t.Fatal(err)
}
// add a gateway route
dst := &net.IPNet{
IP: net.IPv4(192, 168, 0, 0),
Mask: net.CIDRMask(24, 32),
}
route := Route{LinkIndex: link.Attrs().Index, Dst: dst, MTU: 500, MTULock: true}
if err := RouteAdd(&route); err != nil {
t.Fatal(err)
}
routes, err := RouteList(link, FAMILY_V4)
if err != nil {
t.Fatal(err)
}
if len(routes) != 1 {
t.Fatal("Route not added properly")
}
if route.MTU != routes[0].MTU {
t.Fatal("Route MTU not set properly")
}
if route.MTULock != routes[0].MTULock {
t.Fatal("Route MTU lock not set properly")
}
if err := RouteDel(&route); err != nil {
t.Fatal(err)
}
routes, err = RouteList(link, FAMILY_V4)
if err != nil {
t.Fatal(err)
}
if len(routes) != 0 {
t.Fatal("Route not removed properly")
}
}
func TestRouteViaAddDel(t *testing.T) {
minKernelRequired(t, 5, 4)
tearDown := setUpNetlinkTest(t)