From 289d97f258ab10bc864f2cf6601dfe8c360f5598 Mon Sep 17 00:00:00 2001 From: Orne Brocaar Date: Wed, 19 Oct 2022 12:36:31 +0100 Subject: [PATCH] Implement dev_addr_prefixes configuration. This makes it possible to configure one or multiple DevAddr sub-ranges instead of using the whole DevAddr range provided by the configured NetID. Closes #49. --- chirpstack/src/api/device.rs | 19 +++------------ chirpstack/src/cmd/configfile.rs | 20 ++++++++++++++++ chirpstack/src/config.rs | 4 +++- chirpstack/src/devaddr.rs | 33 ++++++++++++++++++++++++++ chirpstack/src/main.rs | 1 + chirpstack/src/test/class_a_pr_test.rs | 8 ++++--- chirpstack/src/uplink/join.rs | 21 ++++------------ chirpstack/src/uplink/join_sns.rs | 19 ++------------- 8 files changed, 71 insertions(+), 54 deletions(-) create mode 100644 chirpstack/src/devaddr.rs diff --git a/chirpstack/src/api/device.rs b/chirpstack/src/api/device.rs index 8cbabb92..a3bd1540 100644 --- a/chirpstack/src/api/device.rs +++ b/chirpstack/src/api/device.rs @@ -4,7 +4,6 @@ use std::time::SystemTime; use bigdecimal::ToPrimitive; use chrono::{DateTime, Local, Utc}; -use rand::RngCore; use tonic::{Request, Response, Status}; use uuid::Uuid; @@ -19,7 +18,7 @@ use crate::storage::error::Error; use crate::storage::{ device, device_keys, device_profile, device_queue, device_session, fields, metrics, }; -use crate::{codec, config}; +use crate::{codec, devaddr::get_random_dev_addr}; pub struct Device { validator: validator::RequestValidator, @@ -547,20 +546,8 @@ impl DeviceService for Device { &self, _request: Request, ) -> Result, Status> { - let conf = config::get(); - let mut dev_addr: [u8; 4] = [0; 4]; - - rand::thread_rng().fill_bytes(&mut dev_addr); - #[cfg(test)] - { - dev_addr = [1, 2, 3, 4]; - } - - let mut dev_addr = DevAddr::from_be_bytes(dev_addr); - dev_addr.set_addr_prefix(&conf.network.net_id); - Ok(Response::new(api::GetRandomDevAddrResponse { - dev_addr: dev_addr.to_string(), + dev_addr: get_random_dev_addr().to_string(), })) } @@ -1347,7 +1334,7 @@ pub mod test { .unwrap(); let dev_addr = DevAddr::from_str(&get_random_dev_addr_resp.get_ref().dev_addr).unwrap(); let mut dev_addr_copy = dev_addr.clone(); - dev_addr_copy.set_addr_prefix(&NetID::from_str("000000").unwrap()); + dev_addr_copy.set_dev_addr_prefix(NetID::from_str("000000").unwrap().dev_addr_prefix()); assert_eq!(dev_addr, dev_addr_copy); // enqueue diff --git a/chirpstack/src/cmd/configfile.rs b/chirpstack/src/cmd/configfile.rs index f7b785cb..fd770d28 100644 --- a/chirpstack/src/cmd/configfile.rs +++ b/chirpstack/src/cmd/configfile.rs @@ -117,6 +117,26 @@ pub fn run() { # Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203). net_id="{{ network.net_id }}" + # DevAddr prefix(es). + # + # This makes it possible to configure one or multiple sub-ranges within + # the configured NetID. If left blank, then the complete DevAddr space + # provided by the configured NetID will be used. + # If multiple prefixes are configured, a random prefix will be chosen when + # generating a DevAddr. + # + # Example configuration: + # dev_addr_prefixes=["0000ff00/24"] + # + # This example configures the DevAddr range to 0000ff00 - 0000ffff. + # The /24 means that the 24MSB of the prefix will be used, meaning that the + # 8LSB will be used as address space. + dev_addr_prefixes=[ + {{#each network.dev_addr_prefixes}} + "{{this}}", + {{/each}} + ] + # Enabled regions. # # Multiple regions can be enabled simultaneously. Each region must match diff --git a/chirpstack/src/config.rs b/chirpstack/src/config.rs index 4e8b3165..ea4e1c6c 100644 --- a/chirpstack/src/config.rs +++ b/chirpstack/src/config.rs @@ -7,7 +7,7 @@ use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use lrwn::region::CommonName; -use lrwn::{AES128Key, NetID, EUI64}; +use lrwn::{AES128Key, DevAddrPrefix, NetID, EUI64}; lazy_static! { static ref CONFIG: Mutex> = Mutex::new(Arc::new(Default::default())); @@ -150,6 +150,7 @@ impl Default for Gateway { #[serde(default)] pub struct Network { pub net_id: NetID, + pub dev_addr_prefixes: Vec, pub enabled_regions: Vec, #[serde(with = "humantime_serde")] pub device_session_ttl: Duration, @@ -164,6 +165,7 @@ impl Default for Network { fn default() -> Self { Network { net_id: NetID::from_be_bytes([0x00, 0x00, 0x00]), + dev_addr_prefixes: vec![], enabled_regions: vec!["eu868".into()], device_session_ttl: Duration::from_secs(60 * 60 * 24 * 31), deduplication_delay: Duration::from_millis(200), diff --git a/chirpstack/src/devaddr.rs b/chirpstack/src/devaddr.rs new file mode 100644 index 00000000..1f3dd15a --- /dev/null +++ b/chirpstack/src/devaddr.rs @@ -0,0 +1,33 @@ +use rand::seq::SliceRandom; +use rand::RngCore; + +use crate::config; +use lrwn::DevAddr; + +pub fn get_random_dev_addr() -> DevAddr { + let conf = config::get(); + let mut rng = rand::thread_rng(); + + // Get configured DevAddr prefixes. + let prefixes = if conf.network.dev_addr_prefixes.is_empty() { + vec![conf.network.net_id.dev_addr_prefix()] + } else { + conf.network.dev_addr_prefixes.clone() + }; + + // Pick a random one (in case multiple prefixes are configured). + let prefix = *prefixes.choose(&mut rng).unwrap(); + + // Generate random DevAddr. + let mut dev_addr: [u8; 4] = [0; 4]; + rng.fill_bytes(&mut dev_addr); + #[cfg(test)] + { + dev_addr = [1, 2, 3, 4]; + } + let mut dev_addr = DevAddr::from_be_bytes(dev_addr); + + // Set DevAddr prefix. + dev_addr.set_dev_addr_prefix(prefix); + dev_addr +} diff --git a/chirpstack/src/main.rs b/chirpstack/src/main.rs index 033601a5..ac179591 100644 --- a/chirpstack/src/main.rs +++ b/chirpstack/src/main.rs @@ -25,6 +25,7 @@ mod certificate; mod cmd; mod codec; mod config; +mod devaddr; mod downlink; mod eventlog; mod framelog; diff --git a/chirpstack/src/test/class_a_pr_test.rs b/chirpstack/src/test/class_a_pr_test.rs index 82574b87..35a49d5b 100644 --- a/chirpstack/src/test/class_a_pr_test.rs +++ b/chirpstack/src/test/class_a_pr_test.rs @@ -86,7 +86,9 @@ async fn test_fns_uplink() { fhdr: lrwn::FHDR { devaddr: { let mut d = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]); - d.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap()); + d.set_dev_addr_prefix( + lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix(), + ); d }, f_ctrl: Default::default(), @@ -232,7 +234,7 @@ async fn test_sns_uplink() { .unwrap(); let mut dev_addr = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]); - dev_addr.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap()); + dev_addr.set_dev_addr_prefix(lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix()); let ds = internal::DeviceSession { dev_eui: vec![2, 2, 3, 4, 5, 6, 7, 8], @@ -428,7 +430,7 @@ async fn test_sns_dev_not_found() { roaming::setup().unwrap(); let mut dev_addr = lrwn::DevAddr::from_be_bytes([0, 0, 0, 0]); - dev_addr.set_addr_prefix(&lrwn::NetID::from_str("000505").unwrap()); + dev_addr.set_dev_addr_prefix(lrwn::NetID::from_str("000505").unwrap().dev_addr_prefix()); let data_phy = lrwn::PhyPayload { mhdr: lrwn::MHDR { diff --git a/chirpstack/src/uplink/join.rs b/chirpstack/src/uplink/join.rs index 4907aec6..dc99072d 100644 --- a/chirpstack/src/uplink/join.rs +++ b/chirpstack/src/uplink/join.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use anyhow::{Context, Result}; use chrono::{DateTime, Local, Utc}; -use rand::RngCore; use tracing::{error, info, span, trace, Instrument, Level}; use lrwn::{ @@ -22,7 +21,9 @@ use crate::storage::{ application, device, device_keys, device_profile, device_queue, error::Error as StorageError, metrics, tenant, }; -use crate::{config, downlink, framelog, integration, metalog, region}; +use crate::{ + config, devaddr::get_random_dev_addr, downlink, framelog, integration, metalog, region, +}; use chirpstack_api::{api, common, integration as integration_pb, internal, meta}; pub struct JoinRequest { @@ -349,21 +350,7 @@ impl JoinRequest { } fn get_random_dev_addr(&mut self) -> Result<()> { - let conf = config::get(); - - let mut dev_addr: [u8; 4] = [0; 4]; - - rand::thread_rng().fill_bytes(&mut dev_addr); - - #[cfg(test)] - { - dev_addr = [1, 2, 3, 4]; - } - - let mut dev_addr = DevAddr::from_be_bytes(dev_addr); - dev_addr.set_addr_prefix(&conf.network.net_id); - self.dev_addr = Some(dev_addr); - + self.dev_addr = Some(get_random_dev_addr()); Ok(()) } diff --git a/chirpstack/src/uplink/join_sns.rs b/chirpstack/src/uplink/join_sns.rs index 20ca4e32..167c903e 100644 --- a/chirpstack/src/uplink/join_sns.rs +++ b/chirpstack/src/uplink/join_sns.rs @@ -2,7 +2,6 @@ use std::sync::Arc; use anyhow::{Context, Result}; use chrono::{DateTime, Local, Utc}; -use rand::RngCore; use tracing::{span, trace, Instrument, Level}; use super::{helpers, UplinkFrameSet}; @@ -12,7 +11,7 @@ use crate::storage::{ application, device, device_keys, device_profile, device_queue, device_session, error::Error as StorageError, metrics, tenant, }; -use crate::{config, integration, metalog, region}; +use crate::{config, devaddr::get_random_dev_addr, integration, metalog, region}; use backend::{PRStartAnsPayload, PRStartReqPayload}; use chirpstack_api::{common, integration as integration_pb, internal, meta}; use lrwn::{keys, AES128Key, DevAddr, NetID}; @@ -203,21 +202,7 @@ impl JoinRequest { } fn get_random_dev_addr(&mut self) -> Result<()> { - let conf = config::get(); - - let mut dev_addr: [u8; 4] = [0; 4]; - - rand::thread_rng().fill_bytes(&mut dev_addr); - - #[cfg(test)] - { - dev_addr = [1, 2, 3, 4]; - } - - let mut dev_addr = DevAddr::from_be_bytes(dev_addr); - dev_addr.set_addr_prefix(&conf.network.net_id); - self.dev_addr = Some(dev_addr); - + self.dev_addr = Some(get_random_dev_addr()); Ok(()) }