mirror of
https://github.com/chirpstack/chirpstack.git
synced 2024-12-22 14:32:24 +00:00
Fix sending empty downlink to Relay (adr_ack_req=true).
In case a Relay would send an uplink with adr_ack_req=true, this would not result in an empty downlink in case there is no downlink to relay back to the relay end-device.
This commit is contained in:
parent
3538145e3d
commit
8e6079ec9c
@ -287,6 +287,10 @@ impl Data {
|
||||
ctx.save_downlink_frame_relayed().await?;
|
||||
ctx.save_device_session().await?;
|
||||
ctx.send_downlink_frame().await?;
|
||||
} else if ctx._must_respond_to_relay() {
|
||||
ctx.set_phy_payloads_relay()?;
|
||||
ctx.save_downlink_frame_relayed().await?;
|
||||
ctx.send_downlink_frame().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -635,6 +639,11 @@ impl Data {
|
||||
true
|
||||
}
|
||||
|
||||
fn _must_respond_to_relay(&self) -> bool {
|
||||
let relay_ctx = self.relay_context.as_ref().unwrap();
|
||||
relay_ctx.must_ack || relay_ctx.must_send_downlink
|
||||
}
|
||||
|
||||
fn _is_class_a(&self) -> bool {
|
||||
self.device.enabled_class == DeviceClass::A
|
||||
}
|
||||
@ -862,6 +871,53 @@ impl Data {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_phy_payloads_relay(&mut self) -> Result<()> {
|
||||
trace!("Set relay PhyPayloads");
|
||||
|
||||
let relay_ctx = self.relay_context.as_ref().unwrap();
|
||||
|
||||
for item in self.downlink_frame_items.iter_mut() {
|
||||
let mut relay_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
fhdr: lrwn::FHDR {
|
||||
devaddr: lrwn::DevAddr::from_slice(&relay_ctx.device_session.dev_addr)?,
|
||||
f_cnt: relay_ctx.device_session.get_a_f_cnt_down(),
|
||||
f_ctrl: lrwn::FCtrl {
|
||||
adr: !self.network_conf.adr_disabled,
|
||||
ack: relay_ctx.must_ack,
|
||||
..Default::default()
|
||||
},
|
||||
f_opts: lrwn::MACCommandSet::new(vec![]),
|
||||
},
|
||||
f_port: None,
|
||||
frm_payload: None,
|
||||
}),
|
||||
mic: None,
|
||||
};
|
||||
|
||||
// Set MIC.
|
||||
// If this is an ACK, then FCntUp has already been incremented by one. If
|
||||
// this is not an ACK, then DownlinkDataMIC will zero out ConfFCnt.
|
||||
relay_phy.set_downlink_data_mic(
|
||||
relay_ctx.device_session.mac_version().from_proto(),
|
||||
relay_ctx.device_session.f_cnt_up - 1,
|
||||
&lrwn::AES128Key::from_slice(&relay_ctx.device_session.s_nwk_s_int_key)?,
|
||||
)?;
|
||||
|
||||
let relay_phy_b = relay_phy.to_vec()?;
|
||||
item.downlink_frame_item.phy_payload = relay_phy_b;
|
||||
self.downlink_frame
|
||||
.items
|
||||
.push(item.downlink_frame_item.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_device_queue_item(&mut self) -> Result<()> {
|
||||
trace!("Updating device queue-item");
|
||||
if let Some(qi) = &mut self.device_queue_item {
|
||||
|
@ -243,7 +243,7 @@ async fn test_lorawan_10() {
|
||||
wor_channel: 0,
|
||||
},
|
||||
frequency: 868100000,
|
||||
payload: Box::new(phy_relay_ed_unconfirmed_up),
|
||||
payload: Box::new(phy_relay_ed_unconfirmed_up.clone()),
|
||||
})),
|
||||
}),
|
||||
mic: None,
|
||||
@ -262,6 +262,49 @@ async fn test_lorawan_10() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut phy_relay_unconfirmed_up_adr_ack_req = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
fhdr: lrwn::FHDR {
|
||||
devaddr: lrwn::DevAddr::from_slice(&ds_relay.dev_addr).unwrap(),
|
||||
f_cnt: 8,
|
||||
f_ctrl: lrwn::FCtrl {
|
||||
adr_ack_req: true,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
f_port: Some(lrwn::LA_FPORT_RELAY),
|
||||
frm_payload: Some(lrwn::FRMPayload::ForwardUplinkReq(lrwn::ForwardUplinkReq {
|
||||
metadata: lrwn::UplinkMetadata {
|
||||
dr: 5,
|
||||
snr: 10,
|
||||
rssi: -100,
|
||||
wor_channel: 0,
|
||||
},
|
||||
frequency: 868100000,
|
||||
payload: Box::new(phy_relay_ed_unconfirmed_up),
|
||||
})),
|
||||
}),
|
||||
mic: None,
|
||||
};
|
||||
phy_relay_unconfirmed_up_adr_ack_req
|
||||
.encrypt_frm_payload(&AES128Key::from_slice(&ds_relay.nwk_s_enc_key).unwrap())
|
||||
.unwrap();
|
||||
phy_relay_unconfirmed_up_adr_ack_req
|
||||
.set_uplink_data_mic(
|
||||
lrwn::MACVersion::LoRaWAN1_0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&AES128Key::from_slice(&ds_relay.f_nwk_s_int_key).unwrap(),
|
||||
&AES128Key::from_slice(&ds_relay.s_nwk_s_int_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut phy_relay_confirmed_up = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
@ -365,6 +408,34 @@ async fn test_lorawan_10() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut phy_relay_unconfirmed_down_empty = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
fhdr: lrwn::FHDR {
|
||||
devaddr: lrwn::DevAddr::from_slice(&ds_relay.dev_addr).unwrap(),
|
||||
f_cnt: 5,
|
||||
f_ctrl: lrwn::FCtrl {
|
||||
adr: true,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
f_port: None,
|
||||
frm_payload: None,
|
||||
}),
|
||||
mic: None,
|
||||
};
|
||||
phy_relay_unconfirmed_down_empty
|
||||
.set_downlink_data_mic(
|
||||
lrwn::MACVersion::LoRaWAN1_0,
|
||||
0,
|
||||
&AES128Key::from_slice(&ds_relay.s_nwk_s_int_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tests = vec![
|
||||
Test {
|
||||
name: "relayed unconfirmed uplink".into(),
|
||||
@ -554,6 +625,129 @@ async fn test_lorawan_10() {
|
||||
}),
|
||||
],
|
||||
},
|
||||
Test {
|
||||
name: "relayed unconfirmed uplink + adr_ack_req".into(),
|
||||
device_queue_items_relay_ed: vec![],
|
||||
device_session_relay: Some(ds_relay.clone()),
|
||||
device_session_relay_ed: Some(ds_relay_ed.clone()),
|
||||
tx_info: tx_info.clone(),
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: phy_relay_unconfirmed_up_adr_ack_req,
|
||||
assert: vec![
|
||||
assert::f_cnt_up(dev_relay.dev_eui, 9),
|
||||
assert::f_cnt_up(dev_relay_ed.dev_eui, 89),
|
||||
assert::uplink_event(integration_pb::UplinkEvent {
|
||||
device_info: Some(integration_pb::DeviceInfo {
|
||||
tenant_id: t.id.to_string(),
|
||||
tenant_name: t.name.clone(),
|
||||
application_id: app.id.to_string(),
|
||||
application_name: app.name.clone(),
|
||||
device_profile_id: dp_relay.id.to_string(),
|
||||
device_profile_name: dp_relay.name.clone(),
|
||||
device_name: dev_relay.name.clone(),
|
||||
dev_eui: dev_relay.dev_eui.to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
dev_addr: "01010101".to_string(),
|
||||
dr: 5,
|
||||
f_cnt: 8,
|
||||
f_port: 226,
|
||||
data: vec![],
|
||||
rx_info: vec![rx_info.clone()],
|
||||
tx_info: Some(tx_info.clone()),
|
||||
..Default::default()
|
||||
}),
|
||||
assert::uplink_event(integration_pb::UplinkEvent {
|
||||
device_info: Some(integration_pb::DeviceInfo {
|
||||
tenant_id: t.id.to_string(),
|
||||
tenant_name: t.name.clone(),
|
||||
application_id: app.id.to_string(),
|
||||
application_name: app.name.clone(),
|
||||
device_profile_id: dp_relay_ed.id.to_string(),
|
||||
device_profile_name: dp_relay_ed.name.clone(),
|
||||
device_name: dev_relay_ed.name.clone(),
|
||||
dev_eui: dev_relay_ed.dev_eui.to_string(),
|
||||
..Default::default()
|
||||
}),
|
||||
dev_addr: "02020202".to_string(),
|
||||
dr: 5,
|
||||
f_cnt: 88,
|
||||
f_port: 1,
|
||||
data: vec![1, 2, 3, 4],
|
||||
rx_info: vec![rx_info.clone()],
|
||||
tx_info: Some(tx_info.clone()),
|
||||
relay_rx_info: Some(integration_pb::UplinkRelayRxInfo {
|
||||
dev_eui: "0101010101010101".into(),
|
||||
frequency: 868100000,
|
||||
dr: 5,
|
||||
snr: 10,
|
||||
rssi: -100,
|
||||
wor_channel: 0,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
assert::downlink_frame(gw::DownlinkFrame {
|
||||
gateway_id: gw.gateway_id.to_string(),
|
||||
items: vec![
|
||||
gw::DownlinkFrameItem {
|
||||
phy_payload: phy_relay_unconfirmed_down_empty.to_vec().unwrap(),
|
||||
tx_info: Some(gw::DownlinkTxInfo {
|
||||
frequency: 868100000,
|
||||
power: 16,
|
||||
modulation: Some(gw::Modulation {
|
||||
parameters: Some(gw::modulation::Parameters::Lora(
|
||||
gw::LoraModulationInfo {
|
||||
bandwidth: 125000,
|
||||
spreading_factor: 7,
|
||||
code_rate: gw::CodeRate::Cr45.into(),
|
||||
polarization_inversion: true,
|
||||
..Default::default()
|
||||
},
|
||||
)),
|
||||
}),
|
||||
timing: Some(gw::Timing {
|
||||
parameters: Some(gw::timing::Parameters::Delay(
|
||||
gw::DelayTimingInfo {
|
||||
delay: Some(Duration::from_secs(1).into()),
|
||||
},
|
||||
)),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
gw::DownlinkFrameItem {
|
||||
phy_payload: phy_relay_unconfirmed_down_empty.to_vec().unwrap(),
|
||||
tx_info: Some(gw::DownlinkTxInfo {
|
||||
frequency: 869525000,
|
||||
power: 29,
|
||||
modulation: Some(gw::Modulation {
|
||||
parameters: Some(gw::modulation::Parameters::Lora(
|
||||
gw::LoraModulationInfo {
|
||||
bandwidth: 125000,
|
||||
spreading_factor: 12,
|
||||
code_rate: gw::CodeRate::Cr45.into(),
|
||||
polarization_inversion: true,
|
||||
..Default::default()
|
||||
},
|
||||
)),
|
||||
}),
|
||||
timing: Some(gw::Timing {
|
||||
parameters: Some(gw::timing::Parameters::Delay(
|
||||
gw::DelayTimingInfo {
|
||||
delay: Some(Duration::from_secs(2).into()),
|
||||
},
|
||||
)),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
..Default::default()
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
for test in &tests {
|
||||
|
@ -1305,8 +1305,8 @@ impl Data {
|
||||
async fn handle_forward_uplink_req(&self) -> Result<()> {
|
||||
trace!("Handling ForwardUplinkReq");
|
||||
|
||||
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||
if let Some(lrwn::FRMPayload::ForwardUplinkReq(pl)) = &pl.frm_payload {
|
||||
if let lrwn::Payload::MACPayload(relay_pl) = &self.phy_payload.payload {
|
||||
if let Some(lrwn::FRMPayload::ForwardUplinkReq(pl)) = &relay_pl.frm_payload {
|
||||
match pl.payload.mhdr.m_type {
|
||||
lrwn::MType::JoinRequest => {
|
||||
super::join::JoinRequest::handle_relayed(
|
||||
@ -1317,6 +1317,7 @@ impl Data {
|
||||
device_session: self.device_session.as_ref().unwrap().clone(),
|
||||
must_ack: self.phy_payload.mhdr.m_type
|
||||
== lrwn::MType::ConfirmedDataUp,
|
||||
must_send_downlink: relay_pl.fhdr.f_ctrl.adr_ack_req,
|
||||
},
|
||||
self.uplink_frame_set.clone(),
|
||||
)
|
||||
@ -1331,6 +1332,7 @@ impl Data {
|
||||
device_session: self.device_session.as_ref().unwrap().clone(),
|
||||
must_ack: self.phy_payload.mhdr.m_type
|
||||
== lrwn::MType::ConfirmedDataUp,
|
||||
must_send_downlink: relay_pl.fhdr.f_ctrl.adr_ack_req,
|
||||
},
|
||||
self.device_gateway_rx_info.as_ref().unwrap().clone(),
|
||||
self.uplink_frame_set.clone(),
|
||||
|
@ -78,6 +78,7 @@ pub struct RelayContext {
|
||||
pub device_profile: device_profile::DeviceProfile,
|
||||
pub device_session: internal::DeviceSession,
|
||||
pub must_ack: bool,
|
||||
pub must_send_downlink: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
Loading…
Reference in New Issue
Block a user