mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-19 00:16:29 +08:00
Add support for default route (IPv4 and IPv6) (#2059)
Based on code by Michael Birtwell <michael.birtwell@oxionics.com>
This commit is contained in:
parent
84e7515721
commit
1ca09b9484
@ -18,8 +18,8 @@ use board_misoc::slave_fpga;
|
|||||||
use board_misoc::{clock, ethmac, net_settings};
|
use board_misoc::{clock, ethmac, net_settings};
|
||||||
use board_misoc::uart_console::Console;
|
use board_misoc::uart_console::Console;
|
||||||
use riscv::register::{mcause, mepc, mtval};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
use smoltcp::iface::SocketStorage;
|
use smoltcp::iface::{Routes, SocketStorage};
|
||||||
use smoltcp::wire::{HardwareAddress, IpAddress, Ipv4Address};
|
use smoltcp::wire::{HardwareAddress, IpAddress, Ipv4Address, Ipv6Address};
|
||||||
|
|
||||||
fn check_integrity() -> bool {
|
fn check_integrity() -> bool {
|
||||||
extern {
|
extern {
|
||||||
@ -411,28 +411,29 @@ fn network_boot() {
|
|||||||
println!("Network addresses: {}", net_addresses);
|
println!("Network addresses: {}", net_addresses);
|
||||||
let mut ip_addrs = [
|
let mut ip_addrs = [
|
||||||
IpCidr::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 0),
|
IpCidr::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 0),
|
||||||
IpCidr::new(net_addresses.ipv6_ll_addr, 0),
|
net_addresses.ipv6_ll_addr,
|
||||||
IpCidr::new(net_addresses.ipv6_ll_addr, 0)
|
IpCidr::new(IpAddress::Ipv6(Ipv6Address::UNSPECIFIED), 0)
|
||||||
];
|
];
|
||||||
if let net_settings::Ipv4AddrConfig::Static(ipv4) = net_addresses.ipv4_addr {
|
if let net_settings::Ipv4AddrConfig::Static(ipv4) = net_addresses.ipv4_addr {
|
||||||
ip_addrs[0] = IpCidr::new(IpAddress::Ipv4(ipv4), 0);
|
ip_addrs[0] = IpCidr::Ipv4(ipv4);
|
||||||
}
|
}
|
||||||
let mut interface = match net_addresses.ipv6_addr {
|
if let Some(ipv6) = net_addresses.ipv6_addr {
|
||||||
Some(addr) => {
|
ip_addrs[2] = IpCidr::Ipv6(ipv6);
|
||||||
ip_addrs[2] = IpCidr::new(addr, 0);
|
|
||||||
smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..])
|
|
||||||
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr))
|
|
||||||
.ip_addrs(&mut ip_addrs[..])
|
|
||||||
.neighbor_cache(neighbor_cache)
|
|
||||||
.finalize()
|
|
||||||
}
|
|
||||||
None =>
|
|
||||||
smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..])
|
|
||||||
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr))
|
|
||||||
.ip_addrs(&mut ip_addrs[..2])
|
|
||||||
.neighbor_cache(neighbor_cache)
|
|
||||||
.finalize()
|
|
||||||
};
|
};
|
||||||
|
let mut routes = [None; 2];
|
||||||
|
let mut interface = smoltcp::iface::InterfaceBuilder::new(net_device, &mut sockets[..])
|
||||||
|
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr))
|
||||||
|
.ip_addrs(&mut ip_addrs[..])
|
||||||
|
.neighbor_cache(neighbor_cache)
|
||||||
|
.routes(Routes::new(&mut routes[..]))
|
||||||
|
.finalize();
|
||||||
|
|
||||||
|
if let Some(default_route) = net_addresses.ipv4_default_route {
|
||||||
|
interface.routes_mut().add_default_ipv4_route(default_route).unwrap();
|
||||||
|
}
|
||||||
|
if let Some(default_route) = net_addresses.ipv6_default_route {
|
||||||
|
interface.routes_mut().add_default_ipv6_route(default_route).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let mut rx_storage = [0; 4096];
|
let mut rx_storage = [0; 4096];
|
||||||
let mut tx_storage = [0; 128];
|
let mut tx_storage = [0; 128];
|
||||||
|
@ -2,7 +2,7 @@ use core::fmt;
|
|||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
use smoltcp::wire::{EthernetAddress, IpAddress, Ipv4Address};
|
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv4Cidr, Ipv6Address, Ipv6Cidr};
|
||||||
|
|
||||||
use config;
|
use config;
|
||||||
#[cfg(soc_platform = "kasli")]
|
#[cfg(soc_platform = "kasli")]
|
||||||
@ -10,18 +10,22 @@ use i2c_eeprom;
|
|||||||
|
|
||||||
pub enum Ipv4AddrConfig {
|
pub enum Ipv4AddrConfig {
|
||||||
UseDhcp,
|
UseDhcp,
|
||||||
Static(Ipv4Address),
|
Static(Ipv4Cidr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Ipv4AddrConfig {
|
impl FromStr for Ipv4AddrConfig {
|
||||||
type Err = ();
|
type Err = ();
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
Ok(if s == "use_dhcp" {
|
if s == "use_dhcp" {
|
||||||
Ipv4AddrConfig::UseDhcp
|
Ok(Ipv4AddrConfig::UseDhcp)
|
||||||
|
} else if let Ok(cidr) = Ipv4Cidr::from_str(s) {
|
||||||
|
Ok(Ipv4AddrConfig::Static(cidr))
|
||||||
|
} else if let Ok(addr) = Ipv4Address::from_str(s) {
|
||||||
|
Ok(Ipv4AddrConfig::Static(Ipv4Cidr::new(addr, 0)))
|
||||||
} else {
|
} else {
|
||||||
Ipv4AddrConfig::Static(Ipv4Address::from_str(s)?)
|
Err(())
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +42,10 @@ impl Display for Ipv4AddrConfig {
|
|||||||
pub struct NetAddresses {
|
pub struct NetAddresses {
|
||||||
pub hardware_addr: EthernetAddress,
|
pub hardware_addr: EthernetAddress,
|
||||||
pub ipv4_addr: Ipv4AddrConfig,
|
pub ipv4_addr: Ipv4AddrConfig,
|
||||||
pub ipv6_ll_addr: IpAddress,
|
pub ipv6_ll_addr: IpCidr,
|
||||||
pub ipv6_addr: Option<IpAddress>
|
pub ipv6_addr: Option<Ipv6Cidr>,
|
||||||
|
pub ipv4_default_route: Option<Ipv4Address>,
|
||||||
|
pub ipv6_default_route: Option<Ipv6Address>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NetAddresses {
|
impl fmt::Display for NetAddresses {
|
||||||
@ -72,28 +78,39 @@ pub fn get_adresses() -> NetAddresses {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ipv4_addr;
|
let ipv4_addr = match config::read_str("ip", |r| r.map(|s| s.parse())) {
|
||||||
match config::read_str("ip", |r| r.map(|s| s.parse())) {
|
Ok(Ok(addr)) => addr,
|
||||||
Ok(Ok(addr)) => ipv4_addr = addr,
|
_ => Ipv4AddrConfig::UseDhcp,
|
||||||
_ => ipv4_addr = Ipv4AddrConfig::UseDhcp,
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let ipv6_ll_addr = IpAddress::v6(
|
let ipv4_default_route = match config::read_str("ipv4_default_route", |r| r.map(|s| s.parse())) {
|
||||||
|
Ok(Ok(addr)) => Some(addr),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ipv6_ll_addr = IpCidr::new(IpAddress::v6(
|
||||||
0xfe80, 0x0000, 0x0000, 0x0000,
|
0xfe80, 0x0000, 0x0000, 0x0000,
|
||||||
(((hardware_addr.0[0] ^ 0x02) as u16) << 8) | (hardware_addr.0[1] as u16),
|
(((hardware_addr.0[0] ^ 0x02) as u16) << 8) | (hardware_addr.0[1] as u16),
|
||||||
((hardware_addr.0[2] as u16) << 8) | 0x00ff,
|
((hardware_addr.0[2] as u16) << 8) | 0x00ff,
|
||||||
0xfe00 | (hardware_addr.0[3] as u16),
|
0xfe00 | (hardware_addr.0[3] as u16),
|
||||||
((hardware_addr.0[4] as u16) << 8) | (hardware_addr.0[5] as u16));
|
((hardware_addr.0[4] as u16) << 8) | (hardware_addr.0[5] as u16)), 10);
|
||||||
|
|
||||||
let ipv6_addr = match config::read_str("ip6", |r| r.map(|s| s.parse())) {
|
let ipv6_addr = match config::read_str("ip6", |r| r.map(|s| s.parse())) {
|
||||||
Ok(Ok(addr)) => Some(addr),
|
Ok(Ok(addr)) => Some(addr),
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let ipv6_default_route = match config::read_str("ipv6_default_route", |r| r.map(|s| s.parse())) {
|
||||||
|
Ok(Ok(addr)) => Some(addr),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
NetAddresses {
|
NetAddresses {
|
||||||
hardware_addr: hardware_addr,
|
hardware_addr,
|
||||||
ipv4_addr: ipv4_addr,
|
ipv4_addr,
|
||||||
ipv6_ll_addr: ipv6_ll_addr,
|
ipv6_ll_addr,
|
||||||
ipv6_addr: ipv6_addr
|
ipv6_addr,
|
||||||
|
ipv4_default_route,
|
||||||
|
ipv6_default_route,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,25 @@
|
|||||||
use board_misoc::clock;
|
use board_misoc::clock;
|
||||||
use sched;
|
use sched;
|
||||||
use sched::Dhcpv4Socket;
|
use sched::Dhcpv4Socket;
|
||||||
use smoltcp::socket::Dhcpv4Event;
|
use core::fmt::{Display, Formatter};
|
||||||
|
use smoltcp::socket::{Dhcpv4Config, Dhcpv4Event};
|
||||||
use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
|
use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
|
||||||
|
|
||||||
|
struct OptionalIpAddressDisplay<'a> (&'a Option<Ipv4Address>);
|
||||||
|
|
||||||
|
impl<'a> Display for OptionalIpAddressDisplay<'a> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
match self.0 {
|
||||||
|
Some(ip) => write!(f, "{}", ip),
|
||||||
|
None => write!(f, "<not set>"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn dhcp_thread(io: sched::Io) {
|
pub fn dhcp_thread(io: sched::Io) {
|
||||||
let mut socket = Dhcpv4Socket::new(&io);
|
let mut socket = Dhcpv4Socket::new(&io);
|
||||||
let mut last_ip: Option<Ipv4Cidr> = None;
|
let mut last_config: Option<Dhcpv4Config> = None;
|
||||||
let mut done_reset = false;
|
let mut done_reset = false;
|
||||||
let start_time = clock::get_ms();
|
let start_time = clock::get_ms();
|
||||||
|
|
||||||
@ -15,8 +28,8 @@ pub fn dhcp_thread(io: sched::Io) {
|
|||||||
// by the server. This is likely to be because the ethernet device isn't quite
|
// by the server. This is likely to be because the ethernet device isn't quite
|
||||||
// ready at the point that it is sent. The following makes recovery from
|
// ready at the point that it is sent. The following makes recovery from
|
||||||
// that faster.
|
// that faster.
|
||||||
if !done_reset && last_ip.is_none() && start_time + 1000 < clock::get_ms() {
|
if !done_reset && last_config.is_none() && start_time + 1000 < clock::get_ms() {
|
||||||
info!("Didn't get initial IP in first second. Assuming packet loss, trying a reset.");
|
info!("Didn't get initial config in first second. Assuming packet loss, trying a reset.");
|
||||||
socket.reset();
|
socket.reset();
|
||||||
done_reset = true;
|
done_reset = true;
|
||||||
}
|
}
|
||||||
@ -26,27 +39,45 @@ pub fn dhcp_thread(io: sched::Io) {
|
|||||||
// Only compare the ip address in the config with previous config because we
|
// Only compare the ip address in the config with previous config because we
|
||||||
// ignore the rest of the config i.e. we don't do any DNS or require a default
|
// ignore the rest of the config i.e. we don't do any DNS or require a default
|
||||||
// gateway.
|
// gateway.
|
||||||
let changed = if let Some(last_ip) = last_ip {
|
let changed = if let Some(last_config) = last_config {
|
||||||
if config.address != last_ip {
|
let mut changed = false;
|
||||||
info!("IP address changed {} -> {}", last_ip, config.address);
|
if config.address != last_config.address {
|
||||||
true
|
info!("IP address changed {} -> {}", last_config.address, config.address);
|
||||||
} else {
|
changed = true;
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
if config.router != last_config.router {
|
||||||
|
info!("Default route changed {} -> {}",
|
||||||
|
OptionalIpAddressDisplay(&last_config.router),
|
||||||
|
OptionalIpAddressDisplay(&config.router),
|
||||||
|
);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
changed
|
||||||
} else {
|
} else {
|
||||||
info!("Acquired IP address: None -> {}", config.address);
|
info!("Acquired DHCP config IP address: None -> {} default route: None -> {}",
|
||||||
|
config.address,
|
||||||
|
OptionalIpAddressDisplay(&config.router),
|
||||||
|
);
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
if changed {
|
if changed {
|
||||||
last_ip = Some(config.address);
|
last_config = Some(config);
|
||||||
io.set_ipv4_address(&config.address);
|
io.set_ipv4_address(&config.address);
|
||||||
|
match config.router {
|
||||||
|
Some(route) => { io.set_ipv4_default_route(route).unwrap(); }
|
||||||
|
None => { io.remove_ipv4_default_route(); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dhcpv4Event::Deconfigured => {
|
Dhcpv4Event::Deconfigured => {
|
||||||
if let Some(ip) = last_ip {
|
if let Some(config) = last_config {
|
||||||
info!("Lost IP address {} -> None", ip);
|
info!("Lost DHCP config IP address {} -> None; default route {} -> None",
|
||||||
|
config.address,
|
||||||
|
OptionalIpAddressDisplay(&config.router),
|
||||||
|
);
|
||||||
io.set_ipv4_address(&Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0));
|
io.set_ipv4_address(&Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0));
|
||||||
last_ip = None;
|
io.remove_ipv4_default_route();
|
||||||
|
last_config = None;
|
||||||
}
|
}
|
||||||
// We always get one of these events at the start, ignore that one
|
// We always get one of these events at the start, ignore that one
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use smoltcp::iface::{Interface, InterfaceBuilder};
|
use smoltcp::iface::{Interface, InterfaceBuilder};
|
||||||
use smoltcp::phy::Device;
|
use smoltcp::phy::Device;
|
||||||
use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr};
|
use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr, Ipv6Cidr};
|
||||||
use board_misoc::net_settings::{Ipv4AddrConfig, NetAddresses};
|
use board_misoc::net_settings::{Ipv4AddrConfig, NetAddresses};
|
||||||
|
|
||||||
|
|
||||||
@ -16,14 +16,14 @@ pub trait InterfaceBuilderEx {
|
|||||||
impl<'a, DeviceT: for<'d> Device<'d>> InterfaceBuilderEx for InterfaceBuilder<'a, DeviceT> {
|
impl<'a, DeviceT: for<'d> Device<'d>> InterfaceBuilderEx for InterfaceBuilder<'a, DeviceT> {
|
||||||
fn init_ip_addrs(self, net_addresses: &NetAddresses) -> Self {
|
fn init_ip_addrs(self, net_addresses: &NetAddresses) -> Self {
|
||||||
let mut storage = [
|
let mut storage = [
|
||||||
IpCidr::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 0); IP_ADDRESS_STORAGE_SIZE
|
IpCidr::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 32); IP_ADDRESS_STORAGE_SIZE
|
||||||
];
|
];
|
||||||
if let Ipv4AddrConfig::Static(ipv4) = net_addresses.ipv4_addr {
|
if let Ipv4AddrConfig::Static(ipv4) = net_addresses.ipv4_addr {
|
||||||
storage[IPV4_INDEX] = IpCidr::new(IpAddress::Ipv4(ipv4), 0);
|
storage[IPV4_INDEX] = IpCidr::Ipv4(ipv4);
|
||||||
}
|
}
|
||||||
storage[IPV6_LL_INDEX] = IpCidr::new(net_addresses.ipv6_ll_addr, 0);
|
storage[IPV6_LL_INDEX] = net_addresses.ipv6_ll_addr;
|
||||||
if let Some(ipv6) = net_addresses.ipv6_addr {
|
if let Some(ipv6) = net_addresses.ipv6_addr {
|
||||||
storage[IPV6_INDEX] = IpCidr::new(ipv6, 0);
|
storage[IPV6_INDEX] = IpCidr::Ipv6(ipv6);
|
||||||
}
|
}
|
||||||
self.ip_addrs(storage)
|
self.ip_addrs(storage)
|
||||||
}
|
}
|
||||||
@ -31,10 +31,14 @@ impl<'a, DeviceT: for<'d> Device<'d>> InterfaceBuilderEx for InterfaceBuilder<'a
|
|||||||
|
|
||||||
pub trait InterfaceEx {
|
pub trait InterfaceEx {
|
||||||
fn update_ipv4_addr(&mut self, addr: &Ipv4Cidr);
|
fn update_ipv4_addr(&mut self, addr: &Ipv4Cidr);
|
||||||
|
fn update_ipv6_addr(&mut self, addr: &Ipv6Cidr);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, DeviceT: for<'d> Device<'d>> InterfaceEx for Interface<'a, DeviceT> {
|
impl<'a, DeviceT: for<'d> Device<'d>> InterfaceEx for Interface<'a, DeviceT> {
|
||||||
fn update_ipv4_addr(&mut self, addr: &Ipv4Cidr) {
|
fn update_ipv4_addr(&mut self, addr: &Ipv4Cidr) {
|
||||||
self.update_ip_addrs(|storage| storage[IPV4_INDEX] = IpCidr::Ipv4(*addr))
|
self.update_ip_addrs(|storage| storage[IPV4_INDEX] = IpCidr::Ipv4(*addr))
|
||||||
}
|
}
|
||||||
|
fn update_ipv6_addr(&mut self, addr: &Ipv6Cidr) {
|
||||||
|
self.update_ip_addrs(|storage| storage[IPV6_INDEX] = IpCidr::Ipv6(*addr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ extern crate logger_artiq;
|
|||||||
extern crate proto_artiq;
|
extern crate proto_artiq;
|
||||||
extern crate riscv;
|
extern crate riscv;
|
||||||
|
|
||||||
|
use alloc::collections::BTreeMap;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use smoltcp::wire::HardwareAddress;
|
use smoltcp::wire::HardwareAddress;
|
||||||
@ -42,6 +43,7 @@ use proto_artiq::{mgmt_proto, moninj_proto, rpc_proto, session_proto, kernel_pro
|
|||||||
use proto_artiq::analyzer_proto;
|
use proto_artiq::analyzer_proto;
|
||||||
|
|
||||||
use riscv::register::{mcause, mepc, mtval};
|
use riscv::register::{mcause, mepc, mtval};
|
||||||
|
use smoltcp::iface::Routes;
|
||||||
use ip_addr_storage::InterfaceBuilderEx;
|
use ip_addr_storage::InterfaceBuilderEx;
|
||||||
|
|
||||||
mod rtio_clocking;
|
mod rtio_clocking;
|
||||||
@ -151,12 +153,23 @@ fn startup() {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
let interface = smoltcp::iface::InterfaceBuilder::new(net_device, vec![])
|
let mut interface = smoltcp::iface::InterfaceBuilder::new(net_device, vec![])
|
||||||
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr))
|
.hardware_addr(HardwareAddress::Ethernet(net_addresses.hardware_addr))
|
||||||
.init_ip_addrs(&net_addresses)
|
.init_ip_addrs(&net_addresses)
|
||||||
.neighbor_cache(neighbor_cache)
|
.neighbor_cache(neighbor_cache)
|
||||||
|
.routes(Routes::new(BTreeMap::new()))
|
||||||
.finalize();
|
.finalize();
|
||||||
|
|
||||||
|
if !use_dhcp {
|
||||||
|
if let Some(ipv4_default_route) = net_addresses.ipv4_default_route {
|
||||||
|
interface.routes_mut().add_default_ipv4_route(ipv4_default_route).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ipv6_default_route) = net_addresses.ipv6_default_route {
|
||||||
|
interface.routes_mut().add_default_ipv6_route(ipv6_default_route).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
let drtio_routing_table = urc::Urc::new(RefCell::new(
|
let drtio_routing_table = urc::Urc::new(RefCell::new(
|
||||||
drtio_routing::config_routing_table(csr::DRTIO.len())));
|
drtio_routing::config_routing_table(csr::DRTIO.len())));
|
||||||
|
@ -8,8 +8,8 @@ use fringe::OwnedStack;
|
|||||||
use fringe::generator::{Generator, Yielder, State as GeneratorState};
|
use fringe::generator::{Generator, Yielder, State as GeneratorState};
|
||||||
use smoltcp::time::Duration;
|
use smoltcp::time::Duration;
|
||||||
use smoltcp::Error as NetworkError;
|
use smoltcp::Error as NetworkError;
|
||||||
use smoltcp::wire::{IpEndpoint, Ipv4Cidr};
|
use smoltcp::wire::{IpEndpoint, Ipv4Address, Ipv4Cidr};
|
||||||
use smoltcp::iface::{Interface, SocketHandle};
|
use smoltcp::iface::{Interface, Route, SocketHandle};
|
||||||
|
|
||||||
use io::{Read, Write};
|
use io::{Read, Write};
|
||||||
use board_misoc::clock;
|
use board_misoc::clock;
|
||||||
@ -278,6 +278,14 @@ impl<'a> Io<'a> {
|
|||||||
pub fn set_ipv4_address(&self, addr: &Ipv4Cidr) {
|
pub fn set_ipv4_address(&self, addr: &Ipv4Cidr) {
|
||||||
self.network.borrow_mut().update_ipv4_addr(addr)
|
self.network.borrow_mut().update_ipv4_addr(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_ipv4_default_route(&self, addr: Ipv4Address) -> Result<Option<Route>, Error> {
|
||||||
|
Ok(self.network.borrow_mut().routes_mut().add_default_ipv4_route(addr)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_ipv4_default_route(&self) -> Option<Route> {
|
||||||
|
self.network.borrow_mut().routes_mut().remove_default_ipv4_route()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -284,19 +284,25 @@ If you purchased a Kasli device from M-Labs, it usually comes with the IP addres
|
|||||||
|
|
||||||
and then reboot the device (with ``artiq_flash start`` or a power cycle).
|
and then reboot the device (with ``artiq_flash start`` or a power cycle).
|
||||||
|
|
||||||
If the ip config field is not set, or set to "use_dhcp" then the device will attempt to obtain an IP address using
|
If the ``ip`` config field is not set, or set to ``use_dhcp`` then the device will
|
||||||
DHCP. If a static IP address is wanted, install OpenOCD as before, and flash the IP (and, if necessary, MAC) addresses
|
attempt to obtain an IP address and default gateway using DHCP. If a static IP
|
||||||
directly: ::
|
address is wanted, install OpenOCD as before, and flash the IP, default gateway
|
||||||
|
(and, if necessary, MAC and IPv6) addresses directly: ::
|
||||||
|
|
||||||
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx/xx -s ipv4_default_route xx.xx.xx.xx -s ip6 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xx -s ipv6_default_route xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
|
||||||
$ artiq_flash -t [board] -V [variant] -f flash_storage.img storage start
|
$ artiq_flash -t [board] -V [variant] -f flash_storage.img storage start
|
||||||
|
|
||||||
For Kasli devices, flashing a MAC address is not necessary as they can obtain it from their EEPROM.
|
For Kasli devices, flashing a MAC address is not necessary as they can obtain it from their EEPROM.
|
||||||
|
If you only want to access the core device from the same subnet you may
|
||||||
|
omit the default gateway and IPv4 prefix length: ::
|
||||||
|
|
||||||
|
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
||||||
|
|
||||||
If DHCP has been used the address can be found in the console output, which can be viewed using: ::
|
If DHCP has been used the address can be found in the console output, which can be viewed using: ::
|
||||||
|
|
||||||
$ python -m misoc.tools.flterm /dev/ttyUSB2
|
$ python -m misoc.tools.flterm /dev/ttyUSB2
|
||||||
|
|
||||||
|
|
||||||
Check that you can ping the device. If ping fails, check that the Ethernet link LED is ON - on Kasli, it is the LED next to the SFP0 connector. As a next step, look at the messages emitted on the UART during boot. Use a program such as flterm or PuTTY to connect to the device's serial port at 115200bps 8-N-1 and reboot the device. On Kasli, the serial port is on FTDI channel 2 with v1.1 hardware (with channel 0 being JTAG) and on FTDI channel 1 with v1.0 hardware. Note that on Windows you might need to install the `FTDI drivers <https://ftdichip.com/drivers/>`_ first.
|
Check that you can ping the device. If ping fails, check that the Ethernet link LED is ON - on Kasli, it is the LED next to the SFP0 connector. As a next step, look at the messages emitted on the UART during boot. Use a program such as flterm or PuTTY to connect to the device's serial port at 115200bps 8-N-1 and reboot the device. On Kasli, the serial port is on FTDI channel 2 with v1.1 hardware (with channel 0 being JTAG) and on FTDI channel 1 with v1.0 hardware. Note that on Windows you might need to install the `FTDI drivers <https://ftdichip.com/drivers/>`_ first.
|
||||||
|
|
||||||
If you want to use IPv6, the device also has a link-local address that corresponds to its EUI-64, and an additional arbitrary IPv6 address can be defined by using the ``ip6`` configuration key. All IPv4 and IPv6 addresses can be used at the same time.
|
If you want to use IPv6, the device also has a link-local address that corresponds to its EUI-64, and an additional arbitrary IPv6 address can be defined by using the ``ip6`` configuration key. All IPv4 and IPv6 addresses can be used at the same time.
|
||||||
|
Loading…
Reference in New Issue
Block a user