1use capsules_extra::ieee802154::device::MacDevice;
18use capsules_extra::net::icmpv6::icmpv6_send::{ICMP6SendStruct, ICMP6Sender};
19use capsules_extra::net::icmpv6::{ICMP6Header, ICMP6Type};
20use capsules_extra::net::ieee802154::MacAddress;
21use capsules_extra::net::ipv6::ip_utils::IPAddr;
22use capsules_extra::net::ipv6::ipv6_send::{IP6SendStruct, IP6Sender};
23use capsules_extra::net::ipv6::{IP6Packet, IPPayload, TransportHeader};
24use capsules_extra::net::network_capabilities::{
25 AddrRange, IpVisibilityCapability, NetworkCapability, PortRange,
26};
27use capsules_extra::net::sixlowpan::sixlowpan_compression;
28use capsules_extra::net::sixlowpan::sixlowpan_state::{Sixlowpan, SixlowpanState, TxState};
29use kernel::ErrorCode;
30
31use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
32use core::cell::Cell;
33use core::ptr::addr_of_mut;
34use kernel::capabilities::NetworkCapabilityCreationCapability;
35use kernel::create_capability;
36use kernel::debug;
37use kernel::hil::radio;
38use kernel::hil::time::{self, Alarm, ConvertTicks};
39use kernel::static_init;
40
41pub const SRC_ADDR: IPAddr = IPAddr([
42 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
43]);
44pub const DST_ADDR: IPAddr = IPAddr([
45 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
46]);
47
48const DEFAULT_CTX_PREFIX_LEN: u8 = 8;
50static DEFAULT_CTX_PREFIX: [u8; 16] = [0x0_u8; 16];
51static mut RX_STATE_BUF: [u8; 1280] = [0x0; 1280];
52const DST_MAC_ADDR: MacAddress = MacAddress::Short(0x802);
53const SRC_MAC_ADDR: MacAddress = MacAddress::Short(0xf00f);
54
55pub const TEST_DELAY_MS: u32 = 10000;
56pub const TEST_LOOP: bool = false;
57
58static mut ICMP_PAYLOAD: [u8; 10] = [0; 10];
59
60pub static mut RF233_BUF: [u8; radio::MAX_BUF_SIZE] = [0_u8; radio::MAX_BUF_SIZE];
61
62pub struct LowpanICMPTest<'a, A: time::Alarm<'a>> {
65 alarm: &'a A,
66 test_counter: Cell<usize>,
67 icmp_sender: &'a dyn ICMP6Sender<'a>,
68 net_cap: &'static NetworkCapability,
69}
70
71type Rf233 = capsules_extra::rf233::RF233<
72 'static,
73 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
74 'static,
75 sam4l::spi::SpiHw<'static>,
76 >,
77>;
78type Ieee802154MacDevice =
79 components::ieee802154::Ieee802154ComponentMacDeviceType<Rf233, sam4l::aes::Aes<'static>>;
80
81pub unsafe fn run(
82 mux_mac: &'static capsules_extra::ieee802154::virtual_mac::MuxMac<'static, Ieee802154MacDevice>,
83 mux_alarm: &'static MuxAlarm<'static, sam4l::ast::Ast>,
84) {
85 let create_cap = create_capability!(NetworkCapabilityCreationCapability);
86 let net_cap = static_init!(
87 NetworkCapability,
88 NetworkCapability::new(AddrRange::Any, PortRange::Any, PortRange::Any, &create_cap)
89 );
90 let ip_vis = static_init!(
91 IpVisibilityCapability,
92 IpVisibilityCapability::new(&create_cap)
93 );
94 let radio_mac = static_init!(
95 capsules_extra::ieee802154::virtual_mac::MacUser<'static, Ieee802154MacDevice>,
96 capsules_extra::ieee802154::virtual_mac::MacUser::new(mux_mac)
97 );
98 mux_mac.add_user(radio_mac);
99 let ipsender_virtual_alarm = static_init!(
100 VirtualMuxAlarm<'static, sam4l::ast::Ast>,
101 VirtualMuxAlarm::new(mux_alarm)
102 );
103 ipsender_virtual_alarm.setup();
104
105 let sixlowpan = static_init!(
106 Sixlowpan<
107 'static,
108 VirtualMuxAlarm<sam4l::ast::Ast<'static>>,
109 sixlowpan_compression::Context,
110 >,
111 Sixlowpan::new(
112 sixlowpan_compression::Context {
113 prefix: DEFAULT_CTX_PREFIX,
114 prefix_len: DEFAULT_CTX_PREFIX_LEN,
115 id: 0,
116 compress: false,
117 },
118 ipsender_virtual_alarm
119 )
120 );
121
122 let sixlowpan_state = sixlowpan as &dyn SixlowpanState;
123 let sixlowpan_tx = TxState::new(sixlowpan_state);
124
125 let icmp_hdr = ICMP6Header::new(ICMP6Type::Type128); let ip_pyld: IPPayload = IPPayload {
128 header: TransportHeader::ICMP(icmp_hdr),
129 payload: &mut *addr_of_mut!(ICMP_PAYLOAD),
130 };
131
132 let ip6_dg = static_init!(IP6Packet<'static>, IP6Packet::new(ip_pyld));
133
134 let ip6_sender = static_init!(
135 IP6SendStruct<'static, VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>>,
136 IP6SendStruct::new(
137 ip6_dg,
138 ipsender_virtual_alarm,
139 &mut *addr_of_mut!(RF233_BUF),
140 sixlowpan_tx,
141 radio_mac,
142 DST_MAC_ADDR,
143 SRC_MAC_ADDR,
144 ip_vis
145 )
146 );
147 radio_mac.set_transmit_client(ip6_sender);
148
149 let icmp_send_struct = static_init!(
150 ICMP6SendStruct<
151 'static,
152 IP6SendStruct<'static, VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>>,
153 >,
154 ICMP6SendStruct::new(ip6_sender)
155 );
156
157 let alarm = static_init!(
158 VirtualMuxAlarm<'static, sam4l::ast::Ast>,
159 VirtualMuxAlarm::new(mux_alarm)
160 );
161 alarm.setup();
162
163 let icmp_lowpan_test = static_init!(
164 LowpanICMPTest<'static, VirtualMuxAlarm<'static, sam4l::ast::Ast>>,
165 LowpanICMPTest::new(
166 alarm,
169 icmp_send_struct,
170 net_cap
171 )
172 );
173
174 ip6_sender.set_client(icmp_send_struct);
175 icmp_send_struct.set_client(icmp_lowpan_test);
176 icmp_lowpan_test.alarm.set_alarm_client(icmp_lowpan_test);
177 ipsender_virtual_alarm.set_alarm_client(ip6_sender);
178 icmp_lowpan_test.start();
179}
180
181impl<'a, A: time::Alarm<'a>> capsules_extra::net::icmpv6::icmpv6_send::ICMP6SendClient
182 for LowpanICMPTest<'a, A>
183{
184 fn send_done(&self, result: Result<(), ErrorCode>) {
185 match result {
186 Ok(()) => {
187 debug!("ICMP Echo Request Packet Sent!");
188 match self.test_counter.get() {
189 2 => debug!("Test completed successfully."),
190 _ => self.schedule_next(),
191 }
192 }
193 _ => debug!("Failed to send ICMP Packet!"),
194 }
195 }
196}
197
198impl<'a, A: time::Alarm<'a>> LowpanICMPTest<'a, A> {
199 pub fn new(
200 alarm: &'a A,
201 icmp_sender: &'a dyn ICMP6Sender<'a>,
202 net_cap: &'static NetworkCapability,
203 ) -> LowpanICMPTest<'a, A> {
204 LowpanICMPTest {
205 alarm,
206 test_counter: Cell::new(0),
207 icmp_sender,
208 net_cap,
209 }
210 }
211
212 pub fn start(&self) {
213 self.schedule_next();
214 }
215
216 fn schedule_next(&self) {
217 let delta = self.alarm.ticks_from_ms(TEST_DELAY_MS);
218 let now = self.alarm.now();
219 self.alarm.set_alarm(now, delta);
220 }
221
222 fn run_test_and_increment(&self) {
223 let test_counter = self.test_counter.get();
224 self.run_test(test_counter);
225 match TEST_LOOP {
226 true => self.test_counter.set((test_counter + 1) % self.num_tests()),
227 false => self.test_counter.set(test_counter + 1),
228 }
229 }
230
231 fn num_tests(&self) -> usize {
232 2
233 }
234
235 fn run_test(&self, test_id: usize) {
236 debug!("Running test {}:", test_id);
237 match test_id {
238 0 => self.ipv6_send_packet_test(),
239 1 => self.ipv6_send_packet_test(),
240 _ => {}
241 }
242 }
243
244 fn ipv6_send_packet_test(&self) {
245 unsafe {
246 self.send_ipv6_packet();
247 }
248 }
249
250 unsafe fn send_ipv6_packet(&self) {
251 self.send_next();
252 }
253
254 fn send_next(&self) {
255 let icmp_hdr = ICMP6Header::new(ICMP6Type::Type128); let _ = unsafe {
257 self.icmp_sender.send(
258 DST_ADDR,
259 icmp_hdr,
260 &mut *addr_of_mut!(ICMP_PAYLOAD),
261 self.net_cap,
262 )
263 };
264 }
265}
266
267impl<'a, A: time::Alarm<'a>> time::AlarmClient for LowpanICMPTest<'a, A> {
268 fn alarm(&self) {
269 self.run_test_and_increment();
270 }
271}