mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Support parsing Prf field in RAs
This change prepares for a later change which actually handles the Prf field in RAs to discover default routers with preference values, as per RFC 4191. Updates #6172. Test: header_test.TestNDPRouterAdvert PiperOrigin-RevId: 379421710
This commit is contained in:
committed by
gVisor bot
parent
bccc446154
commit
3a8ba8ed9d
@@ -19,12 +19,72 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// NDPRoutePreference is the preference values for default routers or
|
||||
// more-specific routes.
|
||||
//
|
||||
// As per RFC 4191 section 2.1,
|
||||
//
|
||||
// Default router preferences and preferences for more-specific routes
|
||||
// are encoded the same way.
|
||||
//
|
||||
// Preference values are encoded as a two-bit signed integer, as
|
||||
// follows:
|
||||
//
|
||||
// 01 High
|
||||
// 00 Medium (default)
|
||||
// 11 Low
|
||||
// 10 Reserved - MUST NOT be sent
|
||||
//
|
||||
// Note that implementations can treat the value as a two-bit signed
|
||||
// integer.
|
||||
//
|
||||
// Having just three values reinforces that they are not metrics and
|
||||
// more values do not appear to be necessary for reasonable scenarios.
|
||||
type NDPRoutePreference uint8
|
||||
|
||||
const (
|
||||
// HighRoutePreference indicates a high preference, as per
|
||||
// RFC 4191 section 2.1.
|
||||
HighRoutePreference NDPRoutePreference = 0b01
|
||||
|
||||
// MediumRoutePreference indicates a medium preference, as per
|
||||
// RFC 4191 section 2.1.
|
||||
//
|
||||
// This is the default preference value.
|
||||
MediumRoutePreference = 0b00
|
||||
|
||||
// LowRoutePreference indicates a low preference, as per
|
||||
// RFC 4191 section 2.1.
|
||||
LowRoutePreference = 0b11
|
||||
|
||||
// ReservedRoutePreference is a reserved preference value, as per
|
||||
// RFC 4191 section 2.1.
|
||||
//
|
||||
// It MUST NOT be sent.
|
||||
ReservedRoutePreference = 0b10
|
||||
)
|
||||
|
||||
// NDPRouterAdvert is an NDP Router Advertisement message. It will only contain
|
||||
// the body of an ICMPv6 packet.
|
||||
//
|
||||
// See RFC 4861 section 4.2 for more details.
|
||||
// See RFC 4861 section 4.2 and RFC 4191 section 2.2 for more details.
|
||||
type NDPRouterAdvert []byte
|
||||
|
||||
// As per RFC 4191 section 2.2,
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Type | Code | Checksum |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Cur Hop Limit |M|O|H|Prf|Resvd| Router Lifetime |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Reachable Time |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Retrans Timer |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Options ...
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-
|
||||
const (
|
||||
// NDPRAMinimumSize is the minimum size of a valid NDP Router
|
||||
// Advertisement message (body of an ICMPv6 packet).
|
||||
@@ -47,6 +107,14 @@ const (
|
||||
// within the bit-field/flags byte of an NDPRouterAdvert.
|
||||
ndpRAOtherConfFlagMask = (1 << 6)
|
||||
|
||||
// ndpDefaultRouterPreferenceShift is the shift of the Prf (Default Router
|
||||
// Preference) field within the flags byte of an NDPRouterAdvert.
|
||||
ndpDefaultRouterPreferenceShift = 3
|
||||
|
||||
// ndpDefaultRouterPreferenceMask is the mask of the Prf (Default Router
|
||||
// Preference) field within the flags byte of an NDPRouterAdvert.
|
||||
ndpDefaultRouterPreferenceMask = (0b11 << ndpDefaultRouterPreferenceShift)
|
||||
|
||||
// ndpRARouterLifetimeOffset is the start of the 2-byte Router Lifetime
|
||||
// field within an NDPRouterAdvert.
|
||||
ndpRARouterLifetimeOffset = 2
|
||||
@@ -80,6 +148,11 @@ func (b NDPRouterAdvert) OtherConfFlag() bool {
|
||||
return b[ndpRAFlagsOffset]&ndpRAOtherConfFlagMask != 0
|
||||
}
|
||||
|
||||
// DefaultRouterPreference returns the Default Router Preference field.
|
||||
func (b NDPRouterAdvert) DefaultRouterPreference() NDPRoutePreference {
|
||||
return NDPRoutePreference((b[ndpRAFlagsOffset] & ndpDefaultRouterPreferenceMask) >> ndpDefaultRouterPreferenceShift)
|
||||
}
|
||||
|
||||
// RouterLifetime returns the lifetime associated with the default router. A
|
||||
// value of 0 means the source of the Router Advertisement is not a default
|
||||
// router and SHOULD NOT appear on the default router list. Note, a value of 0
|
||||
|
||||
@@ -126,36 +126,83 @@ func TestNDPNeighborAdvert(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNDPRouterAdvert(t *testing.T) {
|
||||
b := []byte{
|
||||
64, 128, 1, 2,
|
||||
3, 4, 5, 6,
|
||||
7, 8, 9, 10,
|
||||
tests := []struct {
|
||||
hopLimit uint8
|
||||
managedFlag, otherConfFlag bool
|
||||
prf NDPRoutePreference
|
||||
routerLifetimeS uint16
|
||||
reachableTimeMS, retransTimerMS uint32
|
||||
}{
|
||||
{
|
||||
hopLimit: 1,
|
||||
managedFlag: false,
|
||||
otherConfFlag: true,
|
||||
prf: HighRoutePreference,
|
||||
routerLifetimeS: 2,
|
||||
reachableTimeMS: 3,
|
||||
retransTimerMS: 4,
|
||||
},
|
||||
{
|
||||
hopLimit: 64,
|
||||
managedFlag: true,
|
||||
otherConfFlag: false,
|
||||
prf: LowRoutePreference,
|
||||
routerLifetimeS: 258,
|
||||
reachableTimeMS: 78492,
|
||||
retransTimerMS: 13213,
|
||||
},
|
||||
}
|
||||
|
||||
ra := NDPRouterAdvert(b)
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
flags := uint8(0)
|
||||
if test.managedFlag {
|
||||
flags |= 1 << 7
|
||||
}
|
||||
if test.otherConfFlag {
|
||||
flags |= 1 << 6
|
||||
}
|
||||
flags |= uint8(test.prf) << 3
|
||||
|
||||
if got := ra.CurrHopLimit(); got != 64 {
|
||||
t.Errorf("got ra.CurrHopLimit = %d, want = 64", got)
|
||||
}
|
||||
b := []byte{
|
||||
test.hopLimit, flags, 1, 2,
|
||||
3, 4, 5, 6,
|
||||
7, 8, 9, 10,
|
||||
}
|
||||
binary.BigEndian.PutUint16(b[2:], test.routerLifetimeS)
|
||||
binary.BigEndian.PutUint32(b[4:], test.reachableTimeMS)
|
||||
binary.BigEndian.PutUint32(b[8:], test.retransTimerMS)
|
||||
|
||||
if got := ra.ManagedAddrConfFlag(); !got {
|
||||
t.Errorf("got ManagedAddrConfFlag = false, want = true")
|
||||
}
|
||||
ra := NDPRouterAdvert(b)
|
||||
|
||||
if got := ra.OtherConfFlag(); got {
|
||||
t.Errorf("got OtherConfFlag = true, want = false")
|
||||
}
|
||||
if got := ra.CurrHopLimit(); got != test.hopLimit {
|
||||
t.Errorf("got ra.CurrHopLimit() = %d, want = %d", got, test.hopLimit)
|
||||
}
|
||||
|
||||
if got, want := ra.RouterLifetime(), time.Second*258; got != want {
|
||||
t.Errorf("got ra.RouterLifetime = %d, want = %d", got, want)
|
||||
}
|
||||
if got := ra.ManagedAddrConfFlag(); got != test.managedFlag {
|
||||
t.Errorf("got ManagedAddrConfFlag() = %t, want = %t", got, test.managedFlag)
|
||||
}
|
||||
|
||||
if got, want := ra.ReachableTime(), time.Millisecond*50595078; got != want {
|
||||
t.Errorf("got ra.ReachableTime = %d, want = %d", got, want)
|
||||
}
|
||||
if got := ra.OtherConfFlag(); got != test.otherConfFlag {
|
||||
t.Errorf("got OtherConfFlag() = %t, want = %t", got, test.otherConfFlag)
|
||||
}
|
||||
|
||||
if got, want := ra.RetransTimer(), time.Millisecond*117967114; got != want {
|
||||
t.Errorf("got ra.RetransTimer = %d, want = %d", got, want)
|
||||
if got := ra.DefaultRouterPreference(); got != test.prf {
|
||||
t.Errorf("got DefaultRouterPreference() = %d, want = %d", got, test.prf)
|
||||
}
|
||||
|
||||
if got, want := ra.RouterLifetime(), time.Second*time.Duration(test.routerLifetimeS); got != want {
|
||||
t.Errorf("got ra.RouterLifetime() = %d, want = %d", got, want)
|
||||
}
|
||||
|
||||
if got, want := ra.ReachableTime(), time.Millisecond*time.Duration(test.reachableTimeMS); got != want {
|
||||
t.Errorf("got ra.ReachableTime() = %d, want = %d", got, want)
|
||||
}
|
||||
|
||||
if got, want := ra.RetransTimer(), time.Millisecond*time.Duration(test.retransTimerMS); got != want {
|
||||
t.Errorf("got ra.RetransTimer() = %d, want = %d", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user