1use crate::{
8 GPAddr, MonotonicInstant, NullableHandle, Signals, Status, VcpuContents, guest, ok, sys,
9};
10use bitflags::bitflags;
11use std::mem;
12
13#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
18#[repr(transparent)]
19pub struct Port(NullableHandle);
20impl_handle_based!(Port);
21
22bitflags! {
23 pub struct PortOptions: u32 {
25 const BIND_TO_INTERRUPT = sys::ZX_PORT_BIND_TO_INTERRUPT;
26 }
27}
28
29#[derive(Debug, Copy, Clone, Eq, PartialEq)]
31pub enum PacketContents {
32 User(UserPacket),
34 SignalOne(SignalPacket),
36 GuestBell(GuestBellPacket),
38 GuestMem(GuestMemPacket),
40 GuestIo(GuestIoPacket),
42 GuestVcpu(GuestVcpuPacket),
44 Pager(PagerPacket),
46 Interrupt(InterruptPacket),
48 PowerTransition(PowerTransitionPacket),
51
52 #[doc(hidden)]
53 __Nonexhaustive,
54}
55
56#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
59pub struct UserPacket(sys::zx_packet_user_t);
60
61#[derive(Copy, Clone, Debug, Eq, PartialEq)]
64pub struct SignalPacket(sys::zx_packet_signal_t);
65
66#[derive(Copy, Clone, Debug, Eq, PartialEq)]
69pub struct GuestBellPacket(sys::zx_packet_guest_bell_t);
70
71#[derive(Copy, Clone, Debug, Eq, PartialEq)]
74pub struct GuestMemPacket(sys::zx_packet_guest_mem_t);
75
76#[derive(Copy, Clone, Debug, Eq, PartialEq)]
79pub struct GuestIoPacket(sys::zx_packet_guest_io_t);
80
81#[derive(Copy, Clone, Debug, Eq, PartialEq)]
84pub struct GuestVcpuPacket(sys::zx_packet_guest_vcpu_t);
85
86#[derive(Copy, Clone, Debug, Eq, PartialEq)]
89pub struct PagerPacket(sys::zx_packet_page_request_t);
90
91#[derive(Copy, Clone, Debug, Eq, PartialEq)]
94pub struct InterruptPacket(sys::zx_packet_interrupt_t);
95
96#[derive(Copy, Clone, Debug, Eq, PartialEq)]
99pub struct PowerTransitionPacket(sys::zx_packet_processor_power_level_transition_request_t);
100
101#[derive(PartialEq, Eq, Debug)]
104pub struct Packet(pub(crate) sys::zx_port_packet_t);
105
106impl Packet {
107 pub fn from_user_packet(key: u64, status: i32, user: UserPacket) -> Packet {
109 Packet(sys::zx_port_packet_t {
110 key: key,
111 packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_USER,
112 status: status,
113 union: user.0,
114 })
115 }
116
117 pub fn from_guest_mem_packet(key: u64, status: i32, mem: GuestMemPacket) -> Packet {
119 let mut raw = sys::zx_port_packet_t {
120 key,
121 packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_MEM,
122 status,
123 union: Default::default(),
124 };
125 let bytes: &[u8; std::mem::size_of::<sys::zx_packet_guest_mem_t>()] =
133 unsafe { mem::transmute(&mem.0) };
134 raw.union[0..std::mem::size_of::<sys::zx_packet_guest_mem_t>()].copy_from_slice(bytes);
135 Packet(raw)
136 }
137
138 pub fn from_guest_io_packet(key: u64, status: i32, io: GuestIoPacket) -> Packet {
140 let mut raw = sys::zx_port_packet_t {
141 key,
142 packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_IO,
143 status,
144 union: Default::default(),
145 };
146 let bytes: &[u8; std::mem::size_of::<sys::zx_packet_guest_io_t>()] =
149 unsafe { mem::transmute(&io.0) };
150 raw.union[0..std::mem::size_of::<sys::zx_packet_guest_io_t>()].copy_from_slice(bytes);
151 Packet(raw)
152 }
153
154 pub fn from_guest_vcpu_packet(key: u64, status: i32, vcpu: GuestVcpuPacket) -> Packet {
156 Packet(sys::zx_port_packet_t {
157 key,
158 packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_VCPU,
159 status,
160 union: unsafe { mem::transmute_copy(&vcpu.0) },
161 })
162 }
163
164 pub fn from_power_transition_packet(
166 key: u64,
167 status: i32,
168 power_transition_packet: PowerTransitionPacket,
169 ) -> Packet {
170 Packet(sys::zx_port_packet_t {
171 key: key,
172 packet_type:
173 sys::zx_packet_type_t::ZX_PKT_TYPE_PROCESSOR_POWER_LEVEL_TRANSITION_REQUEST,
174 status: status,
175 union: unsafe { mem::transmute_copy(&power_transition_packet.0) },
176 })
177 }
178
179 pub fn key(&self) -> u64 {
181 self.0.key
182 }
183
184 pub fn status(&self) -> i32 {
187 self.0.status
188 }
189
190 pub fn contents(&self) -> PacketContents {
192 match self.0.packet_type {
193 sys::zx_packet_type_t::ZX_PKT_TYPE_USER => {
194 PacketContents::User(UserPacket(self.0.union))
195 }
196
197 sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_ONE => {
198 PacketContents::SignalOne(SignalPacket(unsafe {
199 mem::transmute_copy(&self.0.union)
200 }))
201 }
202
203 sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_BELL => {
204 PacketContents::GuestBell(GuestBellPacket(unsafe {
205 mem::transmute_copy(&self.0.union)
206 }))
207 }
208
209 sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_MEM => {
210 PacketContents::GuestMem(GuestMemPacket(unsafe {
211 mem::transmute_copy(&self.0.union)
212 }))
213 }
214
215 sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_IO => {
216 PacketContents::GuestIo(GuestIoPacket(unsafe {
217 mem::transmute_copy(&self.0.union)
218 }))
219 }
220
221 sys::zx_packet_type_t::ZX_PKT_TYPE_GUEST_VCPU => {
222 PacketContents::GuestVcpu(GuestVcpuPacket(unsafe {
223 mem::transmute_copy(&self.0.union)
224 }))
225 }
226
227 sys::zx_packet_type_t::ZX_PKT_TYPE_PAGE_REQUEST => {
228 PacketContents::Pager(PagerPacket(unsafe { mem::transmute_copy(&self.0.union) }))
229 }
230
231 sys::zx_packet_type_t::ZX_PKT_TYPE_INTERRUPT => {
232 PacketContents::Interrupt(InterruptPacket(unsafe {
233 mem::transmute_copy(&self.0.union)
234 }))
235 }
236
237 sys::zx_packet_type_t::ZX_PKT_TYPE_PROCESSOR_POWER_LEVEL_TRANSITION_REQUEST => {
238 PacketContents::PowerTransition(PowerTransitionPacket(unsafe {
239 mem::transmute_copy(&self.0.union)
240 }))
241 }
242
243 _ => panic!("unexpected packet type"),
244 }
245 }
246}
247
248impl UserPacket {
249 pub fn from_u8_array(val: [u8; 32]) -> UserPacket {
250 UserPacket(val)
251 }
252
253 pub fn as_u8_array(&self) -> &[u8; 32] {
254 &self.0
255 }
256
257 pub fn as_mut_u8_array(&mut self) -> &mut [u8; 32] {
258 &mut self.0
259 }
260}
261
262impl SignalPacket {
263 pub fn trigger(&self) -> Signals {
265 Signals::from_bits_truncate(self.0.trigger)
266 }
267
268 pub fn observed(&self) -> Signals {
270 Signals::from_bits_truncate(self.0.observed)
271 }
272
273 pub fn count(&self) -> u64 {
275 self.0.count
276 }
277
278 pub fn timestamp(&self) -> sys::zx_time_t {
280 self.0.timestamp
281 }
282
283 pub fn raw_packet(&self) -> &sys::zx_packet_signal_t {
285 &self.0
286 }
287}
288
289impl GuestBellPacket {
290 pub fn addr(&self) -> GPAddr {
292 GPAddr(self.0.addr)
293 }
294}
295
296impl GuestMemPacket {
297 pub fn from_raw(mem: sys::zx_packet_guest_mem_t) -> GuestMemPacket {
298 GuestMemPacket(mem)
299 }
300
301 pub fn addr(&self) -> GPAddr {
303 GPAddr(self.0.addr)
304 }
305}
306
307#[cfg(target_arch = "aarch64")]
308impl GuestMemPacket {
309 pub fn access_size(&self) -> Option<guest::MemAccessSize> {
313 match self.0.access_size {
314 1 => Some(guest::MemAccessSize::Bits8),
315 2 => Some(guest::MemAccessSize::Bits16),
316 4 => Some(guest::MemAccessSize::Bits32),
317 8 => Some(guest::MemAccessSize::Bits64),
318 _ => None,
319 }
320 }
321
322 pub fn sign_extend(&self) -> bool {
324 self.0.sign_extend
325 }
326
327 pub fn reg(&self) -> u8 {
329 self.0.xt
330 }
331
332 pub fn data(&self) -> Option<guest::MemData> {
334 if let guest::AccessType::Write = self.access_type() {
335 self.access_size().map(|size| match size {
336 guest::MemAccessSize::Bits8 => guest::MemData::Data8(self.0.data as u8),
337 guest::MemAccessSize::Bits16 => guest::MemData::Data16(self.0.data as u16),
338 guest::MemAccessSize::Bits32 => guest::MemData::Data32(self.0.data as u32),
339 guest::MemAccessSize::Bits64 => guest::MemData::Data64(self.0.data),
340 })
341 } else {
342 None
343 }
344 }
345
346 pub fn access_type(&self) -> guest::AccessType {
348 match self.0.read {
349 true => guest::AccessType::Read,
350 false => guest::AccessType::Write,
351 }
352 }
353}
354
355#[cfg(target_arch = "x86_64")]
356impl GuestMemPacket {
357 pub fn default_operand_size(&self) -> Option<guest::CSDefaultOperandSize> {
361 match self.0.default_operand_size {
363 2 => Some(guest::CSDefaultOperandSize::Bits16),
364 4 => Some(guest::CSDefaultOperandSize::Bits32),
365 _ => None,
366 }
367 }
368}
369
370impl GuestIoPacket {
371 pub fn from_raw(io: sys::zx_packet_guest_io_t) -> GuestIoPacket {
372 GuestIoPacket(io)
373 }
374
375 pub fn port(&self) -> u16 {
377 self.0.port
378 }
379
380 pub fn access_size(&self) -> Option<guest::PortAccessSize> {
384 match self.0.access_size {
385 1 => Some(guest::PortAccessSize::Bits8),
386 2 => Some(guest::PortAccessSize::Bits16),
387 4 => Some(guest::PortAccessSize::Bits32),
388 _ => None,
389 }
390 }
391
392 pub fn access_type(&self) -> guest::AccessType {
394 match self.0.input {
395 true => guest::AccessType::Read,
396 false => guest::AccessType::Write,
397 }
398 }
399
400 pub fn data(&self) -> Option<guest::PortData> {
402 #[repr(C)]
403 union DataUnion {
404 bit8: [u8; 4],
405 bit16: [u16; 2],
406 bit32: [u32; 1],
407 }
408 if let guest::AccessType::Write = self.access_type() {
409 unsafe {
410 let data = &DataUnion { bit8: self.0.data };
411 self.access_size().map(|size| match size {
412 guest::PortAccessSize::Bits8 => guest::PortData::Data8(data.bit8[0]),
413 guest::PortAccessSize::Bits16 => guest::PortData::Data16(data.bit16[0]),
414 guest::PortAccessSize::Bits32 => guest::PortData::Data32(data.bit32[0]),
415 })
416 }
417 } else {
418 None
419 }
420 }
421}
422
423impl GuestVcpuPacket {
424 pub fn from_raw(vcpu: sys::zx_packet_guest_vcpu_t) -> GuestVcpuPacket {
425 GuestVcpuPacket(vcpu)
426 }
427
428 pub fn contents(&self) -> VcpuContents {
429 match self.0.r#type {
430 sys::zx_packet_guest_vcpu_type_t::ZX_PKT_GUEST_VCPU_INTERRUPT => unsafe {
431 VcpuContents::Interrupt {
432 mask: self.0.union.interrupt.mask,
433 vector: self.0.union.interrupt.vector,
434 }
435 },
436 sys::zx_packet_guest_vcpu_type_t::ZX_PKT_GUEST_VCPU_STARTUP => unsafe {
437 VcpuContents::Startup {
438 id: self.0.union.startup.id,
439 entry: self.0.union.startup.entry,
440 }
441 },
442 _ => panic!("unexpected VCPU packet type"),
443 }
444 }
445}
446
447impl PagerPacket {
448 pub fn command(&self) -> sys::zx_page_request_command_t {
450 self.0.command
451 }
452
453 pub fn range(&self) -> std::ops::Range<u64> {
455 self.0.offset..self.0.offset + self.0.length
456 }
457}
458
459impl InterruptPacket {
460 pub fn timestamp(&self) -> sys::zx_time_t {
461 self.0.timestamp
462 }
463}
464
465impl PowerTransitionPacket {
466 pub fn from_raw(
467 packet: sys::zx_packet_processor_power_level_transition_request_t,
468 ) -> PowerTransitionPacket {
469 PowerTransitionPacket(packet)
470 }
471
472 pub fn domain_id(&self) -> u32 {
473 self.0.domain_id
474 }
475
476 pub fn options(&self) -> u32 {
477 self.0.options
478 }
479
480 pub fn control_interface(&self) -> u64 {
481 self.0.control_interface
482 }
483
484 pub fn control_argument(&self) -> u64 {
485 self.0.control_argument
486 }
487}
488
489impl Port {
490 pub fn create() -> Self {
501 Self::create_with_opts(PortOptions::from_bits_truncate(0))
502 }
503
504 pub fn create_with_opts(opts: PortOptions) -> Self {
505 unsafe {
506 let mut handle = 0;
507 let status = sys::zx_port_create(opts.bits(), &mut handle);
508 ok(status).expect(
509 "port creation always succeeds except with OOM or when job policy denies it",
510 );
511 NullableHandle::from_raw(handle).into()
512 }
513 }
514
515 pub fn queue(&self, packet: &Packet) -> Result<(), Status> {
521 let status =
522 unsafe { sys::zx_port_queue(self.raw_handle(), std::ptr::from_ref(&packet.0)) };
523 ok(status)
524 }
525
526 pub fn wait(&self, deadline: MonotonicInstant) -> Result<Packet, Status> {
532 let mut packet = Default::default();
533 ok(unsafe { sys::zx_port_wait(self.raw_handle(), deadline.into_nanos(), &mut packet) })?;
534 Ok(Packet(packet))
535 }
536
537 pub fn cancel(&self, key: u64) -> Result<(), Status> {
543 let options = 0;
544 let status = unsafe { sys::zx_port_cancel_key(self.raw_handle(), options, key) };
545 ok(status)
546 }
547}
548
549bitflags! {
550 #[repr(transparent)]
552 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
553 pub struct WaitAsyncOpts: u32 {
554 const TIMESTAMP = sys::ZX_WAIT_ASYNC_TIMESTAMP;
556
557 const BOOT_TIMESTAMP = sys::ZX_WAIT_ASYNC_BOOT_TIMESTAMP;
559
560 const EDGE_TRIGGERED = sys::ZX_WAIT_ASYNC_EDGE;
563 }
564}
565
566#[cfg(test)]
567mod tests {
568 use super::*;
569 use crate::{Duration, Event};
570 use assert_matches::assert_matches;
571
572 #[test]
573 fn port_basic() {
574 let ten_ms = Duration::from_millis(10);
575
576 let port = Port::create();
577
578 assert_eq!(port.wait(MonotonicInstant::after(ten_ms)), Err(Status::TIMED_OUT));
580
581 let packet = Packet::from_user_packet(42, 123, UserPacket::from_u8_array([13; 32]));
583 assert!(port.queue(&packet).is_ok());
584
585 let read_packet = port.wait(MonotonicInstant::after(ten_ms)).unwrap();
587 assert_eq!(read_packet, packet);
588 }
589
590 #[test]
591 fn create_with_opts() {
592 let _port = Port::create_with_opts(PortOptions::BIND_TO_INTERRUPT);
593 }
594
595 #[test]
596 fn wait_async_once() {
597 let ten_ms = Duration::from_millis(10);
598 let key = 42;
599
600 let port = Port::create();
601 let event = Event::create();
602 let no_opts = WaitAsyncOpts::empty();
603
604 assert!(event.wait_async(&port, key, Signals::USER_0 | Signals::USER_1, no_opts).is_ok());
605
606 assert_eq!(port.wait(MonotonicInstant::after(ten_ms)), Err(Status::TIMED_OUT));
608
609 assert!(event.signal(Signals::NONE, Signals::USER_0).is_ok());
611 let read_packet = port.wait(MonotonicInstant::after(ten_ms)).unwrap();
612 assert_eq!(read_packet.key(), key);
613 assert_eq!(read_packet.status(), 0);
614 match read_packet.contents() {
615 PacketContents::SignalOne(sig) => {
616 assert_eq!(sig.trigger(), Signals::USER_0 | Signals::USER_1);
617 assert_eq!(sig.observed(), Signals::USER_0);
618 assert_eq!(sig.count(), 1);
619 }
620 _ => panic!("wrong packet type"),
621 }
622
623 assert_eq!(port.wait(MonotonicInstant::after(ten_ms)), Err(Status::TIMED_OUT));
625
626 assert!(event.wait_async(&port, key, Signals::USER_0, no_opts).is_ok());
628 let read_packet = port.wait(MonotonicInstant::after(ten_ms)).unwrap();
629 assert_eq!(read_packet.key(), key);
630 assert_eq!(read_packet.status(), 0);
631 match read_packet.contents() {
632 PacketContents::SignalOne(sig) => {
633 assert_eq!(sig.trigger(), Signals::USER_0);
634 assert_eq!(sig.observed(), Signals::USER_0);
635 assert_eq!(sig.count(), 1);
636 }
637 _ => panic!("wrong packet type"),
638 }
639
640 assert!(event.wait_async(&port, key, Signals::USER_0, no_opts).is_ok());
643 assert!(port.cancel(key).is_ok());
644 assert_eq!(port.wait(MonotonicInstant::after(ten_ms)), Err(Status::TIMED_OUT));
645
646 assert!(event.signal(Signals::USER_0, Signals::NONE).is_ok()); assert!(event.wait_async(&port, key, Signals::USER_0, no_opts).is_ok());
649 assert!(port.cancel(key).is_ok());
650 assert!(event.signal(Signals::NONE, Signals::USER_0).is_ok());
651 assert_eq!(port.wait(MonotonicInstant::after(ten_ms)), Err(Status::TIMED_OUT));
652 }
653
654 #[test]
655 fn guest_mem_packet() {
656 #[cfg(target_arch = "x86_64")]
657 let guest_mem_packet = sys::zx_packet_guest_mem_t {
658 addr: 0xaaaabbbbccccdddd,
659 cr3: 0x0123456789abcdef,
660 rip: 0xffffffff00000000,
661 instruction_size: 8,
662 default_operand_size: 2,
663 };
664 #[cfg(target_arch = "aarch64")]
665 let guest_mem_packet = sys::zx_packet_guest_mem_t {
666 addr: 0x8877665544332211,
667 access_size: 8,
668 sign_extend: true,
669 xt: 0xf3,
670 read: false,
671 data: 0x1122334455667788,
672 };
673 #[cfg(target_arch = "riscv64")]
674 let guest_mem_packet = {
675 let mut ret = sys::zx_packet_guest_mem_t::default();
676 ret.addr = 0x8877665544332211;
677 ret
678 };
679 const KEY: u64 = 0x5555555555555555;
680 const STATUS: i32 = sys::ZX_ERR_INTERNAL;
681
682 let packet =
683 Packet::from_guest_mem_packet(KEY, STATUS, GuestMemPacket::from_raw(guest_mem_packet));
684
685 assert_matches!(packet.contents(), PacketContents::GuestMem(GuestMemPacket(packet)) if packet == guest_mem_packet);
686 assert_eq!(packet.key(), KEY);
687 assert_eq!(packet.status(), STATUS);
688 }
689
690 #[test]
691 fn guest_io_packet() {
692 const GUEST_IO_PACKET: sys::zx_packet_guest_io_t = sys::zx_packet_guest_io_t {
693 port: 0xabcd,
694 access_size: 4,
695 input: true,
696 data: [0xaa, 0xbb, 0xcc, 0xdd],
697 };
698 const KEY: u64 = 0x0123456789abcdef;
699 const STATUS: i32 = sys::ZX_ERR_NO_RESOURCES;
700
701 let packet =
702 Packet::from_guest_io_packet(KEY, STATUS, GuestIoPacket::from_raw(GUEST_IO_PACKET));
703
704 assert_matches!(packet.contents(), PacketContents::GuestIo(GuestIoPacket(packet)) if packet == GUEST_IO_PACKET);
705 assert_eq!(packet.key(), KEY);
706 assert_eq!(packet.status(), STATUS);
707 }
708
709 #[test]
710 fn guest_vcpu_interrupt_packet() {
711 let mut guest_vcpu_packet = sys::zx_packet_guest_vcpu_t::default();
713 guest_vcpu_packet.r#type = sys::zx_packet_guest_vcpu_type_t::ZX_PKT_GUEST_VCPU_INTERRUPT;
714 guest_vcpu_packet.union = sys::zx_packet_guest_vcpu_union_t {
715 interrupt: {
716 let mut interrupt = sys::zx_packet_guest_vcpu_interrupt_t::default();
717 interrupt.mask = 0xaaaaaaaaaaaaaaaa;
718 interrupt.vector = 0x12;
719 interrupt
720 },
721 };
722 const KEY: u64 = 0x0123456789abcdef;
723 const STATUS: i32 = sys::ZX_ERR_NO_RESOURCES;
724
725 let packet = Packet::from_guest_vcpu_packet(
726 KEY,
727 STATUS,
728 GuestVcpuPacket::from_raw(guest_vcpu_packet),
729 );
730
731 assert_matches!(packet.contents(), PacketContents::GuestVcpu(GuestVcpuPacket(packet)) if packet == guest_vcpu_packet);
732 assert_eq!(packet.key(), KEY);
733 assert_eq!(packet.status(), STATUS);
734 }
735
736 #[test]
737 fn guest_vcpu_startup_packet() {
738 let mut guest_vcpu_packet = sys::zx_packet_guest_vcpu_t::default();
739 guest_vcpu_packet.r#type = sys::zx_packet_guest_vcpu_type_t::ZX_PKT_GUEST_VCPU_STARTUP;
740 guest_vcpu_packet.union = sys::zx_packet_guest_vcpu_union_t {
741 startup: sys::zx_packet_guest_vcpu_startup_t { id: 16, entry: 0xffffffff11111111 },
742 };
743 const KEY: u64 = 0x0123456789abcdef;
744 const STATUS: i32 = sys::ZX_ERR_NO_RESOURCES;
745
746 let packet = Packet::from_guest_vcpu_packet(
747 KEY,
748 STATUS,
749 GuestVcpuPacket::from_raw(guest_vcpu_packet),
750 );
751
752 assert_matches!(packet.contents(), PacketContents::GuestVcpu(GuestVcpuPacket(packet)) if packet == guest_vcpu_packet);
753 assert_eq!(packet.key(), KEY);
754 assert_eq!(packet.status(), STATUS);
755 }
756
757 #[test]
758 fn power_transition_packet() {
759 let power_transition_packet =
760 sys::zx_packet_processor_power_level_transition_request_t::default();
761 const KEY: u64 = 0x0123456789abcdef;
762 const STATUS: i32 = sys::ZX_ERR_NO_RESOURCES;
763
764 let packet = Packet::from_power_transition_packet(
765 KEY,
766 STATUS,
767 PowerTransitionPacket::from_raw(power_transition_packet),
768 );
769
770 assert_matches!(
771 packet.contents(),
772 PacketContents::PowerTransition(PowerTransitionPacket(packet)) if packet == power_transition_packet
773 );
774 assert_eq!(packet.key(), KEY);
775 assert_eq!(packet.status(), STATUS);
776 }
777}