393 lines
13 KiB
C#
393 lines
13 KiB
C#
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 };
|
|
}
|
|
|
|
/// <summary>
|
|
/// Network configuration client for FPGA board communication
|
|
/// </summary>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// Initialize NetConfig client
|
|
/// </summary>
|
|
/// <param name="address">Target board address</param>
|
|
/// <param name="port">Target board port</param>
|
|
/// <param name="taskID">Task identifier</param>
|
|
/// <param name="timeout">Timeout in milliseconds</param>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set host IP address
|
|
/// </summary>
|
|
/// <param name="ip">IP address to set</param>
|
|
/// <returns>Result indicating success or failure</returns>
|
|
public async ValueTask<Result<bool>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set board IP address
|
|
/// </summary>
|
|
/// <param name="ip">IP address to set</param>
|
|
/// <returns>Result indicating success or failure</returns>
|
|
public async ValueTask<Result<bool>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set host MAC address
|
|
/// </summary>
|
|
/// <param name="macAddress">MAC address bytes (6 bytes)</param>
|
|
/// <returns>Result indicating success or failure</returns>
|
|
public async ValueTask<Result<bool>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set board MAC address
|
|
/// </summary>
|
|
/// <param name="macAddress">MAC address bytes (6 bytes)</param>
|
|
/// <returns>Result indicating success or failure</returns>
|
|
public async ValueTask<Result<bool>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get host IP address
|
|
/// </summary>
|
|
/// <returns>Host IP address as string</returns>
|
|
public async ValueTask<Result<string>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get board IP address
|
|
/// </summary>
|
|
/// <returns>Board IP address as string</returns>
|
|
public async ValueTask<Result<string>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get host MAC address
|
|
/// </summary>
|
|
/// <returns>Host MAC address as formatted string (XX:XX:XX:XX:XX:XX)</returns>
|
|
public async ValueTask<Result<string>> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get board MAC address
|
|
/// </summary>
|
|
/// <returns>Board MAC address as formatted string (XX:XX:XX:XX:XX:XX)</returns>
|
|
public async ValueTask<Result<string>> 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;
|
|
}
|
|
}
|