1use std::{ffi::CStr, fmt, str::FromStr};
4
5use crate::{
6 bindings::{
7 ip4_header_t, ip6_address_t, ip6_header_t, vlib_helper_format_ip4_header,
8 vlib_helper_format_ip6_header, vlib_helper_format_vnet_sw_if_index_name,
9 vlib_helper_unformat_vnet_sw_interface, vnet_get_main,
10 },
11 vppinfra,
12};
13
14impl ip6_address_t {
15 pub const fn new() -> Self {
17 Self { as_u8: [0; 16] }
18 }
19}
20
21impl ip6_header_t {
22 pub const fn new() -> Self {
24 Self {
25 ip_version_traffic_class_and_flow_label: 0,
26 payload_length: 0,
27 protocol: 0,
28 hop_limit: 0,
29 src_address: ip6_address_t::new(),
30 dst_address: ip6_address_t::new(),
31 }
32 }
33}
34
35impl fmt::Display for ip6_header_t {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 unsafe {
40 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip6_header(
41 std::ptr::null_mut(),
42 self,
43 std::mem::size_of::<Self>(),
44 ));
45 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
46 write!(f, "{}", cstr.to_string_lossy())
47 }
48 }
49}
50
51impl Clone for ip6_header_t {
52 fn clone(&self) -> Self {
53 unsafe {
56 Self {
57 ip_version_traffic_class_and_flow_label: std::ptr::read_unaligned(
58 std::ptr::addr_of!(self.ip_version_traffic_class_and_flow_label),
59 ),
60 payload_length: std::ptr::read_unaligned(std::ptr::addr_of!(self.payload_length)),
61 protocol: self.protocol,
62 hop_limit: self.hop_limit,
63 src_address: self.src_address,
64 dst_address: self.dst_address,
65 }
66 }
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
72pub struct SwIfIndex(u32);
73
74impl SwIfIndex {
75 pub const fn new(sw_if_index: u32) -> Self {
77 Self(sw_if_index)
78 }
79}
80
81impl fmt::Display for SwIfIndex {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 unsafe {
88 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_vnet_sw_if_index_name(
89 std::ptr::null_mut(),
90 vnet_get_main(),
91 self.0,
92 ));
93 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
94 write!(f, "{}", cstr.to_string_lossy())
95 }
96 }
97}
98
99impl From<u32> for SwIfIndex {
100 fn from(value: u32) -> Self {
101 Self(value)
102 }
103}
104
105impl From<SwIfIndex> for u32 {
106 fn from(value: SwIfIndex) -> Self {
107 value.0
108 }
109}
110
111impl FromStr for SwIfIndex {
112 type Err = ();
113
114 fn from_str(s: &str) -> Result<Self, Self::Err> {
115 let mut i = vppinfra::unformat::UnformatInput::from(s);
116 let mut sw_if_index = 0;
117 let ret = unsafe {
120 vlib_helper_unformat_vnet_sw_interface(i.as_ptr(), vnet_get_main(), &mut sw_if_index)
121 };
122 if ret > 0 {
123 Ok(Self(sw_if_index))
124 } else {
125 Err(())
126 }
127 }
128}
129
130impl fmt::Display for ip4_header_t {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 unsafe {
135 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip4_header(
136 std::ptr::null_mut(),
137 self,
138 std::mem::size_of::<Self>(),
139 ));
140 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
141 write!(f, "{}", cstr.to_string_lossy())
142 }
143 }
144}