SatCat5
eth_switch.h
Go to the documentation of this file.
1 // Copyright 2024-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
28 
29 #pragma once
30 
31 #include <satcat5/list.h>
32 #include <satcat5/multi_buffer.h>
33 #include <satcat5/switch_cfg.h>
34 #include <satcat5/types.h>
35 
40 #ifndef SATCAT5_PMASK_TYPE
41 #define SATCAT5_PMASK_TYPE u32
42 #endif
43 
44 namespace satcat5 {
45  namespace eth {
48 
51 
53  constexpr SATCAT5_PMASK_TYPE idx2mask(unsigned idx)
54  { return (idx < 65536) ? (SATCAT5_PMASK_TYPE(1) << idx) : 0; }
55 
59  constexpr unsigned PMASK_SIZE()
60  { return 8 * sizeof(SATCAT5_PMASK_TYPE); }
61 
65  public:
68  virtual void log_packet(const satcat5::eth::SwitchLogMessage& msg) = 0;
69 
70  protected:
72  constexpr SwitchLogHandler() : m_next(nullptr) {}
73 
74  private:
78  };
79 
94  public:
96  SwitchCore(u8* buff, unsigned nbytes);
97 
101  inline satcat5::eth::SwitchPort* get_port(unsigned idx)
102  { return m_ports.get_index(idx); }
103 
108 
110  inline u32 port_count() const
111  { return m_ports.len(); }
112 
114  inline void set_debug(satcat5::io::Writeable* debug)
115  { m_debug = debug; }
116 
120  { m_pktlogs.add(log); }
121  inline void remove_log(satcat5::eth::SwitchLogHandler* log)
122  { m_pktlogs.remove(log); }
123 
127  void set_promiscuous(unsigned port_idx, bool enable);
130  { m_prom_mask = mask; }
133  { return m_prom_mask; }
134 
136  void set_traffic_filter(u16 etype = 0);
138  inline u16 get_traffic_filter() const
139  { return m_stats_filter; }
140 
145  u32 get_traffic_count();
146 
149  void debug_if(const satcat5::eth::PluginPacket& pkt, unsigned mask) const;
150 
152  void debug_log(
153  const satcat5::io::MultiPacket* pkt,
154  u8 reason, SATCAT5_PMASK_TYPE dst = 0) const;
155 
156  protected:
158  unsigned deliver(satcat5::io::MultiPacket* packet) override;
159 
162  void process_stats(const satcat5::eth::PluginPacket& pkt);
166  satcat5::eth::PluginPacket& pkt, unsigned mask);
167  unsigned deliver_switch(const satcat5::eth::PluginPacket& pkt);
169 
174  void plugin_add(satcat5::eth::PluginCore* plugin);
175  void plugin_remove(satcat5::eth::PluginCore* plugin);
177 
181  void port_add(satcat5::eth::SwitchPort* port);
182  void port_remove(satcat5::eth::SwitchPort* port);
183  void port_remove(const SATCAT5_PMASK_TYPE& mask);
185 
188 
191 
192  // Other configuration variables.
193  satcat5::io::Writeable* m_debug;
195  SATCAT5_PMASK_TYPE m_free_pmask;
196  SATCAT5_PMASK_TYPE m_prom_mask;
197  u16 m_stats_filter;
198  u32 m_stats_count;
199  };
200 
202  template <unsigned BSIZE = 65536>
204  public:
205  SwitchCoreStatic() : SwitchCore(m_buff, BSIZE) {}
206  protected:
207  u8 m_buff[BSIZE];
208  };
209 
244  , public satcat5::io::MultiWriter
245  {
246  public:
248  bool accept(SATCAT5_PMASK_TYPE dst_mask, satcat5::io::MultiPacket* packet);
249 
256  void plugin_add(satcat5::eth::PluginPort* plugin);
259 
265 
267  inline bool consistency() const
268  { return m_egress.consistency(); }
269 
272  { return &m_egress; }
273 
276  { return m_switch; }
277 
279  inline void port_enable(bool enable)
280  { m_egress.set_port_enable(enable); }
281 
283  inline bool port_enabled() const
284  { return m_egress.get_port_enable(); }
285 
287  inline void port_flush()
288  { write_abort(); m_egress.flush(); }
289 
292  inline unsigned port_index() const
293  { return m_port_index; }
294 
297  { return m_port_mask; }
298 
301  { m_egress.set_callback(cb); }
302 
305  { return m_vlan_cfg; }
306 
308  inline void vlan_config(const VtagPolicy& cfg)
309  { m_vlan_cfg = cfg; }
310 
313  void write_abort() override;
314 
318  bool write_finalize() override;
319 
320  protected:
323  explicit SwitchPort(
326  ~SwitchPort() SATCAT5_OPTIONAL_DTOR;
327 
328  // Override for EventListener callback.
329  void data_rcvd(satcat5::io::Readable* src) override;
330 
332  satcat5::eth::SwitchCore* const m_switch;
333 
340  const unsigned m_port_index;
342 
344  satcat5::eth::VtagPolicy m_vlan_cfg;
345  // TODO: Support for PAUSE commands?
346 
347  // Egress pipeline.
348  satcat5::io::MultiReaderPriority m_egress;
349  satcat5::io::Writeable* const m_eg_dst;
350  bool m_eg_hdr;
351 
353  satcat5::util::List<satcat5::eth::PluginPort> m_plugins;
354 
355  private:
356  // Linked list of other SwitchPort objects.
357  friend satcat5::util::ListCore;
358  satcat5::eth::SwitchPort* m_next;
359  };
360  }
361 }
Ethernet switch plugin API.
Definition: eth_plugin.h:166
Ethernet port plugin API.
Definition: eth_plugin.h:198
A shared-memory Ethernet switch based on the MultiBuffer class.
Definition: eth_switch.h:93
satcat5::util::List< satcat5::eth::SwitchPort > m_ports
Linked list of attached Ethernet ports.
Definition: eth_switch.h:190
unsigned deliver(satcat5::io::MultiPacket *packet) override
Override the MultiBuffer::deliver() method.
Definition: eth_switch.cc:110
unsigned deliver_switch(const satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
Definition: eth_switch.cc:248
SwitchCore(u8 *buff, unsigned nbytes)
Configure this object and link to the provided working buffer.
Definition: eth_switch.cc:49
satcat5::util::optional< unsigned > process_plugins(satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
Definition: eth_switch.cc:187
satcat5::util::List< satcat5::eth::PluginCore > m_plugins
Linked list of attached plugins.
Definition: eth_switch.h:187
satcat5::util::optional< unsigned > pkt_has_dropped(satcat5::eth::PluginPacket &pkt, unsigned mask)
Internal event-handlers called from deliver(...).
Definition: eth_switch.cc:233
void set_promiscuous(unsigned port_idx, bool enable)
Enable or disable "promiscuous" flag on the specified port index.
Definition: eth_switch.cc:94
u32 get_traffic_count()
Query traffic statistics Count received frames that match the current traffic filter,...
Definition: eth_switch.cc:104
satcat5::eth::SwitchPort * get_port(unsigned idx)
Fetch a SwitchPort object by port-index.
Definition: eth_switch.h:101
void process_stats(const satcat5::eth::PluginPacket &pkt)
Internal event-handlers called from deliver(...).
Definition: eth_switch.cc:176
SATCAT5_PMASK_TYPE next_port_mask()
Get next available bit-mask for new SwitchPort objects.
Definition: eth_switch.cc:66
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.
Definition: eth_switch.cc:147
void set_debug(satcat5::io::Writeable *debug)
Optional debug interface gets a carbon copy of each packet.
Definition: eth_switch.h:114
void add_log(satcat5::eth::SwitchLogHandler *log)
Optional logging interface records a summary of every packet.
Definition: eth_switch.h:119
void set_promiscuous_mask(SATCAT5_PMASK_TYPE mask)
Enable or disable "promiscuous" flag for all ports at once.
Definition: eth_switch.h:129
u16 get_traffic_filter() const
Return the current filter configuration. (0 = Any type)
Definition: eth_switch.h:138
SATCAT5_PMASK_TYPE get_promiscuous_mask() const
Return a bit-mask identifying all "promiscuous" ports.
Definition: eth_switch.h:132
void debug_if(const satcat5::eth::PluginPacket &pkt, unsigned mask) const
Carbon-copy a packet to the debug port, if it is enabled.
Definition: eth_switch.cc:135
void set_traffic_filter(u16 etype=0)
Configure EtherType filter for traffic reporting. (0 = Any type)
Definition: eth_switch.cc:99
u32 port_count() const
Get the number of attached ports.
Definition: eth_switch.h:110
Wrapper for SwitchCore with a statically-allocated working buffer.
Definition: eth_switch.h:203
Define the API for packet-logging callbacks from eth::SwitchCore.
Definition: eth_switch.h:64
virtual void log_packet(const satcat5::eth::SwitchLogMessage &msg)=0
This method is called exactly once for each incoming packet.
constexpr SwitchLogHandler()
Constructor is accessible only to children.
Definition: eth_switch.h:72
Generic packetized I/O interface for use with SwitchCore.
Definition: eth_switch.h:245
const unsigned m_port_index
Define this port's connection to the switch.
Definition: eth_switch.h:340
void plugin_ingress(satcat5::eth::PluginPacket &pkt)
Issue notifications to all attached plugins.
Definition: eth_switch.cc:300
bool write_finalize() override
Override write_finalize() to store metadata.
Definition: eth_switch.cc:335
SATCAT5_PMASK_TYPE m_port_mask
Define this port's connection to the switch.
Definition: eth_switch.h:339
void port_flush()
Discard all pending ingress and egress data.
Definition: eth_switch.h:287
void write_abort() override
Override write_abort() to allow additional error handling.
Definition: eth_switch.cc:329
satcat5::io::MultiReaderPriority * get_egress()
Source for data leaving the switch through this port.
Definition: eth_switch.h:271
void data_rcvd(satcat5::io::Readable *src) override
The data_rcvd() callback is polled whenever data is available.
Definition: eth_switch.cc:368
bool port_enabled() const
Is this port currently enabled?
Definition: eth_switch.h:283
SATCAT5_PMASK_TYPE port_mask() const
Bit-mask for all port(s) associated with this interface.
Definition: eth_switch.h:296
void plugin_remove(satcat5::eth::PluginPort *plugin)
Plugin management.
Definition: eth_switch.cc:297
void port_enable(bool enable)
Enable or disable this port, pausing data-flow.
Definition: eth_switch.h:279
bool m_eg_hdr
Frame header copied?
Definition: eth_switch.h:350
satcat5::eth::VtagPolicy m_vlan_cfg
Metadata required for VLAN functionality.
Definition: eth_switch.h:344
void set_callback(satcat5::io::EventListener *cb)
Set egress data callback, mainly used for unit testing.
Definition: eth_switch.h:300
bool consistency() const
Internal consistency check, mainly used for unit testing.
Definition: eth_switch.h:267
satcat5::eth::SwitchCore *const m_switch
Pointer to the associated switch.
Definition: eth_switch.h:332
satcat5::eth::SwitchCore * get_switch()
Pointer to the parent SwitchCore object.
Definition: eth_switch.h:275
satcat5::util::List< satcat5::eth::PluginPort > m_plugins
Linked list of attached plugins.
Definition: eth_switch.h:353
unsigned port_index() const
Port number for attachment to the parent SwitchCore.
Definition: eth_switch.h:292
void vlan_config(const VtagPolicy &cfg)
Set this port's VLAN configuration.
Definition: eth_switch.h:308
satcat5::eth::VtagPolicy vlan_config() const
Return this port's VLAN configuration.
Definition: eth_switch.h:304
satcat5::io::Writeable *const m_eg_dst
Egress destination.
Definition: eth_switch.h:349
SwitchPort(satcat5::eth::SwitchCore *sw, satcat5::io::Writeable *dst)
Link this port to the designated switch.
Definition: eth_switch.cc:267
void plugin_add(satcat5::eth::PluginPort *plugin)
Plugin management.
Definition: eth_switch.cc:295
satcat5::io::MultiReaderPriority m_egress
Egress data source.
Definition: eth_switch.h:348
void plugin_egress(satcat5::eth::PluginPacket &pkt)
Issue notifications to all attached plugins.
Definition: eth_switch.cc:315
bool accept(SATCAT5_PMASK_TYPE dst_mask, satcat5::io::MultiPacket *packet)
Accept delivery of a given packet?
Definition: eth_switch.cc:291
Event-handler interface for newly received data.
Definition: io_readable.h:43
A multi-source, multi-sink packet buffer.
Definition: multi_buffer.h:198
void set_port_enable(bool enable)
Enable or disable this port.
Definition: multi_buffer.h:283
void flush()
Discard all queued packets.
bool get_port_enable() const
Is this port currently enabled?
Definition: multi_buffer.h:278
A variant of MultiReader that follows priority ordering.
Definition: multi_buffer.h:365
bool consistency() const
Internal consistency self-test (Optional).
A port for writing to a MultiBuffer object.
Definition: multi_buffer.h:405
virtual void set_callback(satcat5::io::EventListener *callback)
Update registered callback for data_rcvd() events.
Definition: io_readable.cc:39
Abstract API for writing byte-streams and packets.
Definition: io_writeable.h:24
constexpr Writeable()
Only children should create or destroy the base class.
Definition: io_writeable.h:113
Helper functions for manipulating singly-linked lists.
Definition: list.h:52
unsigned len() const
Traverse the linked list to count its length.
Definition: list.h:257
T * get_index(unsigned idx)
Fetch the Nth item from the linked list.
Definition: list.h:240
void add(T *item)
Add new item to front or back, whichever is simpler.
Definition: list.h:221
void remove(T *item)
Remove the designated item from the list.
Definition: list.h:277
#define SATCAT5_PMASK_TYPE
Set the integer type used to identify source and destination ports.
Definition: eth_switch.h:41
constexpr SATCAT5_PMASK_TYPE idx2mask(unsigned idx)
Macro converting port-index to a bit-mask.
Definition: eth_switch.h:53
constexpr SATCAT5_PMASK_TYPE PMASK_NONE(0)
Global port-mask indicating no ports (i.e., drop).
constexpr unsigned PMASK_SIZE()
Maximum number of switch ports, based on SATCAT5_PMASK_TYPE.
Definition: eth_switch.h:59
constexpr SATCAT5_PMASK_TYPE PMASK_ALL(-1)
Global port-mask indicating every port (i.e., broadcast).
Templated functions for manipulating singly-linked lists.
Multi-source, multi-sink packet buffer.
Ephemeral data structure provided to plugin callbacks.
Definition: eth_plugin.h:48
A single 24-byte packet-log message.
Definition: eth_sw_log.h:74
Data structure for configuring VLAN tagging policy of each port.
Definition: switch_cfg.h:68
A packet is a linked-list of memory blocks, plus metadata.
Definition: multi_buffer.h:91
An optional field that may be filled or empty.
Definition: utils.h:53
Configuration for a managed SatCat5 switch.
Basic type aliases and prototypes used throughout SatCat5.