Skip to content

Commit

Permalink
minimal perfect hash function
Browse files Browse the repository at this point in the history
  • Loading branch information
Sa1dzhan committed Jul 10, 2024
1 parent 5580097 commit 275d9f9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 22 deletions.
2 changes: 1 addition & 1 deletion chirpstack/src/devaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rand::RngCore;
use sha2::{Digest, Sha256};
// use std::convert::TryInto;
// use tracing::info;
use num_bigint::BigUint;
// use num_bigint::BigUint;
use uuid::Uuid;

use crate::config;
Expand Down
66 changes: 49 additions & 17 deletions chirpstack/src/storage/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use diesel_async::RunQueryDsl;

use super::schema::{application, device, device_profile, tenant, multicast_group, multicast_group_device};
use super::{
application::Application, device::Device, device_profile::DeviceProfile, tenant::Tenant, multicast::MulticastGroup
application::Application, device::Device, device_profile::DeviceProfile, tenant::Tenant
};
use super::{error::Error, get_async_db_conn};
use lrwn::EUI64;
use uuid::Uuid;
use sha2::{Digest, Sha256};

pub async fn get_all_device_data(
dev_eui: EUI64,
Expand All @@ -23,33 +24,64 @@ pub async fn get_all_device_data(
Ok(res)
}


static SECRET_KEY: &[u8; 32] = b"e2fc714cef004ad48c91d2c08b8c4f75";
// Custom function for ts-lora
pub async fn get_multicast_group_index(
pub async fn get_channel_index(
dev_eui: EUI64,
) -> Result<usize, Error> {
let mut db_conn = get_async_db_conn().await?;

// Query to find the multicast group ID for the given dev_eui
let device_multicast_group_id = multicast_group_device::table
let id: Uuid = multicast_group_device::table
.filter(multicast_group_device::dsl::dev_eui.eq(dev_eui))
.select(multicast_group_device::dsl::multicast_group_id)
.first::<Uuid>(&mut db_conn)
.await
.map_err(|e| Error::from_diesel(e, "Error while retrieving multicast group ID".to_string()))?;


// Get all multicast groups to find the index
let multicast_groups: Vec<MulticastGroup> = multicast_group::table
.load::<MulticastGroup>(&mut db_conn)
let counter = multicast_group::table
.filter(multicast_group::dsl::id.eq(id))
.select(multicast_group::dsl::f_cnt)
.first::<i64>(&mut db_conn)
.await
.map_err(|e| Error::from_diesel(e, "Error while retrieving multicast groups".to_string()))?;

// Find the index of the group with the matching ID
multicast_groups.iter().enumerate()
.find_map(|(index, group)| if group.id == device_multicast_group_id {
Some(index)
} else {
None
})
.ok_or_else(|| Error::NotFound(format!("Device's multicast group not found among retrieved groups (id: {})", device_multicast_group_id)))
.map_err(|e| Error::from_diesel(e, "Error while retrieving frame counter from Multicast Group".to_string()))?;

let channel_index = generate_channel(counter, SECRET_KEY, id);

Ok(channel_index)
}

/// Generates a unique channel for a given group UUID.
fn generate_channel(asn: i64, key: &[u8], offset_uuid: Uuid) -> usize {
let mut hasher = Sha256::new();
hasher.update(asn.to_le_bytes());
hasher.update(key);
let hash_bytes = hasher.finalize();

// Extract the 3 most significant bits from the hash.
let msb_3 = (hash_bytes[0] >> 5) as usize;

// Calculate OFFSET_j' using the UUID bytes.
let sum_uuid_bytes: u64 = offset_uuid
.as_bytes()
.iter()
.map(|&b| b as u64)
.sum();
let offset_j_prime = ((sum_uuid_bytes as i64 + asn) % 8) as usize;

// Convert OFFSET_j' to binary.
let b_0 = (offset_j_prime >> 2) & 0b1;
let b_1 = (offset_j_prime >> 1) & 0b1;
let b_2 = offset_j_prime & 0b1;

// XOR msb_3 and binary OFFSET_j'.
let x_0 = (msb_3 >> 2) & 0b1;
let x_1 = (msb_3 >> 1) & 0b1;
let x_2 = msb_3 & 0b1;

// Calculate the channel.
let ch_j = (x_0 ^ b_0) << 2 | (x_1 ^ b_1) << 1 | (x_2 ^ b_2);

ch_j
}
7 changes: 3 additions & 4 deletions chirpstack/src/uplink/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::storage::{
device::{self, DeviceClass},
device_keys, device_profile, device_queue,
error::Error as StorageError,
helpers::{get_all_device_data, get_multicast_group_index},
helpers::{get_all_device_data, get_channel_index},
metrics, tenant,
};
use crate::{config, devaddr::get_random_dev_addr_slot, downlink, integration, region, stream};
Expand Down Expand Up @@ -775,8 +775,7 @@ impl JoinRequest {
let device_profile = self.device_profile.as_ref().unwrap();

// map multicast group index to channel index
let multicast_group_index = get_multicast_group_index(device.dev_eui).await?;
println!("Multicast group index is {} for dev_eui {}", multicast_group_index, device.dev_eui);
let channel_index = get_channel_index(device.dev_eui).await?;

let mut ds = internal::DeviceSession {
region_config_id: self.uplink_frame_set.region_config_id.clone(),
Expand All @@ -795,7 +794,7 @@ impl JoinRequest {
// .iter()
// .map(|i| *i as u32)
// .collect(),
enabled_uplink_channel_indices: vec![multicast_group_index as u32],
enabled_uplink_channel_indices: vec![channel_index as u32],
skip_f_cnt_check: device.skip_fcnt_check,
..Default::default()
};
Expand Down

0 comments on commit 275d9f9

Please sign in to comment.