1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! This file contains the definition and implementation for the UDP reception
//! interface. It follows the same virtualization model as that described in `udp_send.rs`,
//! except that no queueing is needed because received packets are immediately dispatched to the
//! appropriate capsule / app. Once again, port binding for userspace apps is managed separately
//! by the UDP userspace driver, which must correctly check bindings of kernel apps to ensure
//! correctness when dispatching received packets to the appropriate client.
use crate::net::ipv6::ip_utils::IPAddr;
use crate::net::ipv6::ipv6_recv::IP6RecvClient;
use crate::net::ipv6::IP6Header;
use crate::net::udp::driver::UDPDriver;
use crate::net::udp::udp_port_table::{PortQuery, UdpPortBindingRx};
use crate::net::udp::UDPHeader;
use kernel::collections::list::{List, ListLink, ListNode};
use kernel::debug;
use kernel::utilities::cells::{MapCell, OptionalCell};
pub struct MuxUdpReceiver<'a> {
rcvr_list: List<'a, UDPReceiver<'a>>,
driver: OptionalCell<&'static UDPDriver<'static>>,
}
impl<'a> MuxUdpReceiver<'a> {
pub fn new() -> MuxUdpReceiver<'a> {
MuxUdpReceiver {
rcvr_list: List::new(),
driver: OptionalCell::empty(),
}
}
pub fn add_client(&self, rcvr: &'a UDPReceiver<'a>) {
self.rcvr_list.push_tail(rcvr);
}
pub fn set_driver(&self, driver_ref: &'static UDPDriver) {
self.driver.replace(driver_ref);
}
}
impl<'a> IP6RecvClient for MuxUdpReceiver<'a> {
fn receive(&self, ip_header: IP6Header, payload: &[u8]) {
match UDPHeader::decode(payload).done() {
Some((offset, udp_header)) => {
let len = udp_header.get_len() as usize;
let dst_port = udp_header.get_dst_port();
if len > payload.len() {
debug!("[UDP_RECV] Error: Received UDP length too long");
return;
}
for rcvr in self.rcvr_list.iter() {
match rcvr.binding.take() {
Some(binding) => {
if binding.get_port() == dst_port {
rcvr.client.map(|client| {
client.receive(
ip_header.get_src_addr(),
ip_header.get_dst_addr(),
udp_header.get_src_port(),
udp_header.get_dst_port(),
&payload[offset..],
);
});
rcvr.binding.replace(binding);
break;
}
rcvr.binding.replace(binding);
}
// The UDPReceiver used by the driver will not have a binding
None => match self.driver.take() {
Some(driver) => {
if driver.is_bound(dst_port) {
driver.receive(
ip_header.get_src_addr(),
ip_header.get_dst_addr(),
udp_header.get_src_port(),
udp_header.get_dst_port(),
&payload[offset..],
);
self.driver.replace(driver);
break;
}
self.driver.replace(driver);
}
None => {}
},
}
}
}
None => {}
}
}
}
/// The UDP driver implements this client interface trait to receive
/// packets passed up the network stack to the UDPReceiver, and then
/// distributes them to userland applications from there.
/// Kernel apps can also instantiate structs that implement this trait
/// in order to receive UDP packets
pub trait UDPRecvClient {
fn receive(
&self,
src_addr: IPAddr,
dst_addr: IPAddr,
src_port: u16,
dst_port: u16,
payload: &[u8],
);
}
/// This struct is set as the client of the MuxUdpReceiver, and passes
/// received packets up to whatever app layer client assigns itself
/// as the UDPRecvClient held by this UDPReceiver.
pub struct UDPReceiver<'a> {
client: OptionalCell<&'a dyn UDPRecvClient>,
binding: MapCell<UdpPortBindingRx>,
next: ListLink<'a, UDPReceiver<'a>>,
}
impl<'a> ListNode<'a, UDPReceiver<'a>> for UDPReceiver<'a> {
fn next(&'a self) -> &'a ListLink<'a, UDPReceiver<'a>> {
&self.next
}
}
impl<'a> UDPReceiver<'a> {
pub fn new() -> UDPReceiver<'a> {
UDPReceiver {
client: OptionalCell::empty(),
binding: MapCell::empty(),
next: ListLink::empty(),
}
}
pub fn set_client(&self, client: &'a dyn UDPRecvClient) {
self.client.set(client);
}
pub fn get_binding(&self) -> Option<UdpPortBindingRx> {
self.binding.take()
}
pub fn is_bound(&self) -> bool {
self.binding.is_some()
}
pub fn set_binding(&self, binding: UdpPortBindingRx) -> Option<UdpPortBindingRx> {
self.binding.replace(binding)
}
}