webrtc/net/dcsctp/socket/state_cookie.cc
Victor Boivie a736f30a5f dcsctp: Negotiate zero checksum
If configured, attempt to negotiate "zero checksum
acceptable" capability, which will make the outgoing
packets have a fixed checksum of zero. Received
packets will not be verified for a correct checksum
if it's zero.

Also includes some boilerplate:
 - Setting capability in state cookie
 - Adding capability to handover state
 - Adding metric to know if the feature is used

This feature is not enabled by default, as it will be
first evaluated with an A/B experiment before making
it the default.

When the feature is enabled, lower CPU consumption for
both receiving and sending packets is expected. How
much depends on the architecture, as some architectures
have better support for generating CRC32 in hardware
than others.

Bug: webrtc:14997
Change-Id: If23f73e87220c7d42bd4f9a92772cda16bc18fcb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/299076
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39920}
2023-04-21 15:31:35 +00:00

84 lines
3.1 KiB
C++

/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "net/dcsctp/socket/state_cookie.h"
#include <cstdint>
#include <vector>
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/socket/capabilities.h"
#include "rtc_base/logging.h"
namespace dcsctp {
// Magic values, which the state cookie is prefixed with.
constexpr uint32_t kMagic1 = 1684230979;
constexpr uint32_t kMagic2 = 1414541360;
constexpr size_t StateCookie::kCookieSize;
std::vector<uint8_t> StateCookie::Serialize() {
std::vector<uint8_t> cookie;
cookie.resize(kCookieSize);
BoundedByteWriter<kCookieSize> buffer(cookie);
buffer.Store32<0>(kMagic1);
buffer.Store32<4>(kMagic2);
buffer.Store32<8>(*initiate_tag_);
buffer.Store32<12>(*initial_tsn_);
buffer.Store32<16>(a_rwnd_);
buffer.Store32<20>(static_cast<uint32_t>(*tie_tag_ >> 32));
buffer.Store32<24>(static_cast<uint32_t>(*tie_tag_));
buffer.Store8<28>(capabilities_.partial_reliability);
buffer.Store8<29>(capabilities_.message_interleaving);
buffer.Store8<30>(capabilities_.reconfig);
buffer.Store16<32>(capabilities_.negotiated_maximum_incoming_streams);
buffer.Store16<34>(capabilities_.negotiated_maximum_outgoing_streams);
buffer.Store8<36>(capabilities_.zero_checksum);
return cookie;
}
absl::optional<StateCookie> StateCookie::Deserialize(
rtc::ArrayView<const uint8_t> cookie) {
if (cookie.size() != kCookieSize) {
RTC_DLOG(LS_WARNING) << "Invalid state cookie: " << cookie.size()
<< " bytes";
return absl::nullopt;
}
BoundedByteReader<kCookieSize> buffer(cookie);
uint32_t magic1 = buffer.Load32<0>();
uint32_t magic2 = buffer.Load32<4>();
if (magic1 != kMagic1 || magic2 != kMagic2) {
RTC_DLOG(LS_WARNING) << "Invalid state cookie; wrong magic";
return absl::nullopt;
}
VerificationTag verification_tag(buffer.Load32<8>());
TSN initial_tsn(buffer.Load32<12>());
uint32_t a_rwnd = buffer.Load32<16>();
uint32_t tie_tag_upper = buffer.Load32<20>();
uint32_t tie_tag_lower = buffer.Load32<24>();
TieTag tie_tag(static_cast<uint64_t>(tie_tag_upper) << 32 |
static_cast<uint64_t>(tie_tag_lower));
Capabilities capabilities;
capabilities.partial_reliability = buffer.Load8<28>() != 0;
capabilities.message_interleaving = buffer.Load8<29>() != 0;
capabilities.reconfig = buffer.Load8<30>() != 0;
capabilities.negotiated_maximum_incoming_streams = buffer.Load16<32>();
capabilities.negotiated_maximum_outgoing_streams = buffer.Load16<34>();
capabilities.zero_checksum = buffer.Load8<36>() != 0;
return StateCookie(verification_tag, initial_tsn, a_rwnd, tie_tag,
capabilities);
}
} // namespace dcsctp