added networking components, hosts are next

This commit is contained in:
2025-09-07 11:47:15 -04:00
commit 3411089908
59 changed files with 4777 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
#ifndef NETWORK_SWITCH_SWITCH_BUFFER_H
#define NETWORK_SWITCH_SWITCH_BUFFER_H
#include <cstdint>
#include <vector>
#include <deque>
#include <optional>
#include "core/time.h"
#include "core/types.h"
#include "core/simulator.h"
#include "core/error.h"
#include "network/packet.h"
#include "network/link.h"
namespace dofs {
class NetworkSwitch;
// Base class for switch egress buffering with weighted priorities.
// Implementations: SharedBuffer, DedicatedBuffer.
class SwitchBuffer {
public:
struct Queued {
Packet pkt;
PortId egress;
FlowPriority prio;
Time enq_time;
Bytes size_bytes;
};
virtual ~SwitchBuffer() = default;
// --- API: enqueue & drain ---
// NOTE: ECN/drop decisions are expected to be done *before* enqueue;
// we still guard and return false on capacity violations.
virtual bool enqueue_packet(const Packet& pkt,
PortId egress,
FlowPriority prio) = 0;
// Attempt to send exactly one packet on 'port' using weighted priorities.
// Returns true if a packet was reserved and scheduled.
virtual bool drain_one(PortId port) = 0;
// --- Accessors (implemented in .cc) ---
Bytes buffer_size() const noexcept;
SwitchBufferType type() const noexcept;
uint16_t port_cnt() const noexcept;
Bytes port_buffered(PortId p) const noexcept;
const std::vector<Bytes> &ports_buffered() const noexcept;
// Priority shares: percentages [0..100]. Sum must be 100.
uint8_t share_ctrl() const noexcept;
uint8_t share_mice() const noexcept;
uint8_t share_elephant() const noexcept;
// --- Mutators for priority shares (implemented in .cc) ---
// If the 3 shares don't sum to 100, we normalize proportionally.
void set_share_ctrl(uint8_t pct) noexcept;
void set_share_mice(uint8_t pct) noexcept;
void set_share_elephant(uint8_t pct) noexcept;
// Owner & env
const Simulator *simulator() const noexcept;
const NetworkSwitch *owner() const noexcept;
// Link wiring (egress side). Size must equal port_cnt().
void set_egress_links(const std::vector<Link*> &links);
protected:
SwitchBuffer(Simulator* const sim,
NetworkSwitch* const owner,
SwitchBufferType t,
Bytes total_bytes,
uint16_t ports);
// Per-priority index and helpers
static constexpr int PRI_COUNT = 3;
static constexpr int PRI_CTRL = 0;
static constexpr int PRI_MICE = 1;
static constexpr int PRI_ELE = 2;
static int to_idx(FlowPriority p) noexcept {
switch (p) {
case FlowPriority::CTRL:
return PRI_CTRL;
case FlowPriority::MICE:
return PRI_MICE;
case FlowPriority::ELEPHANT:
return PRI_ELE;
}
return PRI_ELE; // defensive
}
// Weighted Deficit Round Robin across priorities (per port):
// Maintain byte-deficits per prio; each drain attempt adds quantum
// proportional to the configured share. Pick first prio whose head fits.
struct PerPortSched {
std::array<int64_t, PRI_COUNT> deficit_bytes {0, 0, 0};
int next_pick = 0; // rotating pointer among priorities
};
// Quantum baseline (bytes) per "share unit". Calibrated to MSS-ish.
// Effective quantum = share_pct * QUANTUM_UNIT.
static constexpr int64_t QUANTUM_UNIT = 128; // bytes per % share
// For derived classes
bool drain_one_common(PortId port);
// Per-port self-scheduling
void schedule_drain_if_needed(PortId port);
void drain_once(PortId port); // event-loop callback
// Derived classes must expose queues and capacity guards:
// Access the 3 per-priority queues for a port.
virtual std::array<std::deque<Queued>, PRI_COUNT> &queues_for(PortId p) = 0;
virtual const std::array<std::deque<Queued>, PRI_COUNT> &queues_for(
PortId p) const = 0;
// Capacity checks and accounting; return false if not enough space.
virtual bool on_enqueue_cap_check(PortId port, Bytes sz) = 0;
virtual void on_enqueue_commit(PortId port, Bytes sz) = 0;
virtual void on_dequeue_commit(PortId port, Bytes sz) = 0;
// Attempt reservation+schedule on the egress link for (port, packet).
// Returns the reservation finish time if successful (for scheduling the next drain).
std::optional<Time> try_reserve_and_send(PortId port, Queued &q);
// Helpers
Bytes queued_bytes_total() const noexcept;
Bytes queued_bytes_port(PortId p) const noexcept;
protected:
Simulator *const _sim;
NetworkSwitch *const _owner;
SwitchBufferType _type;
Bytes _buffer_bytes;
uint16_t _port_cnt;
// Egress link per port (owned by switch; not by buffer)
std::vector<Link *> _egress_links;
std::vector<bool> _drain_scheduled;
// Per-port accounting and sched state
std::vector<Bytes> _per_port_bytes;
std::vector<PerPortSched> _sched; // per-port deficits
// Priority shares (percentages). Maintained to sum to 100.
uint8_t _share_ctrl;
uint8_t _share_mice;
uint8_t _share_ele;
};
} // namespace dofs
#endif // NETWORK_SWITCH_SWITCH_BUFFER_H