26#include <boost/asio/ip/address_v4.hpp>
28#include <unordered_map>
36#include <seastar/core/array_map.hh>
37#include <seastar/net/byteorder.hh>
38#include <seastar/core/byteorder.hh>
39#include <seastar/net/arp.hh>
40#include <seastar/net/ip_checksum.hh>
41#include <seastar/net/const.hh>
42#include <seastar/net/packet-util.hh>
43#include <seastar/core/shared_ptr.hh>
44#include <seastar/net/toeplitz.hh>
45#include <seastar/net/udp.hh>
47#include <seastar/util/modules.hh>
49#include "ipv4_address.hh"
50#include "ipv6_address.hh"
57template <ip_protocol_num ProtoNum>
60template <
typename InetTraits>
70 ip_protocol_num proto_num;
72 using packet_provider_type = std::function<std::optional<l4packet> ()>;
74 csum.sum_many(src.ip.raw, dst.ip.raw, uint8_t(0), uint8_t(ip_protocol_num::tcp), len);
77 csum.sum_many(src.ip.raw, dst.ip.raw, uint8_t(0), uint8_t(ip_protocol_num::udp), len);
79 static constexpr uint8_t ip_hdr_len_min = ipv4_hdr_len_min;
82template <ip_protocol_num ProtoNum>
88 void register_packet_provider(ipv4_traits::packet_provider_type func);
90 const ipv4& inet()
const {
100 std::ignore = out_hash_data;
107template <
typename InetTraits>
109 using ipaddr =
typename InetTraits::address_type;
110 using inet_type =
typename InetTraits::inet_type;
116 uint16_t foreign_port;
118 bool operator==(
const l4connid& x)
const {
119 return local_ip == x.local_ip
120 && foreign_ip == x.foreign_ip
121 && local_port == x.local_port
122 && foreign_port == x.foreign_port;
125 uint32_t hash(rss_key_type rss_key) {
127 hash_data.push_back(hton(foreign_ip.ip));
128 hash_data.push_back(hton(local_ip.ip));
129 hash_data.push_back(hton(foreign_port));
130 hash_data.push_back(hton(local_port));
131 return toeplitz_hash(rss_key, hash_data);
137 std::unique_ptr<tcp<ipv4_traits>> _tcp;
147 enum class msg_type : uint8_t {
155 template <
typename Adjuster>
156 auto adjust_endianness(Adjuster a) {
167 _inet.register_packet_provider([
this] {
168 std::optional<ipv4_traits::l4packet> l4p;
169 if (!_packetq.empty()) {
170 l4p = std::move(_packetq.front());
171 _packetq.pop_front();
172 _queue_space.signal(l4p.value().p.len());
190 _icmp.received(std::move(p), from, to);
200 static const int default_queue_size;
202 static const uint16_t min_anonymous_port = 32768;
204 std::unordered_map<uint16_t, lw_shared_ptr<udp_channel_state>> _channels;
205 int _queue_size = default_queue_size;
206 uint16_t _next_anonymous_port = min_anonymous_port;
209 uint16_t next_port(uint16_t port);
219 _proto._channels.erase(_proto._channels.find(_port));
222 uint16_t port()
const {
232 void set_queue_size(
int size) { _queue_size = size; }
234 const ipv4& inet()
const {
250 uint16_t identification;
253 return src_ip == x.src_ip &&
254 dst_ip == x.dst_ip &&
255 identification == x.identification &&
256 protocol == x.protocol;
261 private std::hash<uint16_t>,
private std::hash<uint8_t> {
262 size_t operator()(
const ipv4_frag_id&
id)
const noexcept {
263 using h1 = std::hash<ipv4_address>;
264 using h2 = std::hash<uint16_t>;
265 using h3 = std::hash<uint8_t>;
266 return h1::operator()(
id.src_ip) ^
267 h1::operator()(
id.dst_ip) ^
268 h2::operator()(
id.identification) ^
269 h3::operator()(
id.protocol);
280 using proto_type = uint16_t;
282 static proto_type arp_protocol_type() {
return proto_type(eth_protocol_num::ipv4); }
285 std::vector<ipv4_traits::packet_provider_type> _pkt_providers;
300 clock_type::time_point rx_time;
301 uint32_t mem_size = 0;
303 bool last_frag_received =
false;
309 std::unordered_map<ipv4_frag_id, frag, ipv4_frag_id::hash> _frags;
310 std::list<ipv4_frag_id> _frags_age;
311 static constexpr std::chrono::seconds _frag_timeout{30};
312 static constexpr uint32_t _frag_low_thresh{3 * 1024 * 1024};
313 static constexpr uint32_t _frag_high_thresh{4 * 1024 * 1024};
314 uint32_t _frag_mem{0};
317 unsigned _pkt_provider_idx = 0;
322 std::optional<l3_protocol::l3packet> get_packet();
324 void frag_limit_mem();
326 void frag_drop(
ipv4_frag_id frag_id, uint32_t dropped_size);
327 void frag_arm(clock_type::time_point
now) {
328 auto tp =
now + _frag_timeout;
343 interface * netif()
const {
353 ipv4_udp& get_udp() {
return _udp; }
354 void register_l4(proto_type
id,
ip_protocol* handler);
360 void register_packet_provider(ipv4_traits::packet_provider_type&& func) {
361 _pkt_providers.push_back(std::move(func));
366template <ip_protocol_num ProtoNum>
369 _inet.register_packet_provider([func = std::move(func)] {
372 l4p.value().proto_num = ProtoNum;
378template <ip_protocol_num ProtoNum>
380future<ethernet_address> ipv4_l4<ProtoNum>::get_l2_dst_address(ipv4_address to) {
381 return _inet.get_l2_dst_address(to);
392 enum class frag_bits : uint8_t { mf = 13, df = 14, reserved = 15, offset_shift = 3 };
399 template <
typename Adjuster>
400 auto adjust_endianness(Adjuster a) {
401 return a(len,
id, frag, csum, src_ip, dst_ip);
403 bool mf() {
return frag & (1 << uint8_t(frag_bits::mf)); }
404 bool df() {
return frag & (1 << uint8_t(frag_bits::df)); }
405 uint16_t offset() {
return frag << uint8_t(frag_bits::offset_shift); }
408template <
typename InetTraits>
411 using h1 = std::hash<ipaddr>;
412 using h2 = std::hash<uint16_t>;
413 return h1::operator()(
id.local_ip)
414 ^ h1::operator()(
id.foreign_ip)
415 ^ h2::operator()(
id.local_port)
416 ^ h2::operator()(
id.foreign_port);
Definition: array_map.hh:39
Definition: circular_buffer.hh:63
A representation of a possibly not-yet-computed value.
Definition: future.hh:1240
Low-resolution and efficient steady clock.
Definition: lowres_clock.hh:56
static time_point now() noexcept
Definition: lowres_clock.hh:74
holds the metric definition.
Definition: metrics_registration.hh:94
void arm(time_point until, std::optional< duration > period={}) noexcept
future now()
Returns a ready future.
Definition: later.hh:35
holds the metric_groups definition needed by class that reports metrics
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: socket_defs.hh:113
Definition: ip_checksum.hh:38
Definition: ethernet.hh:37
Definition: ipv4_address.hh:35
Definition: unaligned.hh:58