capsules_extra/net/ipv6/
ipv6_recv.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use crate::net::ipv6::IP6Header;
6use crate::net::sixlowpan::sixlowpan_state::SixlowpanRxClient;
7
8use kernel::debug;
9use kernel::utilities::cells::OptionalCell;
10use kernel::ErrorCode;
11
12// To provide some context for the entire rx chain:
13/*
14- The radio in the kernel has a single `RxClient`, which is set as the mac layer
15  (awake_mac, typically)
16- The mac layer (i.e. `AwakeMac`) has a single `RxClient`, which is the
17  mac_device(`ieee802154::Framer::framer`)
18- The Mac device has a single receive client - `MuxMac` (virtual MAC device).
19- The `MuxMac` can have multiple "users" which are of type `MacUser`
20- Any received packet is passed to ALL MacUsers, which are expected to filter
21  packets themselves accordingly.
22- Right now, we initialize two MacUsers in the kernel (in main.rs/components).
23  These are the 'radio_mac', which is the MacUser for the RadioDriver that
24  enables the userland interface to directly send 802154 frames, and udp_mac,
25  the mac layer that is ultimately associated with the udp userland interface.
26- The udp_mac MacUser has a single receive client, which is the `sixlowpan_state` struct
27- `sixlowpan_state` has a single rx_client, which in our case is a single struct that
28  implements the `ip_receive ` trait.
29- the `ip_receive` implementing struct (`IP6RecvStruct`) has a single client, which is
30  udp_recv, a `UDPReceive` struct.
31- The UDPReceive struct is a field of the UDPDriver, which ultimately passes the
32  packets up to userland.
33*/
34
35pub trait IP6RecvClient {
36    fn receive(&self, header: IP6Header, payload: &[u8]);
37}
38
39/// Receiver trait for IPv6.
40///
41/// Currently only one implementation of this trait should exist,
42/// as we do not multiplex received packets based on the address.
43/// The receiver receives IP packets destined for any local address.
44/// The receiver should drop any packets with destination addresses
45/// that are not among the local addresses of this device.
46pub trait IP6Receiver<'a> {
47    fn set_client(&self, client: &'a dyn IP6RecvClient);
48}
49
50pub struct IP6RecvStruct<'a> {
51    client: OptionalCell<&'a dyn IP6RecvClient>,
52}
53
54impl<'a> IP6Receiver<'a> for IP6RecvStruct<'a> {
55    fn set_client(&self, client: &'a dyn IP6RecvClient) {
56        self.client.set(client);
57    }
58}
59
60impl<'a> IP6RecvStruct<'a> {
61    pub fn new() -> IP6RecvStruct<'a> {
62        IP6RecvStruct {
63            client: OptionalCell::empty(),
64        }
65    }
66}
67
68impl SixlowpanRxClient for IP6RecvStruct<'_> {
69    fn receive(&self, buf: &[u8], len: usize, result: Result<(), ErrorCode>) {
70        // TODO: Drop here?
71        if len > buf.len() || result != Ok(()) {
72            return;
73        }
74        match IP6Header::decode(buf).done() {
75            Some((offset, ip6_header)) => {
76                let checksum_result = ip6_header.check_transport_checksum(&buf[offset..len]);
77                if checksum_result == Err(ErrorCode::FAIL) {
78                    debug!("cksum fail!: {:?}", checksum_result);
79                    return; //Dropped.
80                }
81                // Note: Protocols for which checksum verification is not implemented (TCP, etc.)
82                // are automatically assumed as fine, rather than dropped
83
84                self.client
85                    .map(|client| client.receive(ip6_header, &buf[offset..len]));
86            }
87            None => {
88                debug!("failed to decode ipv6 header");
89                // TODO: Report the error somewhere...
90            }
91        }
92    }
93}