Support setting and retrieving route MTU/AdvMSS

This commit is contained in:
Vishvananda Ishaya Abrams 2017-11-09 12:28:25 -08:00
parent f7e518d6f0
commit 63ca7e48f5
4 changed files with 93 additions and 0 deletions

View File

@ -278,6 +278,11 @@ func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
return attr
}
// AddChild adds an existing RtAttr as a child.
func (a *RtAttr) AddChild(attr *RtAttr) {
a.children = append(a.children, attr)
}
func (a *RtAttr) Len() int {
if len(a.children) == 0 {
return (unix.SizeofRtAttr + len(a.Data))

View File

@ -45,6 +45,8 @@ type Route struct {
MPLSDst *int
NewDst Destination
Encap Encap
MTU int
AdvMSS int
}
func (r Route) String() string {

View File

@ -454,6 +454,25 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
msg.Type = uint8(route.Type)
}
var metrics []*nl.RtAttr
// TODO: support other rta_metric values
if route.MTU > 0 {
b := nl.Uint32Attr(uint32(route.MTU))
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b))
}
if route.AdvMSS > 0 {
b := nl.Uint32Attr(uint32(route.AdvMSS))
metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b))
}
if metrics != nil {
attr := nl.NewRtAttr(unix.RTA_METRICS, nil)
for _, metric := range metrics {
attr.AddChild(metric)
}
rtAttrs = append(rtAttrs, attr)
}
msg.Flags = uint32(route.Flags)
msg.Scope = uint8(route.Scope)
msg.Family = uint8(family)
@ -685,6 +704,19 @@ func deserializeRoute(m []byte) (Route, error) {
encapType = attr
case nl.RTA_ENCAP:
encap = attr
case unix.RTA_METRICS:
metrics, err := nl.ParseRouteAttr(attr.Value)
if err != nil {
return route, err
}
for _, metric := range metrics {
switch metric.Attr.Type {
case unix.RTAX_MTU:
route.MTU = int(native.Uint32(metric.Value[0:4]))
case unix.RTAX_ADVMSS:
route.AdvMSS = int(native.Uint32(metric.Value[0:4]))
}
}
}
}

View File

@ -904,3 +904,57 @@ func TestSEG6RouteAddDel(t *testing.T) {
t.Fatal("SEG6 routes not removed properly")
}
}
func TestMTURouteAddDel(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}
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 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")
}
}