using System.Net; using DotNext; namespace Peripherals.NetConfigClient; static class NetConfigAddr { const UInt32 BASE = 0x30A7_0000; public static readonly UInt32[] HOST_IP = { BASE + 0, BASE + 1, BASE + 2, BASE + 3 }; public static readonly UInt32[] BOARD_IP = { BASE + 4, BASE + 5, BASE + 6, BASE + 7 }; public static readonly UInt32[] HOST_MAC = { BASE + 8, BASE + 9, BASE + 10, BASE + 11, BASE + 12, BASE + 13 }; public static readonly UInt32[] BOARD_MAC = { BASE + 14, BASE + 15, BASE + 16, BASE + 17, BASE + 18, BASE + 19 }; } /// /// Network configuration client for FPGA board communication /// public class NetConfig { private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); readonly int timeout = 2000; readonly int taskID; readonly int port; readonly string address; private IPEndPoint ep; /// /// Initialize NetConfig client /// /// Target board address /// Target board port /// Task identifier /// Timeout in milliseconds public NetConfig(string address, int port, int taskID, int timeout = 2000) { if (timeout < 0) throw new ArgumentException("Timeout couldn't be negative", nameof(timeout)); this.address = address; this.taskID = taskID; this.port = port; this.ep = new IPEndPoint(IPAddress.Parse(address), port); this.timeout = timeout; } /// /// Set host IP address /// /// IP address to set /// Result indicating success or failure public async ValueTask> SetHostIP(IPAddress ip) { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ipBytes = ip.GetAddressBytes(); var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_IP, ipBytes, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to set host IP: {ret.Error}"); return new(ret.Error); } if (!ret.Value) { logger.Error($"Failed to set host IP: operation returned false"); return false; } // 验证设置结果 var verifyResult = await GetHostIP(); if (!verifyResult.IsSuccessful) { logger.Error($"Failed to verify host IP after setting: {verifyResult.Error}"); return new(verifyResult.Error); } var expectedIP = ip.ToString(); if (verifyResult.Value != expectedIP) { logger.Error($"Host IP verification failed: expected {expectedIP}, got {verifyResult.Value}"); return false; } logger.Info($"Successfully set and verified host IP: {expectedIP}"); return true; } /// /// Set board IP address /// /// IP address to set /// Result indicating success or failure public async ValueTask> SetBoardIP(IPAddress ip) { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ipBytes = ip.GetAddressBytes(); var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_IP, ipBytes, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to set board IP: {ret.Error}"); return new(ret.Error); } if (!ret.Value) { logger.Error($"Failed to set board IP: operation returned false"); return false; } // 验证设置结果 var verifyResult = await GetBoardIP(); if (!verifyResult.IsSuccessful) { logger.Error($"Failed to verify board IP after setting: {verifyResult.Error}"); return new(verifyResult.Error); } var expectedIP = ip.ToString(); if (verifyResult.Value != expectedIP) { logger.Error($"Board IP verification failed: expected {expectedIP}, got {verifyResult.Value}"); return false; } logger.Info($"Successfully set and verified board IP: {expectedIP}"); return true; } /// /// Set host MAC address /// /// MAC address bytes (6 bytes) /// Result indicating success or failure public async ValueTask> SetHostMAC(byte[] macAddress) { if (macAddress == null) throw new ArgumentNullException(nameof(macAddress)); if (macAddress.Length != 6) throw new ArgumentException("MAC address must be 6 bytes", nameof(macAddress)); // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_MAC, macAddress, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to set host MAC address: {ret.Error}"); return new(ret.Error); } if (!ret.Value) { logger.Error($"Failed to set host MAC address: operation returned false"); return false; } // 验证设置结果 var verifyResult = await GetHostMAC(); if (!verifyResult.IsSuccessful) { logger.Error($"Failed to verify host MAC after setting: {verifyResult.Error}"); return new(verifyResult.Error); } var expectedMAC = string.Join(":", macAddress.Select(b => $"{b:X2}")); if (verifyResult.Value != expectedMAC) { logger.Error($"Host MAC verification failed: expected {expectedMAC}, got {verifyResult.Value}"); return false; } logger.Info($"Successfully set and verified host MAC: {expectedMAC}"); return true; } /// /// Set board MAC address /// /// MAC address bytes (6 bytes) /// Result indicating success or failure public async ValueTask> SetBoardMAC(byte[] macAddress) { if (macAddress == null) throw new ArgumentNullException(nameof(macAddress)); if (macAddress.Length != 6) throw new ArgumentException("MAC address must be 6 bytes", nameof(macAddress)); // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_MAC, macAddress, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to set board MAC address: {ret.Error}"); return new(ret.Error); } if (!ret.Value) { logger.Error($"Failed to set board MAC address: operation returned false"); return false; } // 验证设置结果 var verifyResult = await GetBoardMAC(); if (!verifyResult.IsSuccessful) { logger.Error($"Failed to verify board MAC after setting: {verifyResult.Error}"); return new(verifyResult.Error); } var expectedMAC = string.Join(":", macAddress.Select(b => $"{b:X2}")); if (verifyResult.Value != expectedMAC) { logger.Error($"Board MAC verification failed: expected {expectedMAC}, got {verifyResult.Value}"); return false; } logger.Info($"Successfully set and verified board MAC: {expectedMAC}"); return true; } /// /// Get host IP address /// /// Host IP address as string public async ValueTask> GetHostIP() { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_IP, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to get host IP: {ret.Error}"); return new(ret.Error); } var ip = ""; for (int i = 0; i < NetConfigAddr.HOST_IP.Length; i++) { ip += $"{ret.Value[i * 4 + 3]}"; if (i != NetConfigAddr.HOST_IP.Length - 1) ip += "."; } return ip; } /// /// Get board IP address /// /// Board IP address as string public async ValueTask> GetBoardIP() { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_IP, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to get board IP: {ret.Error}"); return new(ret.Error); } var ip = ""; for (int i = 0; i < NetConfigAddr.BOARD_IP.Length; i++) { ip += $"{ret.Value[i * 4 + 3]}"; if (i != NetConfigAddr.BOARD_IP.Length - 1) ip += "."; } return ip; } /// /// Get host MAC address /// /// Host MAC address as formatted string (XX:XX:XX:XX:XX:XX) public async ValueTask> GetHostMAC() { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_MAC, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to get host MAC address: {ret.Error}"); return new(ret.Error); } var mac = ""; for (int i = 0; i < NetConfigAddr.HOST_MAC.Length; i++) { mac += $"{ret.Value[i * 4 + 3]:X2}"; if (i != NetConfigAddr.HOST_MAC.Length - 1) mac += ":"; } return mac; } /// /// Get board MAC address /// /// Board MAC address as formatted string (XX:XX:XX:XX:XX:XX) public async ValueTask> GetBoardMAC() { // 清除UDP服务器接收缓冲区 MsgBus.UDPServer.ClearUDPData(this.address, this.taskID); // 刷新ARP var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address); if (!refrshRet) { logger.Warn($"Refrash Arp failed, but maybe not a big deal."); } var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_MAC, this.timeout); if (!ret.IsSuccessful) { logger.Error($"Failed to get board MAC address: {ret.Error}"); return new(ret.Error); } var mac = ""; for (int i = 0; i < NetConfigAddr.BOARD_MAC.Length; i++) { mac += $"{ret.Value[i * 4 + 3]:X2}"; if (i != NetConfigAddr.BOARD_MAC.Length - 1) mac += ":"; } return mac; } }