|
| 1 | +// This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | +// License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | +// file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 4 | + |
| 5 | +// Copyright 2025 Oxide Computer Company |
| 6 | + |
| 7 | +#[cfg(feature = "kernel")] |
| 8 | +use crate::mblk_t; |
| 9 | +use bitflags::bitflags; |
| 10 | + |
| 11 | +// ====================================================================== |
| 12 | +// uts/common/sys/mac_provider.h |
| 13 | +// ====================================================================== |
| 14 | + |
| 15 | +bitflags! { |
| 16 | +#[repr(C)] |
| 17 | +#[derive(Clone, Copy, Debug, Default)] |
| 18 | +/// Flags which denote the valid fields of a `mac_ether_offload_info_t` |
| 19 | +/// or `mac_ether_tun_info_t`. |
| 20 | +/// |
| 21 | +/// These are derived from `mac_ether_offload_flags_t` (mac_provider.h, |
| 22 | +/// omitting the `MEOI_` prefix). |
| 23 | +pub struct MacEtherOffloadFlags: u32 { |
| 24 | + /// `l2hlen` and `l3proto` are set. |
| 25 | + const L2INFO_SET = 1 << 0; |
| 26 | + /// `l3hlen` and `l4proto` are set. |
| 27 | + const L3INFO_SET = 1 << 1; |
| 28 | + /// `l4hlen` is set. |
| 29 | + const L4INFO_SET = 1 << 2; |
| 30 | + /// `tunhlen` is set. |
| 31 | + const TUNINFO_SET = 1 << 3; |
| 32 | + /// The ethernet header contains a VLAN tag. |
| 33 | + const VLAN_TAGGED = 1 << 4; |
| 34 | + /// The packet is fragmented at L3, and this packet is not the last |
| 35 | + /// fragment. L4 headers are expected to be present. |
| 36 | + const L3_FRAG_MORE = 1 << 5; |
| 37 | + /// The packet is fragmented at L3, and this packet is not the first |
| 38 | + /// fragment. |
| 39 | + const L3_FRAG_OFFSET = 1 << 6; |
| 40 | +} |
| 41 | +} |
| 42 | + |
| 43 | +#[repr(C)] |
| 44 | +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] |
| 45 | +/// The type of tunnel in use for a packet's outermost layer. |
| 46 | +/// |
| 47 | +/// These are derived from `mac_ether_tun_type_t` (mac_provider.h, |
| 48 | +/// omitting the `METT_` prefix). |
| 49 | +pub struct MacTunType(u32); |
| 50 | + |
| 51 | +impl MacTunType { |
| 52 | + pub const NONE: Self = Self(0); |
| 53 | + pub const GENEVE: Self = Self(1); |
| 54 | + pub const VXLAN: Self = Self(2); |
| 55 | +} |
| 56 | + |
| 57 | +#[repr(C)] |
| 58 | +#[derive(Clone, Copy, Debug, Default)] |
| 59 | +pub struct mac_ether_offload_info_t { |
| 60 | + pub meoi_flags: MacEtherOffloadFlags, |
| 61 | + pub meoi_tuntype: MacTunType, |
| 62 | + pub meoi_len: u32, |
| 63 | + pub meoi_l2hlen: u8, |
| 64 | + pub meoi_l3proto: u16, |
| 65 | + pub meoi_l3hlen: u16, |
| 66 | + pub meoi_l4proto: u8, |
| 67 | + pub meoi_l4hlen: u8, |
| 68 | + pub meoi_tunhlen: u16, |
| 69 | +} |
| 70 | + |
| 71 | +#[cfg(feature = "kernel")] |
| 72 | +unsafe extern "C" { |
| 73 | + pub fn lso_info_set(mp: *mut mblk_t, mss: u32, flags: u32); |
| 74 | + pub fn lso_info_cleanup(mp: *mut mblk_t); |
| 75 | + pub fn mac_hcksum_set( |
| 76 | + mp: *mut mblk_t, |
| 77 | + start: u32, |
| 78 | + stuff: u32, |
| 79 | + end: u32, |
| 80 | + value: u32, |
| 81 | + flags: u32, |
| 82 | + ); |
| 83 | + pub fn mac_hcksum_get( |
| 84 | + mp: *mut mblk_t, |
| 85 | + start: *mut u32, |
| 86 | + stuff: *mut u32, |
| 87 | + end: *mut u32, |
| 88 | + value: *mut u32, |
| 89 | + flags: *mut u32, |
| 90 | + ); |
| 91 | + pub fn mac_lso_get(mp: *mut mblk_t, mss: *mut u32, flags: *mut u32); |
| 92 | + pub fn mac_ether_set_pktinfo( |
| 93 | + mp: *mut mblk_t, |
| 94 | + outer_info: *const mac_ether_offload_info_t, |
| 95 | + inner_info: *const mac_ether_offload_info_t, |
| 96 | + ); |
| 97 | +} |
| 98 | + |
| 99 | +// ====================================================================== |
| 100 | +// uts/common/sys/pattr.h |
| 101 | +// ====================================================================== |
| 102 | + |
| 103 | +bitflags! { |
| 104 | +/// Flags which denote checksum and LSO state for an `mblk_t`. |
| 105 | +/// |
| 106 | +/// These are derived from `#define`s in pattr.h. |
| 107 | +#[derive(Copy, Clone, Debug, Eq, PartialEq)] |
| 108 | +pub struct MblkOffloadFlags: u32 { |
| 109 | + /// Tx: IPv4 header checksum must be computed by hardware. |
| 110 | + const HCK_IPV4_HDRCKSUM = 1 << 0; |
| 111 | + /// Rx: IPv4 header checksum was verified correct by hardware. |
| 112 | + const HCK_IPV4_HDRCKSUM_OK = Self::HCK_IPV4_HDRCKSUM.bits(); |
| 113 | + /// * Tx: Compute partial checksum based on start/stuff/end offsets. |
| 114 | + /// * Rx: Partial checksum computed and attached. |
| 115 | + const HCK_PARTIALCKSUM = 1 << 1; |
| 116 | + /// * Tx: Compute full (pseudo + l4 + payload) cksum for this packet. |
| 117 | + /// * Rx: Full checksum was computed in hardware, and is attached. |
| 118 | + const HCK_FULLCKSUM = 1 << 2; |
| 119 | + /// Rx: Hardware has verified that L3/L4 checksums are correct. |
| 120 | + const HCK_FULLCKSUM_OK = 1 << 3; |
| 121 | + /// Tx: Hardware must perform LSO. |
| 122 | + const HW_LSO = 1 << 4; |
| 123 | + /// Tx: The inner frame's IPv4 header checksum must be computed by |
| 124 | + /// hardware. |
| 125 | + const HCK_INNER_V4CKSUM = 1 << 5; |
| 126 | + /// Rx: The inner frame's IPv4 header checksum was verified correct by |
| 127 | + /// hardware. |
| 128 | + const HCK_INNER_V4CKSUM_OK = 1 << 6; |
| 129 | + /// * Tx: Compute inner L4 partial checksum based on MEOI parse offsets. |
| 130 | + const HCK_INNER_PARTIAL = 1 << 7; |
| 131 | + /// * Tx: Compute full (pseudo + l4 + payload) cksum for this packet's |
| 132 | + /// inner L4. |
| 133 | + const HCK_INNER_FULL = 1 << 8; |
| 134 | + /// Rx: Hardware has verified that inner L3/L4 checksums are correct. |
| 135 | + const HCK_INNER_FULL_OK = 1 << 9; |
| 136 | + /// The union of all checksum-related flags. |
| 137 | + const HCK_FLAGS = Self::HCK_IPV4_HDRCKSUM.bits() | |
| 138 | + Self::HCK_PARTIALCKSUM.bits() | Self::HCK_FULLCKSUM.bits() | |
| 139 | + Self::HCK_FULLCKSUM_OK.bits() | Self::HCK_INNER_V4CKSUM.bits() | |
| 140 | + Self::HCK_INNER_V4CKSUM_OK.bits() | Self::HCK_INNER_PARTIAL.bits() | |
| 141 | + Self::HCK_INNER_FULL.bits() | Self::HCK_INNER_FULL_OK.bits(); |
| 142 | + /// The union of all checksum-related flags used in the transmit path |
| 143 | + /// (i.e., indicating missing checksums). |
| 144 | + const HCK_TX_FLAGS = Self::HCK_IPV4_HDRCKSUM.bits() | |
| 145 | + Self::HCK_PARTIALCKSUM.bits() | Self::HCK_FULLCKSUM.bits() | |
| 146 | + Self::HCK_INNER_V4CKSUM.bits() | Self::HCK_INNER_PARTIAL.bits() | |
| 147 | + Self::HCK_INNER_FULL.bits(); |
| 148 | + /// The union of all checksum-related flags used in the transmit path |
| 149 | + /// for outer headers (untunnelled packets and encap layers). |
| 150 | + const HCK_OUTER_TX_FLAGS = Self::HCK_IPV4_HDRCKSUM.bits() | |
| 151 | + Self::HCK_PARTIALCKSUM.bits() | Self::HCK_FULLCKSUM.bits(); |
| 152 | + /// The union of all checksum-related flags for outer headers (untunnelled |
| 153 | + /// packets and encap layers). |
| 154 | + const HCK_OUTER_FLAGS = Self::HCK_OUTER_TX_FLAGS.bits() | |
| 155 | + Self::HCK_IPV4_HDRCKSUM_OK.bits() | Self::HCK_FULLCKSUM_OK.bits(); |
| 156 | + /// The union of all checksum-related flags used in the transmit path |
| 157 | + /// for inner headers (tunnelled packets). |
| 158 | + const HCK_INNER_TX_FLAGS = Self::HCK_INNER_V4CKSUM.bits() | |
| 159 | + Self::HCK_INNER_PARTIAL.bits() | Self::HCK_INNER_FULL.bits(); |
| 160 | + /// The union of all checksum-related flags for inner headers (tunnelled |
| 161 | + /// packets). |
| 162 | + const HCK_INNER_FLAGS = Self::HCK_INNER_TX_FLAGS.bits() | |
| 163 | + Self::HCK_INNER_V4CKSUM_OK.bits() | Self::HCK_INNER_FULL_OK.bits(); |
| 164 | + /// The union of all LSO-related flags. |
| 165 | + const HW_LSO_FLAGS = Self::HW_LSO.bits(); |
| 166 | +} |
| 167 | +} |
| 168 | + |
| 169 | +impl MblkOffloadFlags { |
| 170 | + /// Move any outer offload flags to the inner layer, as part of |
| 171 | + /// encapsulation. |
| 172 | + pub fn shift_in(self) -> Self { |
| 173 | + let mut out = |
| 174 | + self.difference(Self::HCK_INNER_FLAGS.union(Self::HCK_OUTER_FLAGS)); |
| 175 | + |
| 176 | + if self.contains(Self::HCK_IPV4_HDRCKSUM) { |
| 177 | + out |= Self::HCK_INNER_V4CKSUM; |
| 178 | + } |
| 179 | + |
| 180 | + if self.contains(Self::HCK_PARTIALCKSUM) { |
| 181 | + out |= Self::HCK_INNER_PARTIAL; |
| 182 | + } |
| 183 | + |
| 184 | + if self.contains(Self::HCK_FULLCKSUM) { |
| 185 | + out |= Self::HCK_INNER_FULL; |
| 186 | + } |
| 187 | + |
| 188 | + if self.contains(Self::HCK_FULLCKSUM_OK) { |
| 189 | + out |= Self::HCK_INNER_FULL_OK; |
| 190 | + } |
| 191 | + |
| 192 | + out |
| 193 | + } |
| 194 | +} |
0 commit comments