From 9524f266ba835806c7589e4a9fed342062828d8c Mon Sep 17 00:00:00 2001 From: Adrian-Stefan Mares Date: Thu, 29 Feb 2024 20:41:14 +0100 Subject: [PATCH] ns: Add NbTrans per data rate index overrides --- CHANGELOG.md | 2 + pkg/networkserver/grpc_deviceregistry.go | 137 ++++++++++++++++++++--- pkg/networkserver/mac/adr.go | 63 ++++++++++- pkg/networkserver/mac/adr_test.go | 63 ++++++++++- 4 files changed, 244 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5754130f5..c53399688c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ For details about compatibility between different releases, see the **Commitment ### Added +- Fine grained NbTrans overrides for the dynamic ADR mode. See the `--mac-settings.adr.mode.dynamic.overrides.data-rate-[index].min-nb-trans` and `--mac-settings.adr.mode.dynamic.overrides.data-rate-[index].max-nb-trans` family of parameters. + ### Changed ### Deprecated diff --git a/pkg/networkserver/grpc_deviceregistry.go b/pkg/networkserver/grpc_deviceregistry.go index 1052fae03f..756ca39e4c 100644 --- a/pkg/networkserver/grpc_deviceregistry.go +++ b/pkg/networkserver/grpc_deviceregistry.go @@ -1149,6 +1149,55 @@ var ( "mac_settings.adr.mode.dynamic.min_data_rate_index", "mac_settings.adr.mode.dynamic.min_nb_trans", "mac_settings.adr.mode.dynamic.min_tx_power_index", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9", + "mac_settings.adr.mode.dynamic.overrides", "mac_settings.adr.mode.dynamic", "mac_settings.adr.mode.static.data_rate_index", "mac_settings.adr.mode.static.nb_trans", @@ -1170,6 +1219,38 @@ var ( "mac_settings.adr.mode.dynamic.min_data_rate_index.value", "mac_settings.adr.mode.dynamic.min_nb_trans", "mac_settings.adr.mode.dynamic.min_tx_power_index", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.min_nb_trans", "mac_settings.adr.mode.dynamic", } ) @@ -1426,27 +1507,12 @@ func (ns *NetworkServer) Set(ctx context.Context, req *ttnpb.SetEndDeviceRequest if st.HasSetField( "frequency_plan_id", "lorawan_phy_version", - "mac_settings.adr.mode.disabled", - "mac_settings.adr.mode.dynamic.channel_steering.mode.disabled", - "mac_settings.adr.mode.dynamic.channel_steering.mode.lora_narrow", - "mac_settings.adr.mode.dynamic.channel_steering.mode", - "mac_settings.adr.mode.dynamic.channel_steering", - "mac_settings.adr.mode.dynamic.margin", "mac_settings.adr.mode.dynamic.max_data_rate_index.value", - "mac_settings.adr.mode.dynamic.max_data_rate_index", - "mac_settings.adr.mode.dynamic.max_nb_trans", "mac_settings.adr.mode.dynamic.max_tx_power_index", "mac_settings.adr.mode.dynamic.min_data_rate_index.value", - "mac_settings.adr.mode.dynamic.min_data_rate_index", - "mac_settings.adr.mode.dynamic.min_nb_trans", "mac_settings.adr.mode.dynamic.min_tx_power_index", - "mac_settings.adr.mode.dynamic", "mac_settings.adr.mode.static.data_rate_index", - "mac_settings.adr.mode.static.nb_trans", "mac_settings.adr.mode.static.tx_power_index", - "mac_settings.adr.mode.static", - "mac_settings.adr.mode", - "mac_settings.adr", "mac_settings.desired_ping_slot_data_rate_index.value", "mac_settings.desired_relay.mode.served.second_channel.data_rate_index", "mac_settings.desired_relay.mode.serving.default_channel_index", @@ -2496,6 +2562,15 @@ func (ns *NetworkServer) Set(ctx context.Context, req *ttnpb.SetEndDeviceRequest return false, "mac_settings.adr.mode.dynamic.max_nb_trans" } } + for drIdx := ttnpb.DataRateIndex_DATA_RATE_0; drIdx <= ttnpb.DataRateIndex_DATA_RATE_15; drIdx++ { + baseField := fmt.Sprintf("mac_settings.adr.mode.dynamic.overrides.data_rate_%d.", drIdx) + min := mac.DataRateIndexOverridesOf(m[baseField+"min_nb_trans"].GetMacSettings().GetAdr().GetDynamic().GetOverrides(), drIdx).GetMinNbTrans() // nolint: lll + max := mac.DataRateIndexOverridesOf(m[baseField+"max_nb_trans"].GetMacSettings().GetAdr().GetDynamic().GetOverrides(), drIdx).GetMaxNbTrans() // nolint: lll + + if min != nil && max != nil && max.Value < min.Value { + return false, baseField + "max_nb_trans" + } + } return true, "" }, "mac_settings.adr.mode.dynamic.max_data_rate_index.value", @@ -2504,6 +2579,38 @@ func (ns *NetworkServer) Set(ctx context.Context, req *ttnpb.SetEndDeviceRequest "mac_settings.adr.mode.dynamic.min_data_rate_index.value", "mac_settings.adr.mode.dynamic.min_nb_trans", "mac_settings.adr.mode.dynamic.min_tx_power_index", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_0.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_1.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_10.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_11.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_12.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_13.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_14.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_15.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_2.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_3.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_4.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_5.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_6.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_7.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_8.min_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.max_nb_trans", + "mac_settings.adr.mode.dynamic.overrides.data_rate_9.min_nb_trans", ); err != nil { return nil, err } diff --git a/pkg/networkserver/mac/adr.go b/pkg/networkserver/mac/adr.go index 1c471901fa..b82297a877 100644 --- a/pkg/networkserver/mac/adr.go +++ b/pkg/networkserver/mac/adr.go @@ -22,6 +22,7 @@ import ( "go.thethings.network/lorawan-stack/v3/pkg/log" "go.thethings.network/lorawan-stack/v3/pkg/networkserver/internal" "go.thethings.network/lorawan-stack/v3/pkg/ttnpb" + "google.golang.org/protobuf/types/known/wrapperspb" ) var demodulationFloor = map[uint32]map[uint32]float32{ @@ -368,10 +369,64 @@ func clampTxPowerRange( } } -func clampNbTrans(dev *ttnpb.EndDevice, defaults *ttnpb.MACSettings, nbTrans uint32) uint32 { +// DataRateIndexOverridesOf returns the per-data rate index overrides of the given dynamic ADR settings. +func DataRateIndexOverridesOf( + overrides *ttnpb.ADRSettings_DynamicMode_Overrides, drIdx ttnpb.DataRateIndex, +) *ttnpb.ADRSettings_DynamicMode_PerDataRateIndexOverride { + switch drIdx { + case ttnpb.DataRateIndex_DATA_RATE_0: + return overrides.GetDataRate_0() + case ttnpb.DataRateIndex_DATA_RATE_1: + return overrides.GetDataRate_1() + case ttnpb.DataRateIndex_DATA_RATE_2: + return overrides.GetDataRate_2() + case ttnpb.DataRateIndex_DATA_RATE_3: + return overrides.GetDataRate_3() + case ttnpb.DataRateIndex_DATA_RATE_4: + return overrides.GetDataRate_4() + case ttnpb.DataRateIndex_DATA_RATE_5: + return overrides.GetDataRate_5() + case ttnpb.DataRateIndex_DATA_RATE_6: + return overrides.GetDataRate_6() + case ttnpb.DataRateIndex_DATA_RATE_7: + return overrides.GetDataRate_7() + case ttnpb.DataRateIndex_DATA_RATE_8: + return overrides.GetDataRate_8() + case ttnpb.DataRateIndex_DATA_RATE_9: + return overrides.GetDataRate_9() + case ttnpb.DataRateIndex_DATA_RATE_10: + return overrides.GetDataRate_10() + case ttnpb.DataRateIndex_DATA_RATE_11: + return overrides.GetDataRate_11() + case ttnpb.DataRateIndex_DATA_RATE_12: + return overrides.GetDataRate_12() + case ttnpb.DataRateIndex_DATA_RATE_13: + return overrides.GetDataRate_13() + case ttnpb.DataRateIndex_DATA_RATE_14: + return overrides.GetDataRate_14() + case ttnpb.DataRateIndex_DATA_RATE_15: + return overrides.GetDataRate_15() + default: + panic("unreachable") + } +} + +func nbTransRange( + dynamicSettings *ttnpb.ADRSettings_DynamicMode, dataRateIndex ttnpb.DataRateIndex, +) (min, max *wrapperspb.UInt32Value) { + overrides := DataRateIndexOverridesOf(dynamicSettings.Overrides, dataRateIndex) + if overrides == nil { + return dynamicSettings.MinNbTrans, dynamicSettings.MaxNbTrans + } + return overrides.MinNbTrans, overrides.MaxNbTrans +} + +func clampNbTrans( + dev *ttnpb.EndDevice, defaults *ttnpb.MACSettings, nbTrans uint32, dataRateIndex ttnpb.DataRateIndex, +) uint32 { clamp := func(dynamicSettings *ttnpb.ADRSettings_DynamicMode) uint32 { nbTrans := nbTrans - minSetting, maxSetting := dynamicSettings.MinNbTrans, dynamicSettings.MaxNbTrans + minSetting, maxSetting := nbTransRange(dynamicSettings, dataRateIndex) if minSetting != nil && minSetting.Value > nbTrans { nbTrans = minSetting.Value } @@ -601,7 +656,7 @@ func adrAdaptNbTrans( ) { macState := dev.MacState currentParameters, desiredParameters := macState.CurrentParameters, macState.DesiredParameters - nbTrans := clampNbTrans(dev, defaults, currentParameters.AdrNbTrans) + nbTrans := clampNbTrans(dev, defaults, currentParameters.AdrNbTrans, desiredParameters.AdrDataRateIndex) if len(adrUplinks) >= OptimalADRUplinkCount/2 { switch r := adrLossRate(adrUplinks...); { case r < 0.05: @@ -613,7 +668,7 @@ func adrAdaptNbTrans( nbTrans = maxNbTrans } } - desiredParameters.AdrNbTrans = clampNbTrans(dev, defaults, nbTrans) + desiredParameters.AdrNbTrans = clampNbTrans(dev, defaults, nbTrans, desiredParameters.AdrDataRateIndex) } func adaptDataRate(ctx context.Context, dev *ttnpb.EndDevice, phy *band.Band, defaults *ttnpb.MACSettings) error { diff --git a/pkg/networkserver/mac/adr_test.go b/pkg/networkserver/mac/adr_test.go index 971507598e..5acc758a0e 100644 --- a/pkg/networkserver/mac/adr_test.go +++ b/pkg/networkserver/mac/adr_test.go @@ -1253,7 +1253,8 @@ func TestClampNbTrans(t *testing.T) { Device *ttnpb.EndDevice Defaults *ttnpb.MACSettings - InputNbTrans uint32 + InputNbTrans uint32 + DataRateIndex ttnpb.DataRateIndex ExpectedNbTrans uint32 }{ @@ -1420,6 +1421,64 @@ func TestClampNbTrans(t *testing.T) { ExpectedNbTrans: 12, }, + { + Name: "maximum override; left of provided value", + + Device: &ttnpb.EndDevice{ + MacSettings: &ttnpb.MACSettings{ + Adr: &ttnpb.ADRSettings{ + Mode: &ttnpb.ADRSettings_Dynamic{ + Dynamic: &ttnpb.ADRSettings_DynamicMode{ + MaxNbTrans: &wrapperspb.UInt32Value{ + Value: 3, + }, + Overrides: &ttnpb.ADRSettings_DynamicMode_Overrides{ + DataRate_1: &ttnpb.ADRSettings_DynamicMode_PerDataRateIndexOverride{ + MaxNbTrans: &wrapperspb.UInt32Value{ + Value: 2, + }, + }, + }, + }, + }, + }, + }, + }, + + InputNbTrans: 3, + DataRateIndex: ttnpb.DataRateIndex_DATA_RATE_1, + + ExpectedNbTrans: 2, + }, + { + Name: "maximum override; right of provided value", + + Device: &ttnpb.EndDevice{ + MacSettings: &ttnpb.MACSettings{ + Adr: &ttnpb.ADRSettings{ + Mode: &ttnpb.ADRSettings_Dynamic{ + Dynamic: &ttnpb.ADRSettings_DynamicMode{ + MaxNbTrans: &wrapperspb.UInt32Value{ + Value: 1, + }, + Overrides: &ttnpb.ADRSettings_DynamicMode_Overrides{ + DataRate_1: &ttnpb.ADRSettings_DynamicMode_PerDataRateIndexOverride{ + MaxNbTrans: &wrapperspb.UInt32Value{ + Value: 2, + }, + }, + }, + }, + }, + }, + }, + }, + + InputNbTrans: 2, + DataRateIndex: ttnpb.DataRateIndex_DATA_RATE_1, + + ExpectedNbTrans: 2, + }, } { tc := tc t.Run(tc.Name, func(t *testing.T) { @@ -1427,7 +1486,7 @@ func TestClampNbTrans(t *testing.T) { a := assertions.New(t) - value := ClampNbTrans(tc.Device, tc.Defaults, tc.InputNbTrans) + value := ClampNbTrans(tc.Device, tc.Defaults, tc.InputNbTrans, tc.DataRateIndex) a.So(value, should.Equal, tc.ExpectedNbTrans) }) }