SatCat5
router2_offload.cc
1 // Copyright 2024-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <cstring>
7 #include <satcat5/log.h>
8 #include <satcat5/router2_offload.h>
9 #include <satcat5/timeref.h>
10 #include <satcat5/utils.h>
11 
14 using satcat5::log::Log;
16 
17 static const char* LBL = "ROUTER_OFFLOAD";
18 static const unsigned REGADDR_LOG = 489; // Same as m_ctrl->pkt_log
19 static const unsigned REGADDR_IRQ = 510; // Same as m_ctrl->rx_irq
20 
21 Offload::Offload(
22  satcat5::cfg::ConfigBusMmap* cfg, unsigned devaddr,
23  satcat5::router2::Dispatch* router, unsigned hw_ports)
24  : Interrupt(cfg, devaddr, REGADDR_IRQ)
25  , MultiWriter(router)
26  , m_ctrl((ctrl_reg*)cfg->get_device_mmap(devaddr))
27  , m_router(router)
28  , m_pktlog(cfg->get_register(devaddr, REGADDR_LOG))
29  , m_port_index(router->port_count())
30  , m_zero_pad(true)
31  , m_port_mask(0)
32  , m_policy(satcat5::router2::RULE_ALL)
33 {
34  // Sanity check on the control register map.
35  static_assert(sizeof(ctrl_reg) == 4096);
36 
37  // Load policy, MAC address, and IP address.
38  reconfigure();
39 
40  // Register each associated hardware port, and fail loudly if assigned
41  // bits are not consecutive. (Dynamic mapping is prohibitively complex.)
42  for (unsigned a = 0 ; a < hw_ports ; ++a) {
43  SATCAT5_PMASK_TYPE new_mask = m_router->next_port_mask();
44  m_port_mask |= new_mask;
45  if (new_mask != satcat5::eth::idx2mask(m_port_index+a))
46  Log(CRITICAL, LBL).write("Port registration error."); // GCOVR_EXCL_LINE
47  }
48 
49  // Register ourselves as the callback for outgoing data.
50  m_router->set_offload(this);
51 }
52 
53 #if SATCAT5_ALLOW_DELETION
54 Offload::~Offload() {
55  m_router->set_offload(0);
56 }
57 #endif
58 
59 void Offload::rule_allow(u32 mask) {
60  satcat5::util::clr_mask(m_policy, mask);
61  reconfigure(); // Load the new settings.
62 }
63 
64 void Offload::rule_block(u32 mask) {
65  satcat5::util::set_mask(m_policy, mask);
66  reconfigure(); // Load the new settings.
67 }
68 
70  // Sanity check: This interface can't support jumbo frames.
71  unsigned len = meta.pkt->m_length;
72  if (len > sizeof(m_ctrl->txrx_buff)) return;
73 
74  // Translate the software port-mask to a hardware port-mask.
75  u32 hw_mask((meta.dst_mask & m_port_mask) >> m_port_index);
76  if (!hw_mask) return; // No matching ports?
77 
78  // If the busy flag is set, wait a moment and check one more time.
79  // (Worst-case delay is ~4 microseconds for a buffer-to-buffer copy.)
80  if (m_ctrl->tx_ctrl) {
81  SATCAT5_CLOCK->busywait_usec(10);
82  if (m_ctrl->tx_ctrl) return; // Still busy? Drop packet.
83  }
84 
85  // Copy packet to the transmit buffer.
86  MultiPacket::Reader rd(meta.pkt);
87  rd.read_bytes(len, m_ctrl->txrx_buff);
88  rd.read_finalize();
89 
90  // Zero-padding to the minimum Ethernet frame size?
91  static const unsigned MIN_ZPAD = 60;
92  if (m_zero_pad && len < MIN_ZPAD) {
93  unsigned diff = MIN_ZPAD - len;
94  memset(m_ctrl->txrx_buff + len, 0, diff);
95  len += diff;
96  }
97 
98  // Start transmission.
99  m_ctrl->tx_mask = u32(hw_mask);
100  m_ctrl->tx_ctrl = u32(len);
101 }
102 
104  // Read metadata for the incoming packet, if any.
105  u32 status = m_ctrl->rx_ctrl;
106  u32 source = (status >> 16) & 0xFF;
107  u32 length = (status & 0xFFFF);
108  if (!length) return; // False alarm?
109 
110  // Read the VLAN configuration for this source port.
111  auto vlan_cfg = satcat5::eth::VCFG_DEFAULT; // TODO: Implement me!
112  // (Revisit this once we've added necessary registers to the VHDL.)
113 
114  // Copy data from the hardware buffer to the router's input queue.
115  bool ok = (length <= sizeof(m_ctrl->txrx_buff));
116  if (ok) MultiWriter::write_bytes(length, m_ctrl->txrx_buff);
117 
118  // Store required packet metadata before finalizing.
119  // This MUST match the format used in SwitchPort::write_finalize().
120  if (m_write_pkt) {
121  static_assert(SATCAT5_MBUFF_USER >= 2,
122  "SATCAT5_MBUFF_USER must be at least 2.");
123  m_write_pkt->m_user[0] = u32(port_index(source));
124  m_write_pkt->m_user[1] = u32(vlan_cfg.value);
125  }
126  if (ok) MultiWriter::write_finalize();
127 
128  // Flush contents of the hardware buffer.
129  m_ctrl->rx_ctrl = 0;
130 }
131 
133  // Load the gateway-configuration register (3x write + read).
134  u32 ipaddr = m_router->ipaddr().value;
135  u64 mac64 = m_router->macaddr().to_u64();
136  m_ctrl->gateway = u32(mac64 >> 32) | m_policy;
137  m_ctrl->gateway = u32(mac64 >> 0);
138  m_ctrl->gateway = ipaddr;
139  return m_ctrl->gateway;
140 }
Memory-mapped local ConfigBus.
Definition: cfgbus_core.h:199
SATCAT5_PMASK_TYPE next_port_mask()
Get next available bit-mask for new SwitchPort objects.
Definition: eth_switch.cc:66
satcat5::io::MultiPacket * m_write_pkt
Current write state.
Definition: multi_buffer.h:469
The Log class creates and formats one log message.
Definition: log.h:195
Log & write(const char *str)
Formatting methods for various data types.
Definition: log.cc:198
Packet-processing pipeline for the IPv4 router.
void set_offload(satcat5::router2::Offload *iface)
Link this dispatch unit to other parts of the IP/UDP stack.
Offload port for gateware-accelerated IPv4 routers.
void rule_allow(u32 mask)
Set specific router policy flags.
u32 reconfigure()
Reload router IP address and MAC address.
unsigned port_index(unsigned hw_idx) const
Convert hardware port index to a software port-index.
void rule_block(u32 mask)
Clear specific router policy flags.
void deliver(const satcat5::eth::PluginPacket &meta)
Deliver a given packet to the hardware queue.
void irq_event() override
Interrupt service routine.
#define SATCAT5_PMASK_TYPE
Set the integer type used to identify source and destination ports.
Definition: eth_switch.h:41
Diagnostic logging to UART and/or Ethernet ports.
constexpr s8 CRITICAL
Define basic priority codes for log messages.
Definition: log.h:113
constexpr u64 to_u64() const
Convert from MacAddr to u64.
Definition: eth_header.h:44
Ephemeral data structure provided to plugin callbacks.
Definition: eth_plugin.h:48
satcat5::io::MultiPacket * pkt
Complete packet contents.
Definition: eth_plugin.h:51
SATCAT5_PMASK_TYPE dst_mask
Destination mask for which port(s) receive this packet.
Definition: eth_plugin.h:75
A packet is a linked-list of memory blocks, plus metadata.
Definition: multi_buffer.h:91
unsigned m_length
Packet length in bytes.
Definition: multi_buffer.h:102
u32 m_user[SATCAT5_MBUFF_USER]
Packet metadata.
Definition: multi_buffer.h:107
u32 value
Raw access to the underlying representation.
Definition: ip_core.h:17
TimeRef and TimeVal define the API for monotonic timers.
Miscellaneous mathematical utility functions.