rtnetlink: add RouteMetrics nested attributes within RouteAttributes (#81)

Signed-off-by: Matt Layher <mlayher@fastly.com>
This commit is contained in:
Matt Layher 2020-10-02 10:52:24 -04:00 committed by GitHub
parent d699427278
commit 4e9cdead09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 9 deletions

1
go.mod
View File

@ -3,6 +3,7 @@ module github.com/jsimonetti/rtnetlink
go 1.12
require (
github.com/google/go-cmp v0.5.2
github.com/mdlayher/netlink v1.1.0
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5
)

2
go.sum
View File

@ -2,6 +2,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=

View File

@ -72,6 +72,11 @@ const (
RTA_TABLE = linux.RTA_TABLE
RTA_MARK = linux.RTA_MARK
RTA_EXPIRES = linux.RTA_EXPIRES
RTA_METRICS = linux.RTA_METRICS
RTAX_ADVMSS = linux.RTAX_ADVMSS
RTAX_FEATURES = linux.RTAX_FEATURES
RTAX_INITCWND = linux.RTAX_INITCWND
RTAX_MTU = linux.RTAX_MTU
NTF_PROXY = linux.NTF_PROXY
RTN_UNICAST = linux.RTN_UNICAST
RT_TABLE_MAIN = linux.RT_TABLE_MAIN

View File

@ -68,6 +68,11 @@ const (
RTA_TABLE = 0xf
RTA_MARK = 0x10
RTA_EXPIRES = 0x17
RTA_METRICS = 0x8
RTAX_ADVMSS = 0x8
RTAX_FEATURES = 0xc
RTAX_INITCWND = 0xb
RTAX_MTU = 0x2
NTF_PROXY = 0x8
RTN_UNICAST = 0x1
RT_TABLE_MAIN = 0xfe

View File

@ -178,6 +178,7 @@ type RouteAttributes struct {
Table uint32
Mark uint32
Expires *uint32
Metrics *RouteMetrics
}
func (a *RouteAttributes) decode(ad *netlink.AttributeDecoder) error {
@ -215,10 +216,13 @@ func (a *RouteAttributes) decode(ad *netlink.AttributeDecoder) error {
case unix.RTA_EXPIRES:
timeout := ad.Uint32()
a.Expires = &timeout
case unix.RTA_METRICS:
a.Metrics = &RouteMetrics{}
ad.Nested(a.Metrics.decode)
}
}
return nil
return ad.Err()
}
func (a *RouteAttributes) encode(ae *netlink.AttributeEncoder) error {
@ -273,5 +277,54 @@ func (a *RouteAttributes) encode(ae *netlink.AttributeEncoder) error {
ae.Uint32(unix.RTA_EXPIRES, *a.Expires)
}
if a.Metrics != nil {
ae.Nested(unix.RTA_METRICS, a.Metrics.encode)
}
return nil
}
type RouteMetrics struct {
AdvMSS uint32
Features uint32
InitCwnd uint32
MTU uint32
}
func (rm *RouteMetrics) decode(ad *netlink.AttributeDecoder) error {
for ad.Next() {
switch ad.Type() {
case unix.RTAX_ADVMSS:
rm.AdvMSS = ad.Uint32()
case unix.RTAX_FEATURES:
rm.Features = ad.Uint32()
case unix.RTAX_INITCWND:
rm.InitCwnd = ad.Uint32()
case unix.RTAX_MTU:
rm.MTU = ad.Uint32()
}
}
// ad.Err call handled by Nested method in calling attribute decoder.
return nil
}
func (rm *RouteMetrics) encode(ae *netlink.AttributeEncoder) error {
if rm.AdvMSS != 0 {
ae.Uint32(unix.RTAX_ADVMSS, rm.AdvMSS)
}
if rm.Features != 0 {
ae.Uint32(unix.RTAX_FEATURES, rm.Features)
}
if rm.InitCwnd != 0 {
ae.Uint32(unix.RTAX_INITCWND, rm.InitCwnd)
}
if rm.MTU != 0 {
ae.Uint32(unix.RTAX_MTU, rm.MTU)
}
return nil
}

View File

@ -1,11 +1,10 @@
package rtnetlink
import (
"bytes"
"net"
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/jsimonetti/rtnetlink/internal/unix"
)
@ -49,6 +48,9 @@ func TestRouteMessageMarshalBinary(t *testing.T) {
Gateway: net.ParseIP("10.10.10.10"),
OutIface: 4,
Expires: &timeout,
Metrics: &RouteMetrics{
MTU: 1500,
},
},
},
b: []byte{
@ -57,7 +59,8 @@ func TestRouteMessageMarshalBinary(t *testing.T) {
0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
0x0a, 0x0a, 0x0a, 0x0a, 0x08, 0x00, 0x04, 0x00,
0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00,
0xff, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x80,
0x08, 0x00, 0x02, 0x00, 0xdc, 0x05, 0x00, 0x00,
},
},
}
@ -73,8 +76,8 @@ func TestRouteMessageMarshalBinary(t *testing.T) {
return
}
if want, got := tt.b, b; !bytes.Equal(want, got) {
t.Fatalf("unexpected Message bytes:\n- want: [%# x]\n- got: [%# x]", want, got)
if diff := cmp.Diff(tt.b, b); diff != "" {
t.Fatalf("unexpected RouteMessage bytes (-want +got):\n%s", diff)
}
})
}
@ -121,7 +124,8 @@ func TestRouteMessageUnmarshalBinary(t *testing.T) {
0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00,
0x0a, 0x64, 0x0a, 0x01, 0x08, 0x00, 0x04, 0x00,
0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00,
0xe8, 0x03, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x80,
0x08, 0x00, 0x02, 0x00, 0xdc, 0x05, 0x00, 0x00,
},
m: &RouteMessage{
Family: 2,
@ -135,6 +139,9 @@ func TestRouteMessageUnmarshalBinary(t *testing.T) {
Src: net.IP{0x0a, 0x64, 0x0a, 0x01},
OutIface: 5,
Expires: &timeout,
Metrics: &RouteMetrics{
MTU: 1500,
},
},
},
},
@ -152,8 +159,8 @@ func TestRouteMessageUnmarshalBinary(t *testing.T) {
return
}
if want, got := tt.m, m; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Message:\n- want: %#v\n- got: %#v", want, got)
if diff := cmp.Diff(tt.m, m); diff != "" {
t.Fatalf("unexpected RouteMessage (-want +got):\n%s", diff)
}
})
}