Skip to content

Commit 05263e7

Browse files
authored
Merge pull request project-chip#32 from kedars/feature/remove_fabric
"Remove Fabric" Support
2 parents dd3f85d + 2f360af commit 05263e7

File tree

7 files changed

+117
-3
lines changed

7 files changed

+117
-3
lines changed

matter/src/acl.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,17 @@ pub const NOC_CAT_SUBJECT_PREFIX: u64 = 0xFFFF_FFFD_0000_0000;
7878
const NOC_CAT_ID_MASK: u64 = 0xFFFF_0000;
7979
const NOC_CAT_VERSION_MASK: u64 = 0xFFFF;
8080

81+
/// Is this identifier a NOC CAT
8182
fn is_noc_cat(id: u64) -> bool {
8283
(id & NOC_CAT_SUBJECT_PREFIX) == NOC_CAT_SUBJECT_PREFIX
8384
}
8485

86+
/// Get the 16-bit NOC CAT id from the identifier
8587
fn get_noc_cat_id(id: u64) -> u64 {
8688
(id & NOC_CAT_ID_MASK) >> 16
8789
}
8890

91+
/// Get the 16-bit NOC CAT version from the identifier
8992
fn get_noc_cat_version(id: u64) -> u64 {
9093
id & NOC_CAT_VERSION_MASK
9194
}
@@ -96,6 +99,7 @@ pub fn gen_noc_cat(id: u16, version: u16) -> u32 {
9699
((id as u32) << 16) | version as u32
97100
}
98101

102+
/// The Subjects that identify the Accessor
99103
pub struct AccessorSubjects([u64; MAX_ACCESSOR_SUBJECTS]);
100104

101105
impl AccessorSubjects {
@@ -816,4 +820,34 @@ mod tests {
816820
req.set_target_perms(Access::RWVA);
817821
assert_eq!(req.allow(), true);
818822
}
823+
824+
#[test]
825+
fn test_delete_for_fabric() {
826+
let am = Arc::new(AclMgr::new_with(false).unwrap());
827+
am.erase_all();
828+
let path = GenericPath::new(Some(1), Some(1234), None);
829+
let accessor2 = Accessor::new(2, AccessorSubjects::new(112233), AuthMode::Case, am.clone());
830+
let mut req2 = AccessReq::new(&accessor2, &path, Access::READ);
831+
req2.set_target_perms(Access::RWVA);
832+
let accessor3 = Accessor::new(3, AccessorSubjects::new(112233), AuthMode::Case, am.clone());
833+
let mut req3 = AccessReq::new(&accessor3, &path, Access::READ);
834+
req3.set_target_perms(Access::RWVA);
835+
836+
// Allow for subject match - target is wildcard - Fabric idx 2
837+
let mut new = AclEntry::new(2, Privilege::VIEW, AuthMode::Case);
838+
new.add_subject(112233).unwrap();
839+
am.add(new).unwrap();
840+
841+
// Allow for subject match - target is wildcard - Fabric idx 3
842+
let mut new = AclEntry::new(3, Privilege::VIEW, AuthMode::Case);
843+
new.add_subject(112233).unwrap();
844+
am.add(new).unwrap();
845+
846+
// Req for Fabric idx 2 gets denied, and that for Fabric idx 3 is allowed
847+
assert_eq!(req2.allow(), true);
848+
assert_eq!(req3.allow(), true);
849+
am.delete_for_fabric(2).unwrap();
850+
assert_eq!(req2.allow(), false);
851+
assert_eq!(req3.allow(), true);
852+
}
819853
}

matter/src/data_model/sdm/noc.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,24 @@ impl NocCluster {
263263
Ok(())
264264
}
265265

