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::Debug for ip6_header_t {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 <Self as fmt::Display>::fmt(self, f)
38 }
39}
40
41impl fmt::Display for ip6_header_t {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 unsafe {
46 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip6_header(
47 std::ptr::null_mut(),
48 self,
49 std::mem::size_of::<Self>(),
50 ));
51 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
52 write!(f, "{}", cstr.to_string_lossy())
53 }
54 }
55}
56
57impl Clone for ip6_header_t {
58 fn clone(&self) -> Self {
59 unsafe {
62 Self {
63 ip_version_traffic_class_and_flow_label: std::ptr::read_unaligned(
64 std::ptr::addr_of!(self.ip_version_traffic_class_and_flow_label),
65 ),
66 payload_length: std::ptr::read_unaligned(std::ptr::addr_of!(self.payload_length)),
67 protocol: self.protocol,
68 hop_limit: self.hop_limit,
69 src_address: self.src_address,
70 dst_address: self.dst_address,
71 }
72 }
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
78pub struct SwIfIndex(u32);
79
80impl SwIfIndex {
81 pub const LOCAL0: Self = SwIfIndex::new(0);
83
84 pub const fn new(sw_if_index: u32) -> Self {
86 Self(sw_if_index)
87 }
88}
89
90impl fmt::Display for SwIfIndex {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 unsafe {
97 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_vnet_sw_if_index_name(
98 std::ptr::null_mut(),
99 vnet_get_main(),
100 self.0,
101 ));
102 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
103 write!(f, "{}", cstr.to_string_lossy())
104 }
105 }
106}
107
108impl From<u32> for SwIfIndex {
109 fn from(value: u32) -> Self {
110 Self(value)
111 }
112}
113
114impl From<SwIfIndex> for u32 {
115 fn from(value: SwIfIndex) -> Self {
116 value.0
117 }
118}
119
120impl FromStr for SwIfIndex {
121 type Err = ();
122
123 fn from_str(s: &str) -> Result<Self, Self::Err> {
124 let mut i = vppinfra::unformat::UnformatInput::from(s);
125 let mut sw_if_index = 0;
126 let ret = unsafe {
129 vlib_helper_unformat_vnet_sw_interface(i.as_ptr(), vnet_get_main(), &mut sw_if_index)
130 };
131 if ret > 0 {
132 Ok(Self(sw_if_index))
133 } else {
134 Err(())
135 }
136 }
137}
138
139impl fmt::Debug for ip4_header_t {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 <Self as fmt::Display>::fmt(self, f)
142 }
143}
144
145impl fmt::Display for ip4_header_t {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 unsafe {
150 let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip4_header(
151 std::ptr::null_mut(),
152 self,
153 std::mem::size_of::<Self>(),
154 ));
155 let cstr = CStr::from_bytes_with_nul_unchecked(&s);
156 write!(f, "{}", cstr.to_string_lossy())
157 }
158 }
159}