blob: b1a0b3cb0f560cf8659c35796cce35362581c2e1 [file] [log] [blame]
//
// Copyright (c) 2010-2024 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using System;
using System.IO;
using Antmicro.Renode;
using Antmicro.Renode.Core;
using Antmicro.Renode.Exceptions;
using Antmicro.Renode.Peripherals.Network;
using Antmicro.Renode.Peripherals.Wireless;
using Antmicro.Renode.Tools.Network;
using Antmicro.Renode.Utilities;
namespace Antmicro.Renode.Plugins.WiresharkPlugin
{
public static class INetworkLogExtensions
{
public static void CreateWiresharkForBLE(this Emulation emulation, string name)
{
CreateBLEConfiguredWireshark(emulation, name);
}
public static void CreateWiresharkForIEEE802_15_4(this Emulation emulation, string name)
{
CreateIEEE802_15_4ConfiguredWireshark(emulation, name);
}
public static void CreateWiresharkForCAN(this Emulation emulation, string name)
{
CreateCANConfiguredWireshark(emulation, name);
}
public static void CreateWiresharkForEthernet(this Emulation emulation, string name)
{
CreateEthernetConfiguredWireshark(emulation, name);
}
public static void LogToWireshark<T>(this Emulation emulation, INetworkLog<T> reporter, T iface) where T : INetworkInterface
{
GetConfiguredWireshark(emulation, reporter as INetworkLog<INetworkInterface>, GetName(reporter, iface)).LogToWireshark(reporter as INetworkLog<INetworkInterface>, iface);
}
public static void LogToWireshark(this Emulation emulation, INetworkLog<INetworkInterface> reporter)
{
GetConfiguredWireshark(emulation, reporter, GetName(reporter)).LogToWireshark(reporter);
}
public static void LogBLETraffic(this Emulation emulation)
{
var result = CreateBLEConfiguredWireshark(emulation, BLELogName);
foreach(var BLE in emulation.ExternalsManager.GetExternalsOfType<BLEMedium>())
{
result.LogToWireshark((INetworkLog<INetworkInterface>)BLE);
}
// We detach the event before reattaching it to ensure that we are connected only once.
// This manouver allows us not to use an additional variable, which would be difficult
// to reset, as it is a static class.
emulation.ExternalsManager.ExternalsChanged -= AddExternal;
emulation.ExternalsManager.ExternalsChanged += AddExternal;
}
public static void LogIEEE802_15_4Traffic(this Emulation emulation)
{
var result = CreateIEEE802_15_4ConfiguredWireshark(emulation, IEEE802_15_4LogName);
foreach(var IEEE802_15_4 in emulation.ExternalsManager.GetExternalsOfType<IEEE802_15_4Medium>())
{
result.LogToWireshark((INetworkLog<INetworkInterface>)IEEE802_15_4);
}
// We detach the event before reattaching it to ensure that we are connected only once.
// This manouver allows us not to use an additional variable, which would be difficult
// to reset, as it is a static class.
emulation.ExternalsManager.ExternalsChanged -= AddExternal;
emulation.ExternalsManager.ExternalsChanged += AddExternal;
}
public static void LogEthernetTraffic(this Emulation emulation)
{
var result = CreateEthernetConfiguredWireshark(emulation, EthernetLogName);
foreach(var ethernet in emulation.ExternalsManager.GetExternalsOfType<Switch>())
{
result.LogToWireshark((INetworkLog<INetworkInterface>)ethernet);
}
// We detach the event before reattaching it to ensure that we are connected only once.
// This manouver allows us not to use an additional variable, which would be difficult
// to reset, as it is a static class.
emulation.ExternalsManager.ExternalsChanged -= AddExternal;
emulation.ExternalsManager.ExternalsChanged += AddExternal;
}
public static void LogCANTraffic(this Emulation emulation)
{
var result = CreateCANConfiguredWireshark(emulation, CANLogName);
foreach(var hub in emulation.ExternalsManager.GetExternalsOfType<CANHub>())
{
result.LogToWireshark((INetworkLog<INetworkInterface>)hub);
}
// We detach the event before reattaching it to ensure that we are connected only once.
// This manouver allows us not to use an additional variable, which would be difficult
// to reset, as it is a static class.
emulation.ExternalsManager.ExternalsChanged -= AddExternal;
emulation.ExternalsManager.ExternalsChanged += AddExternal;
}
private static void AddExternal(ExternalsManager.ExternalsChangedEventArgs reporter)
{
var external = reporter.External;
var BLEResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(BLELogName, out var BLEWiresharkFound);
var IEEE802_15_4Result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(IEEE802_15_4LogName, out var IEEE802_15_4WiresharkFound);
var ethernetResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(EthernetLogName, out var ethernetWiresharkFound);
var CANResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(CANLogName, out var CANWiresharkFound);
if(IEEE802_15_4WiresharkFound && external is IEEE802_15_4Medium)
{
IEEE802_15_4Result.LogToWireshark((IEEE802_15_4Medium)external);
}
if(BLEWiresharkFound && external is BLEMedium)
{
BLEResult.LogToWireshark((BLEMedium)external);
}
if(ethernetWiresharkFound && external is Switch)
{
ethernetResult.LogToWireshark((Switch)external);
}
if(CANWiresharkFound && external is CANHub)
{
CANResult.LogToWireshark((CANHub)external);
}
}
private static Wireshark GetConfiguredWireshark(Emulation emulation, INetworkLog<INetworkInterface> reporter, string hostName)
{
if(reporter is IEEE802_15_4Medium)
{
return CreateIEEE802_15_4ConfiguredWireshark(emulation, hostName);
}
else if(reporter is BLEMedium)
{
return CreateBLEConfiguredWireshark(emulation, hostName);
}
else if(reporter is Switch)
{
return CreateEthernetConfiguredWireshark(emulation, hostName);
}
else if(reporter is CANHub)
{
return CreateCANConfiguredWireshark(emulation, hostName);
}
else
{
throw new ArgumentException("Expected CANHub, Switch, BLEMedium or IEEE802_15_4Medium.");
}
}
private static Wireshark CreateBLEConfiguredWireshark(Emulation emulation, string name)
{
var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var BLEWiresharkFound);
if(BLEWiresharkFound)
{
return result;
}
return CreateWireshark(emulation, name, LinkLayer.Bluetooth_LE);
}
private static Wireshark CreateIEEE802_15_4ConfiguredWireshark(Emulation emulation, string name)
{
var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var wirelessWiresharkFound);
if(wirelessWiresharkFound)
{
return result;
}
return CreateWireshark(emulation, name, LinkLayer.IEEE802_15_4);
}
private static Wireshark CreateEthernetConfiguredWireshark(Emulation emulation, string name)
{
var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var ethernetWiresharkFound);
if(ethernetWiresharkFound)
{
return result;
}
return CreateWireshark(emulation, name, LinkLayer.Ethernet);
}
private static Wireshark CreateCANConfiguredWireshark(Emulation emulation, string name)
{
var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var CANWiresharkFound);
if(CANWiresharkFound)
{
return result;
}
return CreateWireshark(emulation, name, LinkLayer.CAN);
}
private static Wireshark CreateWireshark(this Emulation emulation, string name, LinkLayer layer)
{
Wireshark result;
var wiresharkPath = ConfigurationManager.Instance.Get("wireshark", "wireshark-path", WiresharkPath);
if(File.Exists(wiresharkPath))
{
result = new Wireshark(name, layer, wiresharkPath);
}
else
{
throw new RecoverableException($"Wireshark is not installed or is not available in the default path. Please adjust the path in the Renode configuration file ({ConfigurationManager.Instance.FilePath}).");
}
emulation.HostMachine.AddHostMachineElement(result, name);
return result;
}
private static string GetName(IEmulationElement element, IEmulationElement nextElement = null)
{
string elementName;
var emulation = EmulationManager.Instance.CurrentEmulation;
emulation.TryGetEmulationElementName(element, out elementName);
if(nextElement != null)
{
string nextElementName;
emulation.TryGetEmulationElementName(nextElement, out nextElementName);
nextElementName = nextElementName.Replace(':', '-').Replace('.', '-');
return "{0}-{1}-{2}".FormatWith(WiresharkExternalPrefix, elementName, nextElementName);
}
return "{0}-{1}".FormatWith(WiresharkExternalPrefix, elementName);
}
private const string WiresharkExternalPrefix = "wireshark";
private const string BLELogName = WiresharkExternalPrefix + "-" + "allBLETraffic";
private const string IEEE802_15_4LogName = WiresharkExternalPrefix + "-" + "allIEEE802_15_4Traffic";
private const string EthernetLogName = WiresharkExternalPrefix + "-" + "allEthernetTraffic";
private const string CANLogName = WiresharkExternalPrefix + "-" + "allCANTraffic";
#if PLATFORM_WINDOWS
private const string WiresharkPath = @"c:\Program Files\Wireshark\Wireshark.exe";
#elif PLATFORM_OSX
private const string WiresharkPath = "/Applications/Wireshark.app/Contents/MacOS/Wireshark";
#else
private const string WiresharkPath = "/usr/bin/wireshark";
#endif
}
}