Adds sitara_depot/free_rtos Original one is on server_gorbunov/SmartForce4.0/sitara_depot
207 lines
4.9 KiB
C++
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;
|
|
}
|