// ----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ----------------------------------------------------------------------------
///
// Microsoft Research, Cambridge
//
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