33 static constexpr
unsigned
34 DEBUG_INGRESS = (1u << 0),
35 DEBUG_PLUGIN = (1u << 1),
36 DEBUG_PLUGOUT = (1u << 2),
37 DEBUG_DELIVERY = (1u << 3),
38 DEBUG_EGRESS = (1u << 4);
42 #ifndef SATCAT5_SWITCH_DEBUG
43 #define SATCAT5_SWITCH_DEBUG (DEBUG_PLUGOUT)
47 static constexpr
unsigned DEBUG_VERBOSE = 0;
49 SwitchCore::SwitchCore(u8* buff,
unsigned nbytes)
50 : MultiBuffer(buff, nbytes)
61 void SwitchCore::plugin_add(
PluginCore* plugin)
63 void SwitchCore::plugin_remove(
PluginCore* plugin)
71 satcat5::util::clr_mask(m_free_pmask, lsb);
77 satcat5::util::clr_mask(m_free_pmask, port->port_mask());
84 port_remove(port->port_mask());
91 satcat5::util::set_mask(m_free_pmask, mask);
96 satcat5::util::set_mask_if(m_prom_mask, mask, enable);
100 m_stats_filter = etype;
105 u32 temp = m_stats_count;
113 if (!meta.read_from(packet)) {
124 if (plg_result)
return plg_result.value();
128 satcat5::util::set_mask(meta.dst_mask, m_prom_mask);
129 satcat5::util::clr_mask(meta.dst_mask, meta.src_mask());
136 unsigned enable = (SATCAT5_SWITCH_DEBUG) & mask;
137 if (m_debug && enable) {
138 MultiPacket::Reader rd(pkt.
pkt);
140 rd.read_consume(pkt.
hlen);
143 rd.copy_and_finalize(m_debug);
148 Header hdr = satcat5::eth::HEADER_NULL;
150 if (m_pktlogs.head()) {
154 auto rd = pkt->
peek();
156 src_port = u8(pkt->
m_user[0]);
171 item = m_pktlogs.
next(item);
181 if ((!m_stats_filter) || (m_stats_filter == meta.
hdr.
type.
value)) {
196 if (result)
return result;
204 if (result)
return result;
211 MultiPacket::Overwriter wr(meta.
pkt);
213 if (wr.write_count() != meta.
hlen) {
214 Log(CRITICAL,
"Plugin changed header length.");
224 if (DEBUG_VERBOSE > 1) {
226 Log(DEBUG,
"SwitchCore::deliver")
253 if (port->accept(meta.
dst_mask, meta.
pkt)) ++count;
262 if (DEBUG_VERBOSE > 0)
270 , m_port_mask(sw->next_port_mask())
271 , m_port_index(satcat5::util::log2_floor(m_port_mask))
280 else Log(CRITICAL,
"SwitchPort overflow");
285 #if SATCAT5_ALLOW_DELETION
286 SwitchPort::~SwitchPort() {
302 if (DEBUG_VERBOSE > 1)
Log(DEBUG,
"SwitchPort::plugin_ingress");
317 if (DEBUG_VERBOSE > 1)
Log(DEBUG,
"SwitchPort::plugin_egress");
332 MultiWriter::write_abort();
340 static_assert(SATCAT5_MBUFF_USER >= 2,
341 "SATCAT5_MBUFF_USER must be at least 2.");
350 }
else if (MultiWriter::write_finalize()) {
359 MultiWriter::write_abort();
369 if (DEBUG_VERBOSE > 0)
Log(DEBUG,
"SwitchPort::data_rcvd");
380 if (pkt.dst_mask == 0) {
383 }
else if (pkt.is_adjusted()) {
401 if (DEBUG_VERBOSE > 1)
Log(DEBUG,
"VlanAdapter::data_rcvd::fin");
Ethernet switch plugin API.
virtual void query(PluginPacket &pkt)=0
Packet-received callback.
Ethernet port plugin API.
virtual void egress(PluginPacket &pkt)
Packet-transmit callback.
virtual void ingress(PluginPacket &pkt)
Packet-received callback.
A shared-memory Ethernet switch based on the MultiBuffer class.
satcat5::util::List< satcat5::eth::SwitchPort > m_ports
Linked list of attached Ethernet ports.
unsigned deliver(satcat5::io::MultiPacket *packet) override
Override the MultiBuffer::deliver() method.
unsigned deliver_switch(const satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
satcat5::util::optional< unsigned > process_plugins(satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
satcat5::util::List< satcat5::eth::PluginCore > m_plugins
Linked list of attached plugins.
satcat5::util::optional< unsigned > pkt_has_dropped(satcat5::eth::PluginPacket &pkt, unsigned mask)
Internal event-handlers called from deliver(...).
void set_promiscuous(unsigned port_idx, bool enable)
Enable or disable "promiscuous" flag on the specified port index.
u32 get_traffic_count()
Query traffic statistics Count received frames that match the current traffic filter,...
satcat5::eth::SwitchPort * get_port(unsigned idx)
Fetch a SwitchPort object by port-index.
void process_stats(const satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
SATCAT5_PMASK_TYPE next_port_mask()
Get next available bit-mask for new SwitchPort objects.
void debug_log(const satcat5::io::MultiPacket *pkt, u8 reason, SATCAT5_PMASK_TYPE dst=0) const
If logging is enabled, record the outcome for this packet.
void debug_if(const satcat5::eth::PluginPacket &pkt, unsigned mask) const
Carbon-copy a packet to the debug port, if it is enabled.
void set_traffic_filter(u16 etype=0)
Configure EtherType filter for traffic reporting. (0 = Any type)
Define the API for packet-logging callbacks from eth::SwitchCore.
virtual void log_packet(const satcat5::eth::SwitchLogMessage &msg)=0
This method is called exactly once for each incoming packet.
Generic packetized I/O interface for use with SwitchCore.
const unsigned m_port_index
Define this port's connection to the switch.
void plugin_ingress(satcat5::eth::PluginPacket &pkt)
Issue notifications to all attached plugins.
bool write_finalize() override
Override write_finalize() to store metadata.
SATCAT5_PMASK_TYPE m_port_mask
Define this port's connection to the switch.
void write_abort() override
Override write_abort() to allow additional error handling.
void data_rcvd(satcat5::io::Readable *src) override
The data_rcvd() callback is polled whenever data is available.
void plugin_remove(satcat5::eth::PluginPort *plugin)
Plugin management.
bool m_eg_hdr
Frame header copied?
satcat5::eth::VtagPolicy m_vlan_cfg
Metadata required for VLAN functionality.
satcat5::eth::SwitchCore *const m_switch
Pointer to the associated switch.
satcat5::util::List< satcat5::eth::PluginPort > m_plugins
Linked list of attached plugins.
satcat5::io::Writeable *const m_eg_dst
Egress destination.
SwitchPort(satcat5::eth::SwitchCore *sw, satcat5::io::Writeable *dst)
Link this port to the designated switch.
void plugin_add(satcat5::eth::PluginPort *plugin)
Plugin management.
satcat5::io::MultiReaderPriority m_egress
Egress data source.
void plugin_egress(satcat5::eth::PluginPacket &pkt)
Issue notifications to all attached plugins.
bool accept(SATCAT5_PMASK_TYPE dst_mask, satcat5::io::MultiPacket *packet)
Accept delivery of a given packet?
unsigned get_read_ready() const override
How many bytes can be read without blocking?
bool read_consume(unsigned nbytes) override
Read and discard 0 or more bytes.
satcat5::io::MultiPacket * get_packet() const
Get a pointer to the current packet, if active.
virtual bool accept(satcat5::io::MultiPacket *packet)
Accept a packet from the source buffer? Default accepts all packets unless this port is disabled or f...
void read_finalize() override
Consume any remaining bytes in this frame, if applicable.
bool get_port_enable() const
Is this port currently enabled?
satcat5::io::MultiPacket * m_write_pkt
Current write state.
Abstract API for reading byte-streams and packets.
virtual void set_callback(satcat5::io::EventListener *callback)
Update registered callback for data_rcvd() events.
unsigned copy_to(satcat5::io::Writeable *dst)
Copy data to a Writeable object, without finalizing.
Abstract API for writing byte-streams and packets.
virtual unsigned get_write_space() const =0
How many bytes can be written without blocking?
virtual bool write_finalize()
Mark end of frame and release temporary working data.
The Log class creates and formats one log message.
Log & write10(s32 val)
Print integer as a decimal value with no leading zeros.
Log & write(const char *str)
Formatting methods for various data types.
T * next(const T *item) const
Fetch pointer to the next item.
void push_back(T *item)
Add a new item at the tail of the list.
void add(T *item)
Add new item to front or back, whichever is simpler.
void remove(T *item)
Remove the designated item from the list.
Plugins for the software-defined Ethernet switch and IPv4 router.
Diagnostic logging system for the Ethernet switch.
Software-defined Ethernet switch.
#define SATCAT5_PMASK_TYPE
Set the integer type used to identify source and destination ports.
constexpr SATCAT5_PMASK_TYPE idx2mask(unsigned idx)
Macro converting port-index to a bit-mask.
constexpr SATCAT5_PMASK_TYPE PMASK_ALL(-1)
Global port-mask indicating every port (i.e., broadcast).
Diagnostic logging to UART and/or Ethernet ports.
constexpr s8 CRITICAL
Define basic priority codes for log messages.
constexpr s8 DEBUG
Define basic priority codes for log messages.
u16 value
The 16-bit value is stored in processor-native order.
Ephemeral data structure provided to plugin callbacks.
satcat5::io::MultiPacket * pkt
Complete packet contents.
u8 reason() const
Accessors and shortcuts for packet metadata.
unsigned src_port() const
Accessors and shortcuts for packet metadata.
u16 hlen
Original header length.
bool is_adjusted() const
Accessors and shortcuts for packet metadata.
SATCAT5_PMASK_TYPE dst_mask
Destination mask for which port(s) receive this packet.
bool is_diverted() const
Accessors and shortcuts for packet metadata.
satcat5::eth::Header hdr
Copy of Ethernet header fields.
void write_to(satcat5::io::Writeable *wr) const
Copy packet headers to the specified destination.
A single 24-byte packet-log message.
void init_keep(const satcat5::eth::Header &hdr, u8 src, u32 dst)
Initialize a KEEP message.
static constexpr u8 DROP_UNKNOWN
Other unspecified error.
static constexpr u8 DROP_BADFRM
Frame length, source MAC, etc.
void init_drop(const satcat5::eth::Header &hdr, u8 src, u8 why)
Initialize a DROP message.
static constexpr u8 DROP_BADFCS
Invalid frame check sequence.
static constexpr u8 DROP_DISABLED
Ingress or egress port disabled.
static constexpr u8 REASON_KEEP
Packet accepted / not dropped.
static constexpr u8 DROP_OVERFLOW
FIFO overflow (Rx or Tx)
u32 value
Packed value holds the tag policy, port number, and default VID.
A packet is a linked-list of memory blocks, plus metadata.
u32 m_user[SATCAT5_MBUFF_USER]
Packet metadata.
satcat5::io::ArrayRead peek() const
Peek at the first chunk, up to SATCAT5_MBUFF_CHUNK bytes.
An optional field that may be filled or empty.
constexpr satcat5::eth::VtagPolicy VCFG_DEFAULT(0, VTAG_ADMIT_ALL, VTAG_DEFAULT)
Default VLAN tagging policy.
Miscellaneous mathematical utility functions.