diff --git a/netstack/src/link/vlan.rs b/netstack/src/link/vlan.rs index 3958712e85..b9d3d7f7fe 100644 --- a/netstack/src/link/vlan.rs +++ b/netstack/src/link/vlan.rs @@ -9,6 +9,7 @@ //! the 4-byte 802.1Q tag (TPID 0x8100 + TCI) before/after the Ethernet //! header on each frame. +use std::cell::RefCell; use std::collections::VecDeque; use std::rc::Rc; @@ -17,13 +18,14 @@ use smoltcp::wire::{ EthernetAddress, EthernetFrame, EthernetProtocol, IpAddress, IpCidr, }; -use super::LinkDevice; +use super::{DeviceList, LinkDevice}; const TPID_8021Q: u16 = 0x8100; pub struct VlanDevice { name: Rc, parent_name: Rc, + devices: Rc>, vlan_id: u16, priority: u8, tag: [u8; 4], @@ -35,7 +37,7 @@ pub struct VlanDevice { } impl VlanDevice { - pub fn new(name: &str, parent_name: &str, vlan_id: u16) -> Self { + pub fn new(name: &str, parent_name: &str, vlan_id: u16, devices: Rc>) -> Self { let tci: u16 = vlan_id & 0x0fff; let tag: [u8; 4] = [ (TPID_8021Q >> 8) as u8, @@ -46,6 +48,7 @@ impl VlanDevice { Self { name: name.into(), parent_name: parent_name.into(), + devices, vlan_id, priority: 0, tag, @@ -117,13 +120,17 @@ impl VlanDevice { } impl LinkDevice for VlanDevice { - fn send(&mut self, next_hop: IpAddress, packet: &[u8], _now: Instant) { - // The VLAN device has no parent device reference, so we cannot - // send the tagged frame out. Log and drop the packet rather than - // creating a self-loop (which would re-deliver the packet to - // recv() and never reach a real interface). - log::debug!("vlan: dropping {} byte frame (no parent device)", packet.len()); - let _ = next_hop; + fn send(&mut self, next_hop: IpAddress, packet: &[u8], now: Instant) { + let tagged = self.insert_tag(packet).to_vec(); + // Forward the tagged frame to the parent device by looking it + // up in the shared device list. If the parent doesn't exist or + // isn't ready, drop the packet with a debug log. + if let Some(parent) = self.devices.borrow_mut().get_mut(&self.parent_name) { + parent.send(next_hop, &tagged, now); + } else { + log::debug!("vlan: parent {} not found, dropping {} byte frame", + self.parent_name, packet.len()); + } } fn recv(&mut self, _now: Instant) -> Option<&[u8]> {