1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.IO; 9 using Antmicro.Renode; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Exceptions; 12 using Antmicro.Renode.Peripherals.Network; 13 using Antmicro.Renode.Peripherals.Wireless; 14 using Antmicro.Renode.Tools.Network; 15 using Antmicro.Renode.Utilities; 16 17 namespace Antmicro.Renode.Plugins.WiresharkPlugin 18 { 19 public static class INetworkLogExtensions 20 { CreateWiresharkForBLE(this Emulation emulation, string name)21 public static void CreateWiresharkForBLE(this Emulation emulation, string name) 22 { 23 CreateBLEConfiguredWireshark(emulation, name); 24 } 25 CreateWiresharkForIEEE802_15_4(this Emulation emulation, string name)26 public static void CreateWiresharkForIEEE802_15_4(this Emulation emulation, string name) 27 { 28 CreateIEEE802_15_4ConfiguredWireshark(emulation, name); 29 } 30 CreateWiresharkForCAN(this Emulation emulation, string name)31 public static void CreateWiresharkForCAN(this Emulation emulation, string name) 32 { 33 CreateCANConfiguredWireshark(emulation, name); 34 } 35 CreateWiresharkForEthernet(this Emulation emulation, string name)36 public static void CreateWiresharkForEthernet(this Emulation emulation, string name) 37 { 38 CreateEthernetConfiguredWireshark(emulation, name); 39 } 40 41 public static void LogToWireshark<T>(this Emulation emulation, INetworkLog<T> reporter, T iface) where T : INetworkInterface 42 { 43 GetConfiguredWireshark(emulation, reporter as INetworkLog<INetworkInterface>, GetName(reporter, iface)).LogToWireshark(reporter as INetworkLog<INetworkInterface>, iface); 44 } 45 LogToWireshark(this Emulation emulation, INetworkLog<INetworkInterface> reporter)46 public static void LogToWireshark(this Emulation emulation, INetworkLog<INetworkInterface> reporter) 47 { 48 GetConfiguredWireshark(emulation, reporter, GetName(reporter)).LogToWireshark(reporter); 49 } 50 LogBLETraffic(this Emulation emulation)51 public static void LogBLETraffic(this Emulation emulation) 52 { 53 var result = CreateBLEConfiguredWireshark(emulation, BLELogName); 54 foreach(var BLE in emulation.ExternalsManager.GetExternalsOfType<BLEMedium>()) 55 { 56 result.LogToWireshark((INetworkLog<INetworkInterface>)BLE); 57 } 58 59 // We detach the event before reattaching it to ensure that we are connected only once. 60 // This manouver allows us not to use an additional variable, which would be difficult 61 // to reset, as it is a static class. 62 emulation.ExternalsManager.ExternalsChanged -= AddExternal; 63 emulation.ExternalsManager.ExternalsChanged += AddExternal; 64 } 65 LogIEEE802_15_4Traffic(this Emulation emulation)66 public static void LogIEEE802_15_4Traffic(this Emulation emulation) 67 { 68 var result = CreateIEEE802_15_4ConfiguredWireshark(emulation, IEEE802_15_4LogName); 69 foreach(var IEEE802_15_4 in emulation.ExternalsManager.GetExternalsOfType<IEEE802_15_4Medium>()) 70 { 71 result.LogToWireshark((INetworkLog<INetworkInterface>)IEEE802_15_4); 72 } 73 74 // We detach the event before reattaching it to ensure that we are connected only once. 75 // This manouver allows us not to use an additional variable, which would be difficult 76 // to reset, as it is a static class. 77 emulation.ExternalsManager.ExternalsChanged -= AddExternal; 78 emulation.ExternalsManager.ExternalsChanged += AddExternal; 79 } 80 LogEthernetTraffic(this Emulation emulation)81 public static void LogEthernetTraffic(this Emulation emulation) 82 { 83 var result = CreateEthernetConfiguredWireshark(emulation, EthernetLogName); 84 foreach(var ethernet in emulation.ExternalsManager.GetExternalsOfType<Switch>()) 85 { 86 result.LogToWireshark((INetworkLog<INetworkInterface>)ethernet); 87 } 88 89 // We detach the event before reattaching it to ensure that we are connected only once. 90 // This manouver allows us not to use an additional variable, which would be difficult 91 // to reset, as it is a static class. 92 emulation.ExternalsManager.ExternalsChanged -= AddExternal; 93 emulation.ExternalsManager.ExternalsChanged += AddExternal; 94 } 95 LogCANTraffic(this Emulation emulation)96 public static void LogCANTraffic(this Emulation emulation) 97 { 98 var result = CreateCANConfiguredWireshark(emulation, CANLogName); 99 foreach(var hub in emulation.ExternalsManager.GetExternalsOfType<CANHub>()) 100 { 101 result.LogToWireshark((INetworkLog<INetworkInterface>)hub); 102 } 103 104 // We detach the event before reattaching it to ensure that we are connected only once. 105 // This manouver allows us not to use an additional variable, which would be difficult 106 // to reset, as it is a static class. 107 emulation.ExternalsManager.ExternalsChanged -= AddExternal; 108 emulation.ExternalsManager.ExternalsChanged += AddExternal; 109 } 110 AddExternal(ExternalsManager.ExternalsChangedEventArgs reporter)111 private static void AddExternal(ExternalsManager.ExternalsChangedEventArgs reporter) 112 { 113 var external = reporter.External; 114 var BLEResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(BLELogName, out var BLEWiresharkFound); 115 var IEEE802_15_4Result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(IEEE802_15_4LogName, out var IEEE802_15_4WiresharkFound); 116 var ethernetResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(EthernetLogName, out var ethernetWiresharkFound); 117 var CANResult = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(CANLogName, out var CANWiresharkFound); 118 119 if(IEEE802_15_4WiresharkFound && external is IEEE802_15_4Medium) 120 { 121 IEEE802_15_4Result.LogToWireshark((IEEE802_15_4Medium)external); 122 } 123 124 if(BLEWiresharkFound && external is BLEMedium) 125 { 126 BLEResult.LogToWireshark((BLEMedium)external); 127 } 128 129 if(ethernetWiresharkFound && external is Switch) 130 { 131 ethernetResult.LogToWireshark((Switch)external); 132 } 133 134 if(CANWiresharkFound && external is CANHub) 135 { 136 CANResult.LogToWireshark((CANHub)external); 137 } 138 } 139 GetConfiguredWireshark(Emulation emulation, INetworkLog<INetworkInterface> reporter, string hostName)140 private static Wireshark GetConfiguredWireshark(Emulation emulation, INetworkLog<INetworkInterface> reporter, string hostName) 141 { 142 if(reporter is IEEE802_15_4Medium) 143 { 144 return CreateIEEE802_15_4ConfiguredWireshark(emulation, hostName); 145 } 146 else if(reporter is BLEMedium) 147 { 148 return CreateBLEConfiguredWireshark(emulation, hostName); 149 } 150 else if(reporter is Switch) 151 { 152 return CreateEthernetConfiguredWireshark(emulation, hostName); 153 } 154 else if(reporter is CANHub) 155 { 156 return CreateCANConfiguredWireshark(emulation, hostName); 157 } 158 else 159 { 160 throw new ArgumentException("Expected CANHub, Switch, BLEMedium or IEEE802_15_4Medium."); 161 } 162 } 163 CreateBLEConfiguredWireshark(Emulation emulation, string name)164 private static Wireshark CreateBLEConfiguredWireshark(Emulation emulation, string name) 165 { 166 var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var BLEWiresharkFound); 167 168 if(BLEWiresharkFound) 169 { 170 return result; 171 } 172 173 return CreateWireshark(emulation, name, LinkLayer.Bluetooth_LE); 174 } 175 CreateIEEE802_15_4ConfiguredWireshark(Emulation emulation, string name)176 private static Wireshark CreateIEEE802_15_4ConfiguredWireshark(Emulation emulation, string name) 177 { 178 var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var wirelessWiresharkFound); 179 180 if(wirelessWiresharkFound) 181 { 182 return result; 183 } 184 185 return CreateWireshark(emulation, name, LinkLayer.IEEE802_15_4); 186 } 187 CreateEthernetConfiguredWireshark(Emulation emulation, string name)188 private static Wireshark CreateEthernetConfiguredWireshark(Emulation emulation, string name) 189 { 190 var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var ethernetWiresharkFound); 191 192 if(ethernetWiresharkFound) 193 { 194 return result; 195 } 196 197 return CreateWireshark(emulation, name, LinkLayer.Ethernet); 198 } 199 CreateCANConfiguredWireshark(Emulation emulation, string name)200 private static Wireshark CreateCANConfiguredWireshark(Emulation emulation, string name) 201 { 202 var result = (Wireshark)EmulationManager.Instance.CurrentEmulation.HostMachine.TryGetByName(name, out var CANWiresharkFound); 203 204 if(CANWiresharkFound) 205 { 206 return result; 207 } 208 209 return CreateWireshark(emulation, name, LinkLayer.CAN); 210 } 211 CreateWireshark(this Emulation emulation, string name, LinkLayer layer)212 private static Wireshark CreateWireshark(this Emulation emulation, string name, LinkLayer layer) 213 { 214 Wireshark result; 215 var wiresharkPath = ConfigurationManager.Instance.Get("wireshark", "wireshark-path", WiresharkPath); 216 if(File.Exists(wiresharkPath)) 217 { 218 result = new Wireshark(name, layer, wiresharkPath); 219 } 220 else 221 { 222 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})."); 223 } 224 225 emulation.HostMachine.AddHostMachineElement(result, name); 226 return result; 227 } 228 GetName(IEmulationElement element, IEmulationElement nextElement = null)229 private static string GetName(IEmulationElement element, IEmulationElement nextElement = null) 230 { 231 string elementName; 232 var emulation = EmulationManager.Instance.CurrentEmulation; 233 emulation.TryGetEmulationElementName(element, out elementName); 234 235 if(nextElement != null) 236 { 237 string nextElementName; 238 emulation.TryGetEmulationElementName(nextElement, out nextElementName); 239 nextElementName = nextElementName.Replace(':', '-').Replace('.', '-'); 240 return "{0}-{1}-{2}".FormatWith(WiresharkExternalPrefix, elementName, nextElementName); 241 } 242 243 return "{0}-{1}".FormatWith(WiresharkExternalPrefix, elementName); 244 } 245 246 private const string WiresharkExternalPrefix = "wireshark"; 247 private const string BLELogName = WiresharkExternalPrefix + "-" + "allBLETraffic"; 248 private const string IEEE802_15_4LogName = WiresharkExternalPrefix + "-" + "allIEEE802_15_4Traffic"; 249 private const string EthernetLogName = WiresharkExternalPrefix + "-" + "allEthernetTraffic"; 250 private const string CANLogName = WiresharkExternalPrefix + "-" + "allCANTraffic"; 251 #if PLATFORM_WINDOWS 252 private const string WiresharkPath = @"c:\Program Files\Wireshark\Wireshark.exe"; 253 #elif PLATFORM_OSX 254 private const string WiresharkPath = "/Applications/Wireshark.app/Contents/MacOS/Wireshark"; 255 #else 256 private const string WiresharkPath = "/usr/bin/wireshark"; 257 #endif 258 } 259 } 260