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.
This commit is contained in:
Orne Brocaar 2022-10-19 12:36:31 +01:00
parent 6cc813aed1
commit 289d97f258
8 changed files with 71 additions and 54 deletions

View File

@ -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<api::GetRandomDevAddrRequest>,
) -> Result<Response<api::GetRandomDevAddrResponse>, 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

View File

@ -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

View File

@ -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<Arc<Configuration>> = 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<DevAddrPrefix>,
pub enabled_regions: Vec<String>,
#[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),

33
chirpstack/src/devaddr.rs Normal file
View File

@ -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
}

View File

@ -25,6 +25,7 @@ mod certificate;
mod cmd;
mod codec;
mod config;
mod devaddr;
mod downlink;
mod eventlog;
mod framelog;

View File

@ -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 {

View File

@ -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(())
}

View File

@ -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(())
}