remote_rom: implement ARP requests
This commit is contained in:
committed by
Norman Feske
parent
8ed98b8459
commit
92ef8619c7
@@ -20,6 +20,28 @@ void Remote_rom::Backend_base::_handle_rx_packet()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Remote_rom::Backend_base::_handle_arp_request(Ethernet_frame ð,
|
||||||
|
Size_guard &guard,
|
||||||
|
Arp_packet &arp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The ARP packet gets re-written, we interchange source
|
||||||
|
* and destination MAC and IP addresses, and set the opcode
|
||||||
|
* to reply, and then push the packet back to the NIC driver.
|
||||||
|
*/
|
||||||
|
Ipv4_address old_src_ip = arp.src_ip();
|
||||||
|
arp.opcode(Arp_packet::REPLY);
|
||||||
|
arp.dst_mac(arp.src_mac());
|
||||||
|
arp.src_mac(_mac_address);
|
||||||
|
arp.src_ip(arp.dst_ip());
|
||||||
|
arp.dst_ip(old_src_ip);
|
||||||
|
eth.dst(arp.dst_mac());
|
||||||
|
|
||||||
|
/* set our MAC as sender */
|
||||||
|
eth.src(_mac_address);
|
||||||
|
send(ð, guard.total_size());
|
||||||
|
}
|
||||||
|
|
||||||
void Remote_rom::Backend_base::handle_ethernet(void* src, Genode::size_t size)
|
void Remote_rom::Backend_base::handle_ethernet(void* src, Genode::size_t size)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -51,23 +73,17 @@ void Remote_rom::Backend_base::handle_arp(Ethernet_frame ð,
|
|||||||
|
|
||||||
/* look whether the IP address is our's */
|
/* look whether the IP address is our's */
|
||||||
if (arp.dst_ip() == _accept_ip) {
|
if (arp.dst_ip() == _accept_ip) {
|
||||||
if (arp.opcode() == Arp_packet::REQUEST) {
|
switch (arp.opcode()) {
|
||||||
/*
|
case Arp_packet::REQUEST:
|
||||||
* The ARP packet gets re-written, we interchange source
|
_handle_arp_request(eth, edguard, arp);
|
||||||
* and destination MAC and IP addresses, and set the opcode
|
break;
|
||||||
* to reply, and then push the packet back to the NIC driver.
|
case Arp_packet::REPLY:
|
||||||
*/
|
if (_arp_waiting && arp.src_ip() == _dst_ip) {
|
||||||
Ipv4_address old_src_ip = arp.src_ip();
|
_dst_mac = arp.src_mac();
|
||||||
arp.opcode(Arp_packet::REPLY);
|
_arp_waiting = false;
|
||||||
arp.dst_mac(arp.src_mac());
|
}
|
||||||
arp.src_mac(_mac_address);
|
break;
|
||||||
arp.src_ip(arp.dst_ip());
|
default: break;
|
||||||
arp.dst_ip(old_src_ip);
|
|
||||||
eth.dst(arp.dst_mac());
|
|
||||||
|
|
||||||
/* set our MAC as sender */
|
|
||||||
eth.src(_mac_address);
|
|
||||||
send(ð, edguard.total_size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,6 +96,9 @@ void Remote_rom::Backend_base::handle_ip(Ethernet_frame ð,
|
|||||||
|| _accept_ip == ip.dst()) {
|
|| _accept_ip == ip.dst()) {
|
||||||
|
|
||||||
if (ip.protocol() == Ipv4_packet::Protocol::UDP) {
|
if (ip.protocol() == Ipv4_packet::Protocol::UDP) {
|
||||||
|
if (_dst_mac == Ethernet_frame::broadcast() && ip.src() == _dst_ip) {
|
||||||
|
_dst_mac = eth.src();
|
||||||
|
}
|
||||||
/* remote_rom protocol is wrapped in UDP */
|
/* remote_rom protocol is wrapped in UDP */
|
||||||
Udp_packet &udp = ip.data<Udp_packet>(edguard);
|
Udp_packet &udp = ip.data<Udp_packet>(edguard);
|
||||||
if (udp.dst_port() == _udp_port)
|
if (udp.dst_port() == _udp_port)
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ class Remote_rom::Backend_base : public Genode::Interface
|
|||||||
/* rx packet handler */
|
/* rx packet handler */
|
||||||
void _handle_rx_packet();
|
void _handle_rx_packet();
|
||||||
|
|
||||||
|
void _handle_arp_request(Ethernet_frame ð,
|
||||||
|
Size_guard &guard,
|
||||||
|
Arp_packet &arp);
|
||||||
|
|
||||||
void _handle_link_state()
|
void _handle_link_state()
|
||||||
{
|
{
|
||||||
Genode::log("link state changed");
|
Genode::log("link state changed");
|
||||||
@@ -79,6 +83,7 @@ class Remote_rom::Backend_base : public Genode::Interface
|
|||||||
Timer::Connection _timer;
|
Timer::Connection _timer;
|
||||||
|
|
||||||
const bool _verbose = false;
|
const bool _verbose = false;
|
||||||
|
bool _arp_waiting { false };
|
||||||
Nic::Packet_allocator _tx_block_alloc;
|
Nic::Packet_allocator _tx_block_alloc;
|
||||||
Nic::Connection _nic;
|
Nic::Connection _nic;
|
||||||
Mac_address _mac_address;
|
Mac_address _mac_address;
|
||||||
@@ -93,8 +98,41 @@ class Remote_rom::Backend_base : public Genode::Interface
|
|||||||
*/
|
*/
|
||||||
virtual void receive(Packet &packet, Size_guard &) = 0;
|
virtual void receive(Packet &packet, Size_guard &) = 0;
|
||||||
|
|
||||||
|
inline void arp_request()
|
||||||
|
{
|
||||||
|
if (_dst_mac == Ethernet_frame::broadcast() && !_arp_waiting) {
|
||||||
|
size_t const frame_size = sizeof(Ethernet_frame)
|
||||||
|
+ sizeof(Arp_packet);
|
||||||
|
Nic::Packet_descriptor pd = alloc_tx_packet(frame_size);
|
||||||
|
Size_guard size_guard(pd.size());
|
||||||
|
|
||||||
|
char *content = _nic.tx()->packet_content(pd);
|
||||||
|
Ethernet_frame ð = Ethernet_frame::construct_at(content,
|
||||||
|
size_guard);
|
||||||
|
eth.src(_mac_address);
|
||||||
|
eth.dst(Ethernet_frame::broadcast());
|
||||||
|
eth.type(Ethernet_frame::Type::ARP);
|
||||||
|
|
||||||
|
Arp_packet &arp = eth.construct_at_data<Arp_packet>(size_guard);
|
||||||
|
arp.hardware_address_type(Arp_packet::ETHERNET);
|
||||||
|
arp.protocol_address_type(Arp_packet::IPV4);
|
||||||
|
arp.hardware_address_size(sizeof(Mac_address));
|
||||||
|
arp.protocol_address_size(sizeof(Ipv4_address));
|
||||||
|
arp.opcode(Arp_packet::REQUEST);
|
||||||
|
arp.src_mac(_mac_address);
|
||||||
|
arp.src_ip(_src_ip);
|
||||||
|
arp.dst_mac(Ethernet_frame::broadcast());
|
||||||
|
arp.dst_ip(_dst_ip);
|
||||||
|
|
||||||
|
_arp_waiting = true;
|
||||||
|
submit_tx_packet(pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ethernet_frame &prepare_eth(void *base, Size_guard &size_guard)
|
Ethernet_frame &prepare_eth(void *base, Size_guard &size_guard)
|
||||||
{
|
{
|
||||||
|
arp_request();
|
||||||
|
|
||||||
Ethernet_frame ð = Ethernet_frame::construct_at(base, size_guard);
|
Ethernet_frame ð = Ethernet_frame::construct_at(base, size_guard);
|
||||||
eth.src(_mac_address);
|
eth.src(_mac_address);
|
||||||
eth.dst(_dst_mac);
|
eth.dst(_dst_mac);
|
||||||
|
|||||||
Reference in New Issue
Block a user