sitara_depot/components/free_rtos/ethernet_ip/eth_arp.cpp

209 lines
4.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* eth_arp.cpp
*
* Created on: 13 мар. 2023 г.
* Author: sychev
*/
#include "free_rtos/ethernet_ip/eth_arp.hpp"
#include "free_rtos/ethernet/eth_frame.h"
#include "free_rtos/ethernet_ip/eth_prots_id.h"
#include "free_rtos/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;
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);
}
}
}
}
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);
tmrGratuitous_.start(1000);
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));
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));
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);
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);
if (ip_sender == 0) {
return 0;
}
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];
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);
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;
}
uint16_t free_rtos::EthArp::Sender(HandlerArgs& handlerArgs, size_t scatter_segment)
{
return 0;
}