diff --git a/repos/os/src/server/nic_router/dhcp_client.cc b/repos/os/src/server/nic_router/dhcp_client.cc index 4440e3c22a..5db450af6e 100644 --- a/repos/os/src/server/nic_router/dhcp_client.cc +++ b/repos/os/src/server/nic_router/dhcp_client.cc @@ -228,4 +228,6 @@ void Dhcp_client::_send(Message_type msg_type, ip.total_length(size_guard.head_size() - ip_off); ip.update_checksum(); }); + + _interface.wakeup_source(); } diff --git a/repos/os/src/server/nic_router/interface.cc b/repos/os/src/server/nic_router/interface.cc index 50491bcd5a..06d9939a72 100644 --- a/repos/os/src/server/nic_router/interface.cc +++ b/repos/os/src/server/nic_router/interface.cc @@ -1538,7 +1538,7 @@ void Interface::_handle_pkt_stream_signal() * sending new packets in the subsequent steps of this handler. */ while (_source.ack_avail()) { - _source.release_packet(_source.get_acked_packet()); + _source.release_packet(_source.try_get_acked_packet()); } /* @@ -1567,6 +1567,23 @@ void Interface::_handle_pkt_stream_signal() _handle_pkt(); } } + + /* + * Since we use the try_*() variants of the packet-stream API, we + * haven't emitted any packet_avail, ack_avail, ready_to_submit or + * ready_to_ack signal up to now. We've removed packets from our sink's + * submit queue and might have forwarded it to any interface. We may have + * also removed acks from our sink's ack queue. + * + * We therefore wakeup all sources and our sink. Note that the packet-stream + * API takes care of emitting only the signals that are actually needed. + */ + _config().domains().for_each([&] (Domain &domain) { + domain.interfaces().for_each([&] (Interface &interface) { + interface.wakeup_source(); + }); + }); + wakeup_sink(); } @@ -1810,7 +1827,7 @@ void Interface::_send_submit_pkt(Packet_descriptor &pkt, } catch (Size_guard::Exceeded) { log("[", local_domain, "] snd ?"); } } - _source.submit_packet(pkt); + _source.try_submit_packet(pkt); } @@ -2132,6 +2149,13 @@ void Interface::_failed_to_send_packet_link() } +void Interface::_failed_to_send_packet_submit() +{ + if (_config().verbose()) { + log("[", _domain(), "] failed to send packet (queue full)"); } +} + + void Interface::_failed_to_send_packet_alloc() { if (_config().verbose()) { @@ -2254,14 +2278,13 @@ void Interface::handle_config_3() void Interface::_ack_packet(Packet_descriptor const &pkt) { - if (!_sink.ready_to_ack()) { + if (!_sink.try_ack_packet(pkt)) { if (_config().verbose()) { log("[", _domain(), "] leak packet (sink not ready to " "acknowledge)"); } return; } - _sink.acknowledge_packet(pkt); } diff --git a/repos/os/src/server/nic_router/interface.h b/repos/os/src/server/nic_router/interface.h index 6ac3caf146..1556bcaabb 100644 --- a/repos/os/src/server/nic_router/interface.h +++ b/repos/os/src/server/nic_router/interface.h @@ -345,6 +345,8 @@ class Net::Interface : private Interface_list::Element void _failed_to_send_packet_link(); + void _failed_to_send_packet_submit(); + void _failed_to_send_packet_alloc(); void _send_icmp_dst_unreachable(Ipv4_address_prefix const &local_intf, @@ -394,6 +396,10 @@ class Net::Interface : private Interface_list::Element _failed_to_send_packet_link(); return; } + if (!_source.ready_to_submit()) { + _failed_to_send_packet_submit(); + return; + } try { Packet_descriptor pkt; void *pkt_base; @@ -456,6 +462,8 @@ class Net::Interface : private Interface_list::Element Interface_link_stats &icmp_stats() { return _icmp_stats; } Interface_object_stats &arp_stats() { return _arp_stats; } Interface_object_stats &dhcp_stats() { return _dhcp_stats; } + void wakeup_source() { _source.wakeup(); } + void wakeup_sink() { _sink.wakeup(); } }; #endif /* _INTERFACE_H_ */ diff --git a/repos/os/src/server/nic_router/nic_client.cc b/repos/os/src/server/nic_router/nic_client.cc index 28645c42d4..ede74c4aea 100644 --- a/repos/os/src/server/nic_router/nic_client.cc +++ b/repos/os/src/server/nic_router/nic_client.cc @@ -170,6 +170,12 @@ Net::Nic_client_interface::Nic_client_interface(Env &env, rx_channel()->sigh_packet_avail(_interface.pkt_stream_signal_handler()); tx_channel()->sigh_ack_avail (_interface.pkt_stream_signal_handler()); + /* + * We do not install ready_to_submit because submission is only triggered + * by incoming packets (and dropped if the submit queue is full). + * The ack queue should never be full otherwise we'll be leaking packets. + */ + /* initialize link state handling */ Nic::Connection::link_state_sigh(_session_link_state_handler); _session_link_state = Nic::Connection::link_state(); diff --git a/repos/os/src/server/nic_router/nic_session_root.cc b/repos/os/src/server/nic_router/nic_session_root.cc index 3efa739f42..a381081448 100644 --- a/repos/os/src/server/nic_router/nic_session_root.cc +++ b/repos/os/src/server/nic_router/nic_session_root.cc @@ -256,6 +256,12 @@ Nic_session_component(Session_env &session_env, /* install packet stream signal handlers */ _tx.sigh_packet_avail(_interface.pkt_stream_signal_handler()); _rx.sigh_ack_avail (_interface.pkt_stream_signal_handler()); + + /* + * We do not install ready_to_submit because submission is only triggered by + * incoming packets (and dropped if the submit queue is full). + * The ack queue should never be full otherwise we'll be leaking packets. + */ } diff --git a/repos/os/src/server/nic_router/uplink_session_root.cc b/repos/os/src/server/nic_router/uplink_session_root.cc index fb3beaf4de..e1430772a0 100644 --- a/repos/os/src/server/nic_router/uplink_session_root.cc +++ b/repos/os/src/server/nic_router/uplink_session_root.cc @@ -104,6 +104,12 @@ Net::Uplink_session_component::Uplink_session_component(Session_env /* install packet stream signal handlers */ _tx.sigh_packet_avail(_interface.pkt_stream_signal_handler()); _rx.sigh_ack_avail (_interface.pkt_stream_signal_handler()); + + /* + * We do not install ready_to_submit because submission is only triggered by + * incoming packets (and dropped if the submit queue is full). + * The ack queue should never be full otherwise we'll be leaking packets. + */ }