Commit d208d8ef authored by Martin Vítek's avatar Martin Vítek

Working ARP reply to request

parent 292db2df
......@@ -75,14 +75,34 @@ void ARP_protocol::assembly_request(const IP& ip, ethernet_payload& payload)
memcpy(arp->IP_target, ip, 4);
}
void ARP_protocol::assembly_reply(const IP& ip, ethernet_payload& payload)
void ARP_protocol::assembly_reply(const IP& requested_ip, const MAC& requested_mac, const IP& ip, const MAC& mac, ethernet_payload& payload)
{
//TODO: implementation
arp_packet* arp = (arp_packet*)payload.data;
payload.length = sizeof(arp_packet);
arp->hw_type = __htons(ETHERNET);
arp->protocol_type = __htons(IPV4);
arp->hw_size = 6;
arp->protocol_size = 4;
arp->operation_code = __htons(ARP_REPLY);
//Requested MAC
memcpy(arp->MAC_sender, local_mac, 6);
//Requested MAC
memcpy(arp->IP_sender, local_ip, 4);
//Sender MAC
memcpy(arp->MAC_target, mac, 6);
//Sender IP
memcpy(arp->IP_target, ip, 4);
}
bool ARP_protocol::decode(const ethernet_payload& payload)
bool ARP_protocol::decode(const ethernet_payload& rx_payload, ethernet_payload& tx_payload)
{
arp_packet* arp = (arp_packet*)payload.data;
arp_packet* arp = (arp_packet*)rx_payload.data;
if (arp->hw_type != __htons(ETHERNET)) return false;
if (arp->protocol_type != __htons(IPV4)) return false;
......@@ -91,9 +111,23 @@ bool ARP_protocol::decode(const ethernet_payload& payload)
if (arp->operation_code == __htons(ARP_REQUEST))
{
//TODO: Look to cache and send reply
IP requested_ip(arp->IP_target);
//Is requested IP my IP?
if (requested_ip == local_ip)
{
assembly_reply(local_ip, local_mac, IP(arp->IP_sender), MAC(arp->MAC_sender), tx_payload);
return true;
}
//If not, search in local cache
else
{
//TODO:
}
return true;
return false;
}
if (arp->operation_code == __htons(ARP_REPLY))
......@@ -103,7 +137,9 @@ bool ARP_protocol::decode(const ethernet_payload& payload)
debug.info(buffer);
return true;
save(IP(arp->IP_sender), MAC(arp->MAC_sender));
return false;
}
return false;
......
......@@ -75,7 +75,7 @@ class ARP_protocol
bool search(const IP& ip, MAC& mac);
void assembly_request(const IP& ip, ethernet_payload& payload);
void assembly_reply(const IP& ip, ethernet_payload& payload);
void assembly_reply(const IP& requested_ip, const MAC& requested_mac, const IP& ip, const MAC& mac, ethernet_payload& payload);
bool decode(const ethernet_payload& payload);
bool decode(const ethernet_payload& rx_payload, ethernet_payload& tx_payload);
};
......@@ -44,4 +44,9 @@ class CircularBuffer
if (write_position < read_position) return (SIZE + write_position - read_position);
else return (write_position - read_position);
}
uint32_t free_space()
{
return SIZE - check();
}
};
......@@ -490,20 +490,20 @@ namespace ENC28J60_namespace
uint16_t next_packet_pointer;
rx_status_vector status;
//Go to start of packet
//Go to start of frame
write_control_register(ERDPTL, eth_rx_packet_start&0xFF);
write_control_register(ERDPTH, eth_rx_packet_start>>8);
read_buffer_memory(next_packet_pointer);
read_buffer_memory(status.vector, 4);
//Save address of next packet
//Save address of next frame
eth_rx_packet_start = next_packet_pointer;
//CRC error
if (status.bit.crc_error)
{
//Decrement packet count
//Decrement frames count
bit_field_set_in_register(ECON2, PKTDEC_bm);
debug.error("Received frame - mishmash CRC (packet was dropped)");
......@@ -515,7 +515,7 @@ namespace ENC28J60_namespace
//Length check error
if (status.bit.length_check_error)
{
//Decrement packet count
//Decrement frame count
bit_field_set_in_register(ECON2, PKTDEC_bm);
debug.error("Received frame - length field doesn't correspond with rx bytes");
......@@ -524,7 +524,7 @@ namespace ENC28J60_namespace
return false;
}
//Packet wasn't received ok
//Frame wasn't received ok
if (!status.bit.received_ok)
{
//Decrement frames count
......
......@@ -18,6 +18,7 @@ NixieStack stack(eth);
NixieStack::NixieStack(ENC28J60& eth): eth(eth),
mac(0),
broadcast_mac({0xff, 0xff, 0xff, 0xff, 0xff, 0xff}),
ip(0),
gateway(0),
link_is_up(false),
......@@ -70,7 +71,7 @@ void NixieStack::check_link()
void NixieStack::rx_handler()
{
//There is pending received packet
if (eth.flag_pending_packet)
if (eth.flag_pending_packet && rx_buffer.free_space())
{
//If was RX successuful
if (eth.rx_frame(rx_buffer.write()))
......@@ -119,6 +120,42 @@ void NixieStack::tx_handler()
}
}
void NixieStack::packet_handler()
{
//There is non processed packet
if (rx_buffer.check())
{
ethernet_frame* frame = rx_buffer.read();
switch (__htons(frame->type_length))
{
case IPV4:
break;
case ARP:
{
ethernet_frame* tx_frame = tx_buffer.write();
if (arp.decode(frame->payload, tx_frame->payload))
{
//Send ARP reply
memcpy(tx_frame->dest_address, frame->src_address, 6);
memcpy(tx_frame->src_address, mac, 6);
tx_frame->type_length = __htons(ARP);
tx_buffer.write_advance();
}
}
break;
default:
break;
}
rx_buffer.read_advance();
}
}
void NixieStack::test_tx()
{
ethernet_frame* frame = tx_buffer.write();
......
......@@ -19,6 +19,7 @@ class NixieStack
ENC28J60& eth;
MAC mac;
MAC broadcast_mac;
IP ip;
IP gateway;
......@@ -44,6 +45,8 @@ class NixieStack
void rx_handler();
void tx_handler();
void packet_handler();
//For testing
void test_tx();
......
......@@ -3,7 +3,6 @@
#include <stdint.h>
const static uint8_t broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
enum ETHERNET_FRAME_TYPE
{
......
......@@ -115,6 +115,7 @@ int main(void)
stack.check_link();
stack.rx_handler();
stack.tx_handler();
stack.packet_handler();
if (adc.done)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment