mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-02-22 17:42:36 +00:00
Implement removing device from Relay filter list.
This commit is contained in:
parent
050610de55
commit
4359e90613
@ -1652,12 +1652,12 @@ impl Data {
|
|||||||
async fn _update_filter_list(&mut self) -> Result<()> {
|
async fn _update_filter_list(&mut self) -> Result<()> {
|
||||||
trace!("Updating Relay filter list");
|
trace!("Updating Relay filter list");
|
||||||
|
|
||||||
// Get the current relay state.
|
if self.device_session.relay.is_none() {
|
||||||
let mut relay = if let Some(r) = &self.device_session.relay {
|
self.device_session.relay = Some(internal::Relay::default());
|
||||||
r.clone()
|
}
|
||||||
} else {
|
|
||||||
internal::Relay::default()
|
// Get a copy of the current relay state.
|
||||||
};
|
let relay = self.device_session.relay.as_ref().unwrap().clone();
|
||||||
|
|
||||||
// Get devices that must be configured on the relay.
|
// Get devices that must be configured on the relay.
|
||||||
let relay_devices = relay::list_devices(
|
let relay_devices = relay::list_devices(
|
||||||
@ -1669,22 +1669,52 @@ impl Data {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// We filter out the devices that are no longer configured on the relay.
|
// Get DevEUIs of Relay EDs.
|
||||||
// This way we can combine the delete + add by just overwriting an old slot.
|
|
||||||
// Note that index 0 has a special meaning.
|
|
||||||
let relay_devices_dev_euis: Vec<Vec<u8>> =
|
let relay_devices_dev_euis: Vec<Vec<u8>> =
|
||||||
relay_devices.iter().map(|d| d.dev_eui.to_vec()).collect();
|
relay_devices.iter().map(|d| d.dev_eui.to_vec()).collect();
|
||||||
relay
|
|
||||||
|
// Calculate removed slots.
|
||||||
|
let removed_slots: Vec<u32> = relay
|
||||||
.filters
|
.filters
|
||||||
.retain(|f| f.index == 0 || relay_devices_dev_euis.contains(&f.dev_eui));
|
.iter()
|
||||||
|
.filter(|f| f.index != 0 && !relay_devices_dev_euis.contains(&f.dev_eui))
|
||||||
|
.map(|f| f.index)
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Calculate free slots.
|
// Calculate free slots.
|
||||||
// Note that the first slot is used as "catch-all" filter.
|
// Note that the first slot is used as "catch-all" filter.
|
||||||
let used_slots: Vec<u32> = relay.filters.iter().map(|f| f.index).collect();
|
let used_slots: Vec<u32> = relay
|
||||||
|
.filters
|
||||||
|
.iter()
|
||||||
|
.filter(|f| f.index == 0 || relay_devices_dev_euis.contains(&f.dev_eui))
|
||||||
|
.map(|f| f.index)
|
||||||
|
.collect();
|
||||||
let free_slots: Vec<u32> = (1..15).filter(|x| !used_slots.contains(x)).collect();
|
let free_slots: Vec<u32> = (1..15).filter(|x| !used_slots.contains(x)).collect();
|
||||||
|
|
||||||
// Update device-session.
|
// Unset slots of devices that are no longer configured.
|
||||||
self.device_session.relay = Some(relay);
|
if !removed_slots.is_empty() {
|
||||||
|
let mut commands: Vec<lrwn::MACCommand> = Vec::new();
|
||||||
|
for slot in removed_slots {
|
||||||
|
commands.push(lrwn::MACCommand::FilterListReq(
|
||||||
|
lrwn::FilterListReqPayload {
|
||||||
|
filter_list_idx: slot as u8,
|
||||||
|
filter_list_action: lrwn::FilterListAction::NoRule,
|
||||||
|
filter_list_eui: vec![],
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
if commands.len() > 5 {
|
||||||
|
commands.drain(5..);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = lrwn::MACCommandSet::new(commands);
|
||||||
|
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::FilterListReq, &set).await?;
|
||||||
|
self.mac_commands.push(set);
|
||||||
|
|
||||||
|
// The deletes needs to be processed before we can add new entries.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the first item contains the "catch-all" filter.
|
// Make sure the first item contains the "catch-all" filter.
|
||||||
// This is needed to make sure that only the rest of the filter items are allowed to join
|
// This is needed to make sure that only the rest of the filter items are allowed to join
|
||||||
@ -3230,6 +3260,59 @@ mod test {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Test {
|
||||||
|
name: "remove filter".into(),
|
||||||
|
device_session: internal::DeviceSession {
|
||||||
|
relay: Some(internal::Relay {
|
||||||
|
filters: vec![
|
||||||
|
internal::RelayFilter {
|
||||||
|
index: 0,
|
||||||
|
action: 2,
|
||||||
|
provisioned: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
internal::RelayFilter {
|
||||||
|
index: 1,
|
||||||
|
action: 1,
|
||||||
|
dev_eui: vec![2, 2, 2, 2, 2, 2, 2, 0],
|
||||||
|
join_eui: vec![2, 2, 2, 2, 2, 2, 2, 1],
|
||||||
|
provisioned: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
relay_devices: vec![],
|
||||||
|
expected_mac_commands: vec![lrwn::MACCommandSet::new(vec![
|
||||||
|
lrwn::MACCommand::FilterListReq(lrwn::FilterListReqPayload {
|
||||||
|
filter_list_idx: 1,
|
||||||
|
filter_list_action: lrwn::FilterListAction::NoRule,
|
||||||
|
filter_list_eui: vec![],
|
||||||
|
}),
|
||||||
|
])],
|
||||||
|
expected_device_session: internal::DeviceSession {
|
||||||
|
relay: Some(internal::Relay {
|
||||||
|
filters: vec![
|
||||||
|
internal::RelayFilter {
|
||||||
|
index: 0,
|
||||||
|
action: 2,
|
||||||
|
provisioned: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
internal::RelayFilter {
|
||||||
|
index: 1,
|
||||||
|
action: 1,
|
||||||
|
dev_eui: vec![2, 2, 2, 2, 2, 2, 2, 0],
|
||||||
|
join_eui: vec![2, 2, 2, 2, 2, 2, 2, 1],
|
||||||
|
provisioned: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
let _guard = test::prepare().await;
|
let _guard = test::prepare().await;
|
||||||
|
@ -44,6 +44,13 @@ pub fn handle(
|
|||||||
f.provisioned = true;
|
f.provisioned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the action was NoRule, we remove the filter from the relay filters.
|
||||||
|
if req_pl.filter_list_action == lrwn::FilterListAction::NoRule {
|
||||||
|
relay
|
||||||
|
.filters
|
||||||
|
.retain(|f| f.index != req_pl.filter_list_idx as u32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
@ -168,6 +175,42 @@ mod test {
|
|||||||
},
|
},
|
||||||
expected_error: None,
|
expected_error: None,
|
||||||
},
|
},
|
||||||
|
Test {
|
||||||
|
name: "acked removing filter".into(),
|
||||||
|
device_session: internal::DeviceSession {
|
||||||
|
relay: Some(internal::Relay {
|
||||||
|
filters: vec![internal::RelayFilter {
|
||||||
|
index: 1,
|
||||||
|
provisioned: true,
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
filter_list_req: Some(lrwn::MACCommandSet::new(vec![
|
||||||
|
lrwn::MACCommand::FilterListReq(lrwn::FilterListReqPayload {
|
||||||
|
filter_list_idx: 1,
|
||||||
|
filter_list_action: lrwn::FilterListAction::NoRule,
|
||||||
|
filter_list_eui: vec![],
|
||||||
|
}),
|
||||||
|
])),
|
||||||
|
filter_list_ans: lrwn::MACCommandSet::new(vec![lrwn::MACCommand::FilterListAns(
|
||||||
|
lrwn::FilterListAnsPayload {
|
||||||
|
filter_list_action_ack: true,
|
||||||
|
filter_list_len_ack: true,
|
||||||
|
combined_rules_ack: true,
|
||||||
|
},
|
||||||
|
)]),
|
||||||
|
expected_device_session: internal::DeviceSession {
|
||||||
|
relay: Some(internal::Relay {
|
||||||
|
filters: vec![],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
expected_error: None,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for tst in &tests {
|
for tst in &tests {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user