266+
fn handle_command_rmfabric(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
267+
cmd_enter!("Remove Fabric");
268+
let req =
269+
RemoveFabricReq::from_tlv(&cmd_req.data).map_err(|_| IMStatusCode::InvalidCommand)?;
270+
if self.fabric_mgr.remove(req.fab_idx).is_ok() {
271+
let _ = self.acl_mgr.delete_for_fabric(req.fab_idx);
272+
cmd_req.trans.terminate();
273+
} else {
274+
NocCluster::create_nocresponse(
275+
cmd_req.resp,
276+
NocStatus::InvalidFabricIndex,
277+
req.fab_idx,
278+
"".to_string(),
279+
);
280+
}
281+
Ok(())
282+
}
283+
266284
fn handle_command_addnoc(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
267285
cmd_enter!("AddNOC");
268286
if let Err(e) = self._handle_command_addnoc(cmd_req) {
@@ -437,6 +455,7 @@ impl ClusterType for NocCluster {
437455
Commands::AttReq => self.handle_command_attrequest(cmd_req),
438456
Commands::CertChainReq => self.handle_command_certchainrequest(cmd_req),
439457
Commands::UpdateFabricLabel => self.handle_command_updatefablabel(cmd_req),
458+
Commands::RemoveFabric => self.handle_command_rmfabric(cmd_req),
440459
_ => Err(IMStatusCode::UnsupportedCommand),
441460
}
442461
}
@@ -566,6 +585,11 @@ struct CertChainReq {
566585
cert_type: u8,
567586
}
568587

588+
#[derive(FromTLV)]
589+
struct RemoveFabricReq {
590+
fab_idx: u8,
591+
}
592+
569593
fn get_certchainrequest_params(data: &TLVElement) -> Result<DataType, Error> {
570594
let cert_type = CertChainReq::from_tlv(data)?.cert_type;
571595

matter/src/fabric.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,17 @@ impl Fabric {
195195
}
196196
}
197197

198+
fn rm_store(&self, index: usize, psm: &MutexGuard<Psm>) {
199+
psm.rm(fb_key!(index, ST_RCA));
200+
psm.rm(fb_key!(index, ST_ICA));
201+
psm.rm(fb_key!(index, ST_NOC));
202+
psm.rm(fb_key!(index, ST_IPK));
203+
psm.rm(fb_key!(index, ST_LBL));
204+
psm.rm(fb_key!(index, ST_PBKEY));
205+
psm.rm(fb_key!(index, ST_PRKEY));
206+
psm.rm(fb_key!(index, ST_VID));
207+
}
208+
198209
fn store(&self, index: usize, psm: &MutexGuard<Psm>) -> Result<(), Error> {
199210
let mut key = [0u8; MAX_CERT_TLV_LEN];
200211
let len = self.root_ca.as_tlv(&mut key)?;
@@ -335,6 +346,19 @@ impl FabricMgr {
335346
Ok(index as u8)
336347
}
337348

349+
pub fn remove(&self, fab_idx: u8) -> Result<(), Error> {
350+
let fab_idx = fab_idx as usize;
351+
let mut mgr = self.inner.write().unwrap();
352+
let psm = self.psm.lock().unwrap();
353+
if let Some(f) = &mgr.fabrics[fab_idx] {
354+
f.rm_store(fab_idx, &psm);
355+
mgr.fabrics[fab_idx] = None;
356+
Ok(())
357+
} else {
358+
Err(Error::NotFound)
359+
}
360+
}
361+
338362
pub fn match_dest_id(&self, random: &[u8], target: &[u8]) -> Result<usize, Error> {
339363
let mgr = self.inner.read()?;
340364
for i in 0..MAX_SUPPORTED_FABRICS {

matter/src/interaction_model/core.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ impl<'a> Transaction<'a> {
6868
}
6969
}
7070

71+
/// Terminates the transaction, no communication (even ACKs) happens hence forth
72+
pub fn terminate(&mut self) {
73+
self.state = TransactionState::Terminate
74+
}
75+
76+
pub fn is_terminate(&self) -> bool {
77+
self.state == TransactionState::Terminate
78+
}
79+
80+
/// Marks the transaction as completed from the application's perspective
7181
pub fn complete(&mut self) {
7282
self.state = TransactionState::Complete
7383
}
@@ -200,7 +210,9 @@ impl proto_demux::HandleProto for InteractionModel {
200210
info!("Sending response");
201211
tlv::print_tlv_list(ctx.tx.as_borrow_slice());
202212
}
203-
if trans.is_complete() {
213+
if trans.is_terminate() {
214+
ctx.exch_ctx.exch.terminate();
215+
} else if trans.is_complete() {
204216
ctx.exch_ctx.exch.close();
205217
}
206218
Ok(result)

matter/src/interaction_model/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use self::{
3030
pub enum TransactionState {
3131
Ongoing,
3232
Complete,
33+
Terminate,
3334
}
3435
pub struct Transaction<'a> {
3536
pub state: TransactionState,

matter/src/sys/posix.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
use std::{
1919
convert::TryInto,
20-
fs::{DirBuilder, File},
20+
fs::{remove_file, DirBuilder, File},
2121
io::{Read, Write},
2222
sync::{Arc, Mutex, Once},
2323
};
@@ -89,4 +89,8 @@ impl Psm {
8989
*val = u64::from_be_bytes(vec.as_slice().try_into()?);
9090
Ok(())
9191
}
92+
93+
pub fn rm(&self, key: &str) {
94+
let _ = remove_file(psm_path!(key));
95+
}
9296
}

matter/src/transport/exchange.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,15 @@ impl Default for Role {
4848
}
4949
}
5050

51+
/// State of the exchange
5152
#[derive(Debug, PartialEq)]
5253
enum State {
54+
/// The exchange is open and active
5355
Open,
56+
/// The exchange is closed, but keys are active since retransmissions/acks may be pending
5457
Close,
58+
/// The exchange is terminated, keys are destroyed, no communication can happen
59+
Terminate,
5560
}
5661

5762
impl Default for State {
@@ -100,6 +105,11 @@ impl Exchange {
100105
}
101106
}
102107

108+
pub fn terminate(&mut self) {
109+
self.data = DataOption::None;
110+
self.state = State::Terminate;
111+
}
112+
103113
pub fn close(&mut self) {
104114
self.data = DataOption::None;
105115
self.state = State::Close;
@@ -111,7 +121,7 @@ impl Exchange {
111121

112122
pub fn is_purgeable(&self) -> bool {
113123
// No Users, No pending ACKs/Retrans
114-
self.state == State::Close && self.mrp.is_empty()
124+
self.state == State::Terminate || (self.state == State::Close && self.mrp.is_empty())
115125
}
116126

117127
pub fn get_id(&self) -> u16 {
@@ -170,6 +180,11 @@ impl Exchange {
170180
mut proto_tx: BoxSlab<PacketPool>,
171181
session: &mut SessionHandle,
172182
) -> Result<(), Error> {
183+
if self.state == State::Terminate {
184+
info!("Skipping tx for terminated exchange {}", self.id);
185+
return Ok(());
186+
}
187+
173188
trace!("payload: {:x?}", proto_tx.as_borrow_slice());
174189
info!(
175190
"{} with proto id: {} opcode: {}",

0 commit comments

Comments
 (0)