/* * 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 #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; } uint32_t free_rtos::EthArp::Sender(uint8_t * p_data, size_t scatter_segment) { return 0; }