/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // /////////////////////////////////////////////////////////////////////////////// /** * Microsoft Research, Cambridge * author: Yaron Weinsberg, Richard Black */ using NetStack.Common; using System; using System.Net; using System.Text; using System.Reflection; using System.Net.IP; using Drivers.Net; using NetStack.Configuration; using NetStack.Protocols; using NetStack.NetDrivers; namespace NetStack.Runtime { /// /// Parses XML configuration file and instantiates runtime components. /// public class XmlConfiguration { string configFile; // the driver's path (for dynamic loading) protected string driversPath; // the protocols' path (for dynamic loading) // where the actual module reside protected string protocolsPath; public XmlConfiguration(string configFile) { this.configFile = configFile; if (System.IO.File.Exists(configFile) == false) { Core.Panic("Can't locate configuration file, Exit!"); } } public XmlConfiguration() { // check if the file exists... // 1. check for .xml // 2. then for config.xml locally string appFullPath = AppDomain.CurrentDomain.BaseDirectory + AppDomain.CurrentDomain.FriendlyName; string configFile1 = AppDomain.CurrentDomain.BaseDirectory + @"config.xml"; string configFile2 = appFullPath.Substring(0,appFullPath.Length-4) + @".xml"; if (System.IO.File.Exists(configFile1)) { configFile = configFile1; } else if (System.IO.File.Exists(configFile2)) { configFile = configFile2; } else { Core.Panic("Can't locate configuration file, Exit!"); } } // loads an adapter's driver and add the relevant data structures // for managing it. protected bool LoadAdapter(ProtocolParams args, string driversPath) { // the user can ignore an adapter // so ignore it... string ignore = args["ignore"]; if (ignore != null && ignore == "true") return true; string name = ProtocolParams.LookupString(args, "name", "unknown"); string typeName = ProtocolParams.LookupString(args, "type", "unknown"); string id = ProtocolParams.LookupString(args, "id", "unknown"); int mtu = ProtocolParams.LookupInt32(args, "mtu", EthernetFormat.MaxFrameSize); int txRing = ProtocolParams.LookupInt32(args, "txRing", 64); int rxRing = ProtocolParams.LookupInt32(args, "rxRing", 64); int fwQueue = ProtocolParams.LookupInt32(args, "fwQueue", 64); IAdapterFactory factory = null; IAdapter adapter = null; try { string factoryTypeName = typeName + "Factory"; Assembly assembly = Assembly.LoadFrom(driversPath); Type[] types = assembly.GetTypes(); foreach (Type t in types) { if (t.IsClass && t.Name.Equals(typeName)) { factory = (IAdapterFactory)Activator.CreateInstance(t, null); break; } if (factory == null) throw new Exception("Can't find Adapter's Factory."); adapter = factory.CreateAdapter(name, id, txRing, rxRing); Core.Instance().RegisterAdapter(adapter, fwQueue); } } catch (Exception e) { adapter = null; Console.Out.WriteLine(e.Message); Environment.Exit(1); } IPModule ipModule = Core.Instance().GetProtocolByName("IP") as IPModule; HostConfiguration hostConfig = ipModule.HostConfiguration; for (int i = 0; ; i++) { string ipTag = String.Format("ip{0}", i); string maskTag = String.Format("mask{0}", i); string gatewayTag = String.Format("gateway{0}", i); // XXX No point-to-point support here. IPv4 address = ProtocolParams.LookupIPv4(args, ipTag, IPv4.AllOnes); IPv4 netmask = ProtocolParams.LookupIPv4(args, maskTag, IPv4.AllOnes); IPv4 gateway = ProtocolParams.LookupIPv4(args, gatewayTag, IPv4.Zero); if (address == IPv4.AllOnes || netmask == IPv4.AllOnes) { break; } hostConfig.Bindings.Add(adapter, new InterfaceIPConfiguration(address, netmask, gateway, 128) ); } #if DEBUG System.Console.Out.WriteLine("[Interface {0}]", args["name"]); System.Console.Out.WriteLine("-----------------------------"); #endif return true; } // This method dynamically loads a protocol and // initializes it. protected bool LoadProtocolModule(ProtocolParams args) { // the user can mark a protocol ignore field so // we just ignore it... string ignore = args["ignore"]; if (ignore != null && ignore == "true") return true; #if DEBUG System.Console.Out.WriteLine("[Protocol {0}]", args["name"]); foreach (string s in args.Keys) System.Console.Out.WriteLine("{0}={1}",s,args[s]); System.Console.Out.WriteLine("-----------------------------"); #endif // dynamic load the protocol // by default it is in the Runtime assembly string protocolType = args["type"]; try { IProtocol protocol = (IProtocol)Activator.CreateInstance(Type.GetType(protocolType)); if (protocol == null) throw new Exception("Can't find Protocol's Class."); // initialize the protocol protocol.Initialize(args); } catch (Exception e) { Console.Out.WriteLine(String.Format("Can't load protocol class: {0}",protocolType)); Console.Out.WriteLine(e.Message); return false; } return true; } // parse the configuration file return the root or // null if error. protected ConfigElement ParseConfiguration(bool toPrint) { ConfigElement root = null; root = ConfigFileParser.parseFile(configFile); if (root!=null && toPrint) { System.Text.StringBuilder tree = new System.Text.StringBuilder(); ConfigFileParser.printConfigurationTree(root,tree,0); System.Console.WriteLine(tree); } return root; } //handle host config protected void HandleConfiguration() { Core core = Core.Instance(); // the path of the driver assembly ConfigElement config = ParseConfiguration(false); // we start with the configuration tag... // we assume that the XML is valid! // if we have children, and we have... if (config.ChildElements.Count > 0) { foreach(ConfigElement element in config.ChildElements) { switch (element.TagName) { case "creator": break; case "date": break; case "hostname": break; case "forwarding": break; case "OutQHandlerTimeout": core.SetOutQueueHandlerInterval(Convert.ToInt32(element.Text,10)); break; case "protocol-path": protocolsPath = element.Text; break; case "drivers-path": driversPath = element.Text; break; case "backlog-size": int freeListSize = Convert.ToInt32(element.Text,10); core.ProvisionDemux( freeListSize, EthernetFormat.MaxFrameSize ); break; case "protocols": // handle the protocols // use a generic scheme and apply // it to the adapters in the future ;-) // the args include the name and type! ProtocolParams args = new ProtocolParams();; foreach(ConfigElement prot in element.ChildElements) { args.Clear(); foreach (string attr in prot.Attributes.Keys) args.Add(attr,prot.Attribute(attr)); foreach (ConfigElement protInfo in prot.ChildElements) args.Add(protInfo.TagName,protInfo.Text); // done with one... if (!LoadProtocolModule(args)) Core.Panic("Error while loading Protocol"); } break; case "adapters": // handle the adapters ProtocolParams adArgs = new ProtocolParams();; foreach(ConfigElement ad in element.ChildElements) { adArgs.Clear(); foreach (string attr in ad.Attributes.Keys) adArgs.Add(attr,ad.Attribute(attr)); foreach (ConfigElement adInfo in ad.ChildElements) adArgs.Add(adInfo.TagName,adInfo.Text); // done with one... if (!LoadAdapter(adArgs,driversPath)) Core.Panic("Error while loading an Adapter"); } break; } } } } public string ConfigurationFilename { get { return configFile; } } } } // NetStack.Runtime