Merge pull request #32 from kedars/feature/remove_fabric
"Remove Fabric" Support
This commit is contained in:
commit
05263e7a2c
7 changed files with 117 additions and 3 deletions
|
@ -78,14 +78,17 @@ pub const NOC_CAT_SUBJECT_PREFIX: u64 = 0xFFFF_FFFD_0000_0000;
|
||||||
const NOC_CAT_ID_MASK: u64 = 0xFFFF_0000;
|
const NOC_CAT_ID_MASK: u64 = 0xFFFF_0000;
|
||||||
const NOC_CAT_VERSION_MASK: u64 = 0xFFFF;
|
const NOC_CAT_VERSION_MASK: u64 = 0xFFFF;
|
||||||
|
|
||||||
|
/// Is this identifier a NOC CAT
|
||||||
fn is_noc_cat(id: u64) -> bool {
|
fn is_noc_cat(id: u64) -> bool {
|
||||||
(id & NOC_CAT_SUBJECT_PREFIX) == NOC_CAT_SUBJECT_PREFIX
|
(id & NOC_CAT_SUBJECT_PREFIX) == NOC_CAT_SUBJECT_PREFIX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the 16-bit NOC CAT id from the identifier
|
||||||
fn get_noc_cat_id(id: u64) -> u64 {
|
fn get_noc_cat_id(id: u64) -> u64 {
|
||||||
(id & NOC_CAT_ID_MASK) >> 16
|
(id & NOC_CAT_ID_MASK) >> 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the 16-bit NOC CAT version from the identifier
|
||||||
fn get_noc_cat_version(id: u64) -> u64 {
|
fn get_noc_cat_version(id: u64) -> u64 {
|
||||||
id & NOC_CAT_VERSION_MASK
|
id & NOC_CAT_VERSION_MASK
|
||||||
}
|
}
|
||||||
|
@ -96,6 +99,7 @@ pub fn gen_noc_cat(id: u16, version: u16) -> u32 {
|
||||||
((id as u32) << 16) | version as u32
|
((id as u32) << 16) | version as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The Subjects that identify the Accessor
|
||||||
pub struct AccessorSubjects([u64; MAX_ACCESSOR_SUBJECTS]);
|
pub struct AccessorSubjects([u64; MAX_ACCESSOR_SUBJECTS]);
|
||||||
|
|
||||||
impl AccessorSubjects {
|
impl AccessorSubjects {
|
||||||
|
@ -816,4 +820,34 @@ mod tests {
|
||||||
req.set_target_perms(Access::RWVA);
|
req.set_target_perms(Access::RWVA);
|
||||||
assert_eq!(req.allow(), true);
|
assert_eq!(req.allow(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_delete_for_fabric() {
|
||||||
|
let am = Arc::new(AclMgr::new_with(false).unwrap());
|
||||||
|
am.erase_all();
|
||||||
|
let path = GenericPath::new(Some(1), Some(1234), None);
|
||||||
|
let accessor2 = Accessor::new(2, AccessorSubjects::new(112233), AuthMode::Case, am.clone());
|
||||||
|
let mut req2 = AccessReq::new(&accessor2, &path, Access::READ);
|
||||||
|
req2.set_target_perms(Access::RWVA);
|
||||||
|
let accessor3 = Accessor::new(3, AccessorSubjects::new(112233), AuthMode::Case, am.clone());
|
||||||
|
let mut req3 = AccessReq::new(&accessor3, &path, Access::READ);
|
||||||
|
req3.set_target_perms(Access::RWVA);
|
||||||
|
|
||||||
|
// Allow for subject match - target is wildcard - Fabric idx 2
|
||||||
|
let mut new = AclEntry::new(2, Privilege::VIEW, AuthMode::Case);
|
||||||
|
new.add_subject(112233).unwrap();
|
||||||
|
am.add(new).unwrap();
|
||||||
|
|
||||||
|
// Allow for subject match - target is wildcard - Fabric idx 3
|
||||||
|
let mut new = AclEntry::new(3, Privilege::VIEW, AuthMode::Case);
|
||||||
|
new.add_subject(112233).unwrap();
|
||||||
|
am.add(new).unwrap();
|
||||||
|
|
||||||
|
// Req for Fabric idx 2 gets denied, and that for Fabric idx 3 is allowed
|
||||||
|
assert_eq!(req2.allow(), true);
|
||||||
|
assert_eq!(req3.allow(), true);
|
||||||
|
am.delete_for_fabric(2).unwrap();
|
||||||
|
assert_eq!(req2.allow(), false);
|
||||||
|
assert_eq!(req3.allow(), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,24 @@ impl NocCluster {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_command_rmfabric(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
|
||||||
|
cmd_enter!("Remove Fabric");
|
||||||
|
let req =
|
||||||
|
RemoveFabricReq::from_tlv(&cmd_req.data).map_err(|_| IMStatusCode::InvalidCommand)?;
|
||||||
|
if self.fabric_mgr.remove(req.fab_idx).is_ok() {
|
||||||
|
let _ = self.acl_mgr.delete_for_fabric(req.fab_idx);
|
||||||
|
cmd_req.trans.terminate();
|
||||||
|
} else {
|
||||||
|
NocCluster::create_nocresponse(
|
||||||
|
cmd_req.resp,
|
||||||
|
NocStatus::InvalidFabricIndex,
|
||||||
|
req.fab_idx,
|
||||||
|
"".to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_command_addnoc(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
|
fn handle_command_addnoc(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
|
||||||
cmd_enter!("AddNOC");
|
cmd_enter!("AddNOC");
|
||||||
if let Err(e) = self._handle_command_addnoc(cmd_req) {
|
if let Err(e) = self._handle_command_addnoc(cmd_req) {
|
||||||
|
@ -437,6 +455,7 @@ impl ClusterType for NocCluster {
|
||||||
Commands::AttReq => self.handle_command_attrequest(cmd_req),
|
Commands::AttReq => self.handle_command_attrequest(cmd_req),
|
||||||
Commands::CertChainReq => self.handle_command_certchainrequest(cmd_req),
|
Commands::CertChainReq => self.handle_command_certchainrequest(cmd_req),
|
||||||
Commands::UpdateFabricLabel => self.handle_command_updatefablabel(cmd_req),
|
Commands::UpdateFabricLabel => self.handle_command_updatefablabel(cmd_req),
|
||||||
|
Commands::RemoveFabric => self.handle_command_rmfabric(cmd_req),
|
||||||
_ => Err(IMStatusCode::UnsupportedCommand),
|
_ => Err(IMStatusCode::UnsupportedCommand),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -566,6 +585,11 @@ struct CertChainReq {
|
||||||
cert_type: u8,
|
cert_type: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromTLV)]
|
||||||
|
struct RemoveFabricReq {
|
||||||
|
fab_idx: u8,
|
||||||
|
}
|
||||||
|
|
||||||
fn get_certchainrequest_params(data: &TLVElement) -> Result<DataType, Error> {
|
fn get_certchainrequest_params(data: &TLVElement) -> Result<DataType, Error> {
|
||||||
let cert_type = CertChainReq::from_tlv(data)?.cert_type;
|
let cert_type = CertChainReq::from_tlv(data)?.cert_type;
|
||||||
|
|
||||||
|
|
|
@ -195,6 +195,17 @@ impl Fabric {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rm_store(&self, index: usize, psm: &MutexGuard<Psm>) {
|
||||||
|
psm.rm(fb_key!(index, ST_RCA));
|
||||||
|
psm.rm(fb_key!(index, ST_ICA));
|
||||||
|
psm.rm(fb_key!(index, ST_NOC));
|
||||||
|
psm.rm(fb_key!(index, ST_IPK));
|
||||||
|
psm.rm(fb_key!(index, ST_LBL));
|
||||||
|
psm.rm(fb_key!(index, ST_PBKEY));
|
||||||
|
psm.rm(fb_key!(index, ST_PRKEY));
|
||||||
|
psm.rm(fb_key!(index, ST_VID));
|
||||||
|
}
|
||||||
|
|
||||||
fn store(&self, index: usize, psm: &MutexGuard<Psm>) -> Result<(), Error> {
|
fn store(&self, index: usize, psm: &MutexGuard<Psm>) -> Result<(), Error> {
|
||||||
let mut key = [0u8; MAX_CERT_TLV_LEN];
|
let mut key = [0u8; MAX_CERT_TLV_LEN];
|
||||||
let len = self.root_ca.as_tlv(&mut key)?;
|
let len = self.root_ca.as_tlv(&mut key)?;
|
||||||
|
@ -335,6 +346,19 @@ impl FabricMgr {
|
||||||
Ok(index as u8)
|
Ok(index as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove(&self, fab_idx: u8) -> Result<(), Error> {
|
||||||
|
let fab_idx = fab_idx as usize;
|
||||||
|
let mut mgr = self.inner.write().unwrap();
|
||||||
|
let psm = self.psm.lock().unwrap();
|
||||||
|
if let Some(f) = &mgr.fabrics[fab_idx] {
|
||||||
|
f.rm_store(fab_idx, &psm);
|
||||||
|
mgr.fabrics[fab_idx] = None;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn match_dest_id(&self, random: &[u8], target: &[u8]) -> Result<usize, Error> {
|
pub fn match_dest_id(&self, random: &[u8], target: &[u8]) -> Result<usize, Error> {
|
||||||
let mgr = self.inner.read()?;
|
let mgr = self.inner.read()?;
|
||||||
for i in 0..MAX_SUPPORTED_FABRICS {
|
for i in 0..MAX_SUPPORTED_FABRICS {
|
||||||
|
|
|
@ -68,6 +68,16 @@ impl<'a> Transaction<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Terminates the transaction, no communication (even ACKs) happens hence forth
|
||||||
|
pub fn terminate(&mut self) {
|
||||||
|
self.state = TransactionState::Terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_terminate(&self) -> bool {
|
||||||
|
self.state == TransactionState::Terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks the transaction as completed from the application's perspective
|
||||||
pub fn complete(&mut self) {
|
pub fn complete(&mut self) {
|
||||||
self.state = TransactionState::Complete
|
self.state = TransactionState::Complete
|
||||||
}
|
}
|
||||||
|
@ -200,7 +210,9 @@ impl proto_demux::HandleProto for InteractionModel {
|
||||||
info!("Sending response");
|
info!("Sending response");
|
||||||
tlv::print_tlv_list(ctx.tx.as_borrow_slice());
|
tlv::print_tlv_list(ctx.tx.as_borrow_slice());
|
||||||
}
|
}
|
||||||
if trans.is_complete() {
|
if trans.is_terminate() {
|
||||||
|
ctx.exch_ctx.exch.terminate();
|
||||||
|
} else if trans.is_complete() {
|
||||||
ctx.exch_ctx.exch.close();
|
ctx.exch_ctx.exch.close();
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
|
|
|
@ -30,6 +30,7 @@ use self::{
|
||||||
pub enum TransactionState {
|
pub enum TransactionState {
|
||||||
Ongoing,
|
Ongoing,
|
||||||
Complete,
|
Complete,
|
||||||
|
Terminate,
|
||||||
}
|
}
|
||||||
pub struct Transaction<'a> {
|
pub struct Transaction<'a> {
|
||||||
pub state: TransactionState,
|
pub state: TransactionState,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
fs::{DirBuilder, File},
|
fs::{remove_file, DirBuilder, File},
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
sync::{Arc, Mutex, Once},
|
sync::{Arc, Mutex, Once},
|
||||||
};
|
};
|
||||||
|
@ -89,4 +89,8 @@ impl Psm {
|
||||||
*val = u64::from_be_bytes(vec.as_slice().try_into()?);
|
*val = u64::from_be_bytes(vec.as_slice().try_into()?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rm(&self, key: &str) {
|
||||||
|
let _ = remove_file(psm_path!(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,10 +48,15 @@ impl Default for Role {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State of the exchange
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum State {
|
enum State {
|
||||||
|
/// The exchange is open and active
|
||||||
Open,
|
Open,
|
||||||
|
/// The exchange is closed, but keys are active since retransmissions/acks may be pending
|
||||||
Close,
|
Close,
|
||||||
|
/// The exchange is terminated, keys are destroyed, no communication can happen
|
||||||
|
Terminate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for State {
|
impl Default for State {
|
||||||
|
@ -100,6 +105,11 @@ impl Exchange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn terminate(&mut self) {
|
||||||
|
self.data = DataOption::None;
|
||||||
|
self.state = State::Terminate;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn close(&mut self) {
|
pub fn close(&mut self) {
|
||||||
self.data = DataOption::None;
|
self.data = DataOption::None;
|
||||||
self.state = State::Close;
|
self.state = State::Close;
|
||||||
|
@ -111,7 +121,7 @@ impl Exchange {
|
||||||
|
|
||||||
pub fn is_purgeable(&self) -> bool {
|
pub fn is_purgeable(&self) -> bool {
|
||||||
// No Users, No pending ACKs/Retrans
|
// No Users, No pending ACKs/Retrans
|
||||||
self.state == State::Close && self.mrp.is_empty()
|
self.state == State::Terminate || (self.state == State::Close && self.mrp.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_id(&self) -> u16 {
|
pub fn get_id(&self) -> u16 {
|
||||||
|
@ -170,6 +180,11 @@ impl Exchange {
|
||||||
mut proto_tx: BoxSlab<PacketPool>,
|
mut proto_tx: BoxSlab<PacketPool>,
|
||||||
session: &mut SessionHandle,
|
session: &mut SessionHandle,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
if self.state == State::Terminate {
|
||||||
|
info!("Skipping tx for terminated exchange {}", self.id);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
trace!("payload: {:x?}", proto_tx.as_borrow_slice());
|
trace!("payload: {:x?}", proto_tx.as_borrow_slice());
|
||||||
info!(
|
info!(
|
||||||
"{} with proto id: {} opcode: {}",
|
"{} with proto id: {} opcode: {}",
|
||||||
|
|
Loading…
Add table
Reference in a new issue