sitara_depot/components/free_rtos/ethernet_ip/eth_arp.cpp
algin ae3cac8a7d feat: First commit
Adds sitara_depot/free_rtos

Original one is on server_gorbunov/SmartForce4.0/sitara_depot
2023-05-03 14:01:32 +03:00

207 lines
4.9 KiB
C++

/*
* eth_arp.cpp
*
* Created on: 13 ìàð. 2023 ã.
* 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;
/// Çàïðàøèâàåì ñîáñòâåííûé 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); /// Çàïðîñ mac àäðåñà ïî 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ìñ
tmrGratuitous_.start(1000); /// 1 ðàç â ñåêóíäó
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));
/// Çàïîëíÿåì çàãîëîâîê 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));
/// Êîïèðóåì ip-àäðåñ äëÿ çàïðîñà
memcpy(arp_hdr->ar_tpa, &ip, ETH_IP_ADDR_LEN);
request_pkt_.length = sizeof(TArpHeader);
/// Øèðîêîâåùàòåëüíûé çàïðîñ
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; /// Ìàê àäðåñ óæå èçâåñòåí
}
else if (p_ip_req_data->tmr.is_started()) {
return true; /// Îïðîñ óæå èäåò
}
}
p_ip_req_data->attemps = 0;
p_ip_req_data->tmr.start(1000); /// Îïðîñ 1 ðàçâ â ñåê
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);
/**
* åñëè ip == 0, òî ýòî çàïðîñ "Who has....".
* Îòâå÷àòü íà íåãî íå íóæíî.
*/
if (ip_sender == 0) {
return 0;
}
/// Äîáàâëÿåì çàïèñü â arp-òàáëèöó
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_)
{
/// Òèï ïàêåòà - îòâåò
arp_hdr->ar_op = arp_opr_be_[e_oprReply];
/// Ìåíÿåì ìåñòàìè mac àäðåñ
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);
/// Ìåíÿåì ìåñòàìè ip àäðåñ
memcpy(arp_hdr->ar_tpa, arp_hdr->ar_spa, ETH_IP_ADDR_LEN);
memcpy(arp_hdr->ar_spa, &self_ip_, ETH_IP_ADDR_LEN);
/// Îòïðàâëÿåì ðàçìåð ïàêåòà äëÿ îòïðàâêè
return len;
}
}
return 0;
}