212 lines
5.6 KiB
C++
212 lines
5.6 KiB
C++
/*
|
||
* eth_arp.cpp
|
||
*
|
||
* Created on: 13 <20><><EFBFBD>. 2023 <20>.
|
||
* Author: sychev
|
||
*/
|
||
#include "ethernet_ip/eth_arp.hpp"
|
||
#include "ethernet/eth_frame.h"
|
||
#include "ethernet_ip/eth_prots_id.h"
|
||
#include "ethernet_ip/eth_ip_types.h"
|
||
|
||
#include <cstring>
|
||
|
||
#define ARP_ETH_TYPE_BE 0x1000
|
||
|
||
void free_rtos::clock_timeout(ClockP_Object * obj, void * arg)
|
||
{
|
||
EthArp * p_arp = ( EthArp *)arg;
|
||
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ip
|
||
if (p_arp->tmrGratuitous_.tick(100))
|
||
{
|
||
if (p_arp->table_mac_.empty()) {
|
||
p_arp->request(p_arp->self_ip_);
|
||
}
|
||
}
|
||
|
||
for (auto& item : p_arp->table_ip_)
|
||
{
|
||
auto& ip_data = item.second;
|
||
if (ip_data.tmr.tick(100))
|
||
{
|
||
if (++ip_data.attemps >= p_arp->max_attemps_)
|
||
{
|
||
ip_data.tmr.stop();
|
||
ip_data.attemps = 0;
|
||
}
|
||
else
|
||
{
|
||
p_arp->request(item.first); /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> mac <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ip
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
free_rtos::EthArp::EthArp(EthStackIface& eth_stack) :
|
||
eth_stack_{eth_stack}
|
||
{
|
||
|
||
}
|
||
|
||
bool free_rtos::EthArp::init(TEthMacPorts eth_port_id, uint64_t self_mac, uint32_t self_ip)
|
||
{
|
||
self_mac_ = self_mac;
|
||
self_ip_ = self_ip;
|
||
|
||
eth_port_id_ = eth_port_id;
|
||
|
||
init_request_pkt(self_mac_, self_ip_);
|
||
|
||
clock_.init(100, free_rtos::clock_timeout, this); /// 100<30><30>
|
||
|
||
tmrGratuitous_.start(1000); /// 1 <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
clock_.start();
|
||
|
||
return true;
|
||
}
|
||
|
||
void free_rtos::EthArp::init_request_pkt(uint64_t self_mac, uint32_t self_ip)
|
||
{
|
||
TArpHeader * arp_hdr = (TArpHeader *)(request_pkt_.data + sizeof(TEthFrameHeader));
|
||
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ARP
|
||
memcpy(arp_hdr->ar_sha, &self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||
memset(arp_hdr->ar_tha, 0, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||
memcpy(arp_hdr->ar_spa, &self_ip_, ETH_IP_ADDR_LEN);
|
||
|
||
arp_hdr->ar_op = arp_opr_be_[e_oprRequest];
|
||
arp_hdr->ar_hrd = ARP_ETH_TYPE_BE;
|
||
arp_hdr->ar_pro = ETH_PROT_IP_BE;
|
||
|
||
arp_hdr->ar_hln = ETH_FRAME_MAC_ADDR_LEN_BYTES;
|
||
|
||
arp_hdr->ar_pln = ETH_IP_ADDR_LEN;
|
||
}
|
||
|
||
bool free_rtos::EthArp::request(uint32_t ip)
|
||
{
|
||
TArpHeader * arp_hdr = (TArpHeader *)(request_pkt_.data + sizeof(TEthFrameHeader));
|
||
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ip-<2D><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
memcpy(arp_hdr->ar_tpa, &ip, ETH_IP_ADDR_LEN);
|
||
|
||
request_pkt_.length = sizeof(TArpHeader);
|
||
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
return eth_stack_.send_pkt(eth_port_id_, ETH_FRAME_MAC_ADDR_BROADCAST, ETH_PROT_ARP_BE, request_pkt_);
|
||
}
|
||
|
||
bool free_rtos::EthArp::try_request(uint32_t ip)
|
||
{
|
||
ArpIpReqData * p_ip_req_data = nullptr;
|
||
auto item = table_ip_.find(ip);
|
||
|
||
if (item == table_ip_.end())
|
||
{
|
||
p_ip_req_data = &table_ip_[ip]; ///
|
||
}
|
||
else
|
||
{
|
||
p_ip_req_data = &item->second;
|
||
if (p_ip_req_data->mac != 0) {
|
||
return true; /// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
}
|
||
else if (p_ip_req_data->tmr.is_started()) {
|
||
return true; /// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
|
||
}
|
||
}
|
||
|
||
p_ip_req_data->attemps = 0;
|
||
p_ip_req_data->tmr.start(1000); /// <20><><EFBFBD><EFBFBD><EFBFBD> 1 <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD>
|
||
|
||
return request(ip);
|
||
}
|
||
|
||
void free_rtos::EthArp::add(uint64_t mac, uint32_t ip) {
|
||
table_mac_[mac] = ip;
|
||
|
||
auto& item = table_ip_[ip];
|
||
|
||
item.mac = mac;
|
||
item.attemps = 0;
|
||
item.tmr.stop();
|
||
}
|
||
|
||
bool free_rtos::EthArp::getIpAddr(uint64_t mac, uint32_t& ip) {
|
||
auto item = table_mac_.find(mac);
|
||
|
||
if (item == table_mac_.end()) {
|
||
return false;
|
||
}
|
||
|
||
ip = item->second;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool free_rtos::EthArp::getMacAddr(uint32_t ip, uint64_t& mac) {
|
||
auto item = table_ip_.find(ip);
|
||
|
||
if (item == table_ip_.end()) {
|
||
try_request(ip);
|
||
return false;
|
||
}
|
||
|
||
mac = item->second.mac;
|
||
|
||
return true;
|
||
}
|
||
|
||
int32_t free_rtos::EthArp::Process(uint8_t * p_data, uint32_t len)
|
||
{
|
||
TArpHeader * arp_hdr = (TArpHeader *)(p_data);
|
||
uint16_t type = arp_hdr->ar_op;
|
||
|
||
uint64_t mac_sender = 0;
|
||
uint32_t ip_sender = 0;
|
||
|
||
memcpy(&mac_sender, arp_hdr->ar_sha, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||
memcpy(&ip_sender, arp_hdr->ar_spa, ETH_IP_ADDR_LEN);
|
||
|
||
/**
|
||
* <20><><EFBFBD><EFBFBD> ip == 0, <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "Who has....".
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>.
|
||
*/
|
||
if (ip_sender == 0) {
|
||
return 0;
|
||
}
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> arp-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
add(mac_sender, ip_sender);
|
||
|
||
if ( type == arp_opr_be_[e_oprRequest])
|
||
{
|
||
uint32_t ip_target;
|
||
memcpy(&ip_target, arp_hdr->ar_tpa, ETH_IP_ADDR_LEN);
|
||
|
||
if (ip_target == self_ip_)
|
||
{
|
||
/// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
arp_hdr->ar_op = arp_opr_be_[e_oprReply];
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> mac <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
memcpy(arp_hdr->ar_tha, arp_hdr->ar_sha, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||
memcpy(arp_hdr->ar_sha, &self_mac_, ETH_FRAME_MAC_ADDR_LEN_BYTES);
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ip <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
memcpy(arp_hdr->ar_tpa, arp_hdr->ar_spa, ETH_IP_ADDR_LEN);
|
||
memcpy(arp_hdr->ar_spa, &self_ip_, ETH_IP_ADDR_LEN);
|
||
|
||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
return len;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
uint32_t free_rtos::EthArp::Sender(uint8_t * p_data, size_t scatter_segment)
|
||
{
|
||
return 0;
|
||
}
|