iris_core/protocols/packet/
ipv6.rs1use crate::memory::mbuf::Mbuf;
4use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
5use crate::utils::types::*;
6
7use std::net::Ipv6Addr;
8
9use anyhow::{bail, Result};
10
11const IPV6_PROTOCOL: usize = 0x86DD;
12const IPV6_HEADER_LEN: usize = 40;
13
14#[derive(Debug)]
18pub struct Ipv6<'a> {
19 header: Ipv6Header,
21 offset: usize,
23 mbuf: &'a Mbuf,
25}
26
27impl Ipv6<'_> {
28 #[inline]
30 pub fn version(&self) -> u8 {
31 let v: u32 = (self.header.version_to_flow_label & u32be::from(0xf000_0000)).into();
32 (v >> 28) as u8
33 }
34
35 #[inline]
37 pub fn dscp(&self) -> u8 {
38 let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0fc0_0000)).into();
39 (v >> 22) as u8
40 }
41
42 #[inline]
44 pub fn ecn(&self) -> u8 {
45 let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0030_0000)).into();
46 (v >> 20) as u8
47 }
48
49 #[inline]
51 pub fn traffic_class(&self) -> u8 {
52 let v: u32 = (self.header.version_to_flow_label & u32be::from(0x0ff0_0000)).into();
53 (v >> 20) as u8
54 }
55
56 #[inline]
58 pub fn flow_label(&self) -> u32 {
59 (self.header.version_to_flow_label & u32be::from(0x000f_ffff)).into()
60 }
61
62 #[inline]
64 pub fn version_to_flow_label(&self) -> u32 {
65 self.header.version_to_flow_label.into()
66 }
67
68 #[inline]
70 pub fn payload_length(&self) -> u16 {
71 self.header.payload_length.into()
72 }
73
74 #[inline]
76 pub fn next_header(&self) -> u8 {
77 self.header.next_header
78 }
79
80 #[inline]
82 pub fn hop_limit(&self) -> u8 {
83 self.header.hop_limit
84 }
85
86 #[inline]
88 pub fn src_addr(&self) -> Ipv6Addr {
89 self.header.src_addr
90 }
91
92 #[inline]
94 pub fn dst_addr(&self) -> Ipv6Addr {
95 self.header.dst_addr
96 }
97}
98
99impl<'a> Packet<'a> for Ipv6<'a> {
100 fn mbuf(&self) -> &Mbuf {
101 self.mbuf
102 }
103
104 fn header_len(&self) -> usize {
105 self.header.length()
106 }
107
108 fn next_header_offset(&self) -> usize {
109 self.offset + self.header_len()
110 }
111
112 fn next_header(&self) -> Option<usize> {
113 Some(self.next_header().into())
114 }
115
116 fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self>
117 where
118 Self: Sized,
119 {
120 let offset = outer.next_header_offset();
121 if let Ok(header) = outer.mbuf().get_data(offset) {
122 match outer.next_header() {
123 Some(IPV6_PROTOCOL) => Ok(Ipv6 {
124 header: unsafe { *header },
125 offset,
126 mbuf: outer.mbuf(),
127 }),
128 _ => bail!(PacketParseError::InvalidProtocol),
129 }
130 } else {
131 bail!(PacketParseError::InvalidRead)
132 }
133 }
134}
135
136#[derive(Debug, Clone, Copy)]
138#[repr(C)]
139struct Ipv6Header {
140 version_to_flow_label: u32be,
141 payload_length: u16be,
142 next_header: u8,
143 hop_limit: u8,
144 src_addr: Ipv6Addr,
145 dst_addr: Ipv6Addr,
146}
147
148impl PacketHeader for Ipv6Header {
149 fn length(&self) -> usize {
151 IPV6_HEADER_LEN
152 }
153}