s2n_quic_core/xdp/
path.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    inet::{ethernet::MacAddress, ipv4, IpAddress},
6    path::{self, Handle},
7};
8
9#[cfg(any(test, feature = "generator"))]
10use bolero_generator::prelude::*;
11
12macro_rules! define_address {
13    ($name:ident) => {
14        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
15        #[cfg_attr(any(test, feature = "generator"), derive(TypeGenerator))]
16        pub struct $name {
17            pub mac: MacAddress,
18            pub ip: IpAddress,
19            pub port: u16,
20        }
21
22        impl $name {
23            pub const UNSPECIFIED: Self = Self {
24                mac: MacAddress::UNSPECIFIED,
25                ip: IpAddress::Ipv4(ipv4::IpV4Address::UNSPECIFIED),
26                port: 0,
27            };
28
29            #[inline]
30            pub fn unmap(self) -> Self {
31                Self {
32                    mac: self.mac,
33                    ip: self.ip.unmap(),
34                    port: self.port,
35                }
36            }
37        }
38
39        impl From<path::$name> for $name {
40            #[inline]
41            fn from(addr: path::$name) -> Self {
42                Self {
43                    mac: MacAddress::UNSPECIFIED,
44                    ip: addr.ip(),
45                    port: addr.port(),
46                }
47            }
48        }
49
50        impl From<$name> for path::$name {
51            #[inline]
52            fn from(addr: $name) -> Self {
53                addr.ip.with_port(addr.port).into()
54            }
55        }
56    };
57}
58
59define_address!(RemoteAddress);
60define_address!(LocalAddress);
61
62#[derive(Clone, Copy, Debug, Eq, PartialEq)]
63#[cfg_attr(any(test, feature = "generator"), derive(TypeGenerator))]
64pub struct Tuple {
65    pub remote_address: RemoteAddress,
66    pub local_address: LocalAddress,
67}
68
69impl Tuple {
70    pub const UNSPECIFIED: Self = Self {
71        remote_address: RemoteAddress::UNSPECIFIED,
72        local_address: LocalAddress::UNSPECIFIED,
73    };
74
75    #[inline]
76    pub fn swap(&mut self) {
77        core::mem::swap(&mut self.remote_address.mac, &mut self.local_address.mac);
78        core::mem::swap(&mut self.remote_address.ip, &mut self.local_address.ip);
79        core::mem::swap(&mut self.remote_address.port, &mut self.local_address.port);
80    }
81}
82
83impl Handle for Tuple {
84    #[inline]
85    fn from_remote_address(remote_address: path::RemoteAddress) -> Self {
86        let remote_address = remote_address.into();
87        let local_address = LocalAddress::UNSPECIFIED;
88        Self {
89            remote_address,
90            local_address,
91        }
92    }
93
94    #[inline]
95    fn remote_address(&self) -> path::RemoteAddress {
96        self.remote_address.into()
97    }
98
99    #[inline]
100    fn set_remote_address(&mut self, addr: path::RemoteAddress) {
101        self.remote_address.ip = addr.ip();
102        self.remote_address.port = addr.port();
103    }
104
105    #[inline]
106    fn local_address(&self) -> path::LocalAddress {
107        self.local_address.into()
108    }
109
110    #[inline]
111    fn set_local_address(&mut self, addr: path::LocalAddress) {
112        self.local_address.ip = addr.ip();
113        self.local_address.port = addr.port();
114    }
115
116    #[inline]
117    fn unmapped_eq(&self, other: &Self) -> bool {
118        // TODO only compare everything if the other is all filled out
119        PartialEq::eq(&self.local_address.unmap(), &other.local_address.unmap())
120            && PartialEq::eq(&self.remote_address.unmap(), &other.remote_address.unmap())
121    }
122
123    #[inline]
124    fn strict_eq(&self, other: &Self) -> bool {
125        PartialEq::eq(self, other)
126    }
127
128    #[inline]
129    fn maybe_update(&mut self, other: &Self) {
130        if other.local_address.port == 0 {
131            return;
132        }
133
134        // once we discover our path, or the port changes, update the address with the new information
135        if self.local_address.port != other.local_address.port {
136            *self = *other;
137        }
138    }
139}