nic_router: send with individual composing functor

Normally, Interface::send always takes the base and size of the RAM region
where a packet was composed and copies this finished packet at once into the
packet stream RAM. But we want to be able to also compose packets directly in
the packet stream RAM, so that no memcpy is needed. Thus, Interface::send now
takes a functor that describes how to compose the packet, then allocates the
packet stream RAM and applies the functor to this RAM. there is also a version
of Interface::send that provides the old behavior but with the new back end.
This way, we stay backwards-compatible.

Issue #2626
This commit is contained in:
Martin Stein 2017-12-20 14:04:50 +01:00 committed by Christian Helmuth
parent 4c76a87fec
commit b6991f9c03
2 changed files with 49 additions and 15 deletions

View File

@ -927,21 +927,32 @@ void Interface::_handle_eth(void *const eth_base,
}
void Interface::send(Ethernet_frame &eth, Genode::size_t const size)
void Interface::send(Ethernet_frame &eth, size_t eth_size)
{
send(eth_size, [&] (void *pkt_base) {
Genode::memcpy(pkt_base, (void *)&eth, eth_size);
});
}
void Interface::_send_alloc_pkt(Packet_descriptor &pkt,
void * &pkt_base,
size_t pkt_size)
{
pkt = _source().alloc_packet(pkt_size);
pkt_base = _source().packet_content(pkt);
}
void Interface::_send_submit_pkt(Packet_descriptor &pkt,
void * &pkt_base,
size_t pkt_size)
{
_source().submit_packet(pkt);
_domain.raise_tx_bytes(pkt_size);
if (_config().verbose()) {
log("(", _domain, " <- router) ", eth); }
try {
/* copy and submit packet */
Packet_descriptor const pkt = _source().alloc_packet(size);
char *content = _source().packet_content(pkt);
Genode::memcpy((void *)content, (void *)&eth, size);
_source().submit_packet(pkt);
_domain.raise_tx_bytes(size);
}
catch (Packet_stream_source::Packet_alloc_failed) {
if (_config().verbose()) {
log("Failed to allocate packet"); }
log("(", _domain, " <- router) ",
*reinterpret_cast<Ethernet_frame *>(pkt_base));
}
}

View File

@ -168,6 +168,14 @@ class Net::Interface : public Genode::List<Interface>::Element
virtual Packet_stream_source &_source() = 0;
void _send_alloc_pkt(Genode::Packet_descriptor &pkt,
void * &pkt_base,
Genode::size_t pkt_size);
void _send_submit_pkt(Genode::Packet_descriptor &pkt,
void * &pkt_base,
Genode::size_t pkt_size);
/***********************************
** Packet-stream signal handlers **
@ -212,10 +220,25 @@ class Net::Interface : public Genode::List<Interface>::Element
~Interface();
void dhcp_allocation_expired(Dhcp_allocation &allocation);
void send(Ethernet_frame &eth, Genode::size_t const eth_size);
template <typename FUNC>
void send(Genode::size_t pkt_size, FUNC && write_to_pkt)
{
try {
Packet_descriptor pkt;
void *pkt_base;
_send_alloc_pkt(pkt, pkt_base, pkt_size);
write_to_pkt(pkt_base);
_send_submit_pkt(pkt, pkt_base, pkt_size);
}
catch (Packet_stream_source::Packet_alloc_failed) {
Genode::warning("failed to allocate packet");
}
}
void send(Ethernet_frame &eth, Genode::size_t eth_size);
Link_list &dissolved_links(L3_protocol const protocol);