<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=US-ASCII">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2654.45">
<TITLE>RE: Geting remote and locale ip addresses - the functionality</TITLE>
</HEAD>
<BODY>
<BR>
<BR>

<P><FONT SIZE=2>>-----Original Message-----</FONT>
<BR><FONT SIZE=2>>From: Fab Tillier [<A HREF="mailto:ftillier@silverstorm.com">mailto:ftillier@silverstorm.com</A>]</FONT>
<BR><FONT SIZE=2>>Sent: Wednesday, September 07, 2005 9:01 PM</FONT>
<BR><FONT SIZE=2>>To: 'Tzachi Dar'; openib-windows@openib.org</FONT>
<BR><FONT SIZE=2>>Subject: RE: Geting remote and locale ip addresses - the functionality</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> From: Tzachi Dar [<A HREF="mailto:tzachid@mellanox.co.il">mailto:tzachid@mellanox.co.il</A>]</FONT>
<BR><FONT SIZE=2>>> Sent: Wednesday, September 07, 2005 2:46 AM</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> In a previous mail Fab asked the following questions:</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> What functionality should IPoIB provide?  Should it provide?</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> 1. IP to path</FONT>
<BR><FONT SIZE=2>>> 2. Ethernet MAC to path</FONT>
<BR><FONT SIZE=2>>> 3. IP to GID</FONT>
<BR><FONT SIZE=2>>> 4. Ethernet MAC to GID</FONT>
<BR><FONT SIZE=2>>> 5. Get all locally assigned IP addresses</FONT>
<BR><FONT SIZE=2>>> 6. Path validation (e.g. given an IP pair and a path, return validity of</FONT>
<BR><FONT SIZE=2>>> path)</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> WSD would care most about 1, 5, and 6.  DAPL probably only cares about 1</FONT>
<BR><FONT SIZE=2>>and</FONT>
<BR><FONT SIZE=2>>> 6. What about SDP?</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> Before I'll try to answer the questions I'll say that I assume that each</FONT>
<BR><FONT SIZE=2>>> adapter has one mac address and that it can have one or many IP's. This</FONT>
<BR><FONT SIZE=2>>is</FONT>
<BR><FONT SIZE=2>>> not always the case, but this is the very big majority of the cases.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Will we need to support multiple MAC addresses per instance?  What about</FONT>
<BR><FONT SIZE=2>>multiple GIDs per instance?</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>I believe that in the near future we will not have to support such scenarios. </FONT>
</P>

<P><FONT SIZE=2>>> The questions above are not very clear since they don't really say if</FONT>
<BR><FONT SIZE=2>>this</FONT>
<BR><FONT SIZE=2>>> is remote IP or local ip, that should be used. Still, I'll try to explain</FONT>
<BR><FONT SIZE=2>>> the way I see things.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Items 1-4 in my list take as input pairs of IP or MAC addresses (source &</FONT>
<BR><FONT SIZE=2>>destination).  Items 3 and 4 return a pair of GIDs (source & destination).</FONT>
<BR><FONT SIZE=2>>Sorry for not clarifying this in my original mail.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> On SDP and WSD (I don't know about DAPL) one gets the remote IP that he</FONT>
<BR><FONT SIZE=2>>has</FONT>
<BR><FONT SIZE=2>>> to connect to it. He might get the local IP.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>WSD has the local IP - the WSD switch binds sockets to a specific IP before</FONT>
<BR><FONT SIZE=2>>using them in a connection.  So a connect request always has both the</FONT>
<BR><FONT SIZE=2>>source and</FONT>
<BR><FONT SIZE=2>>destination IP addresses.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> If he doesn't get the locale</FONT>
<BR><FONT SIZE=2>>> IP, he should be able to find it. Windows supplies the GetBestRoute</FONT>
<BR><FONT SIZE=2>>function</FONT>
<BR><FONT SIZE=2>>> that does exactly this. This function exists in user mode, I'm not sure</FONT>
<BR><FONT SIZE=2>>if</FONT>
<BR><FONT SIZE=2>>> it exists in kernel mode, and in any case this is not something that the</FONT>
<BR><FONT SIZE=2>>> IPOIB should know about. From here I assume that we have both IP's.</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> Given the locale IP and the remote IP one should be able to find both</FONT>
<BR><FONT SIZE=2>>ports</FONT>
<BR><FONT SIZE=2>>> GIDS. This is something that the IPOIB should be able to supply.</FONT>
<BR><FONT SIZE=2>>></FONT>
<BR><FONT SIZE=2>>> Let's look at the problem of converting the locale IP to a port's GID</FONT>
<BR><FONT SIZE=2>>(and</FONT>
<BR><FONT SIZE=2>>> probably also the HCA's GID). This information should be known to the</FONT>
<BR><FONT SIZE=2>>IPOIB,</FONT>
<BR><FONT SIZE=2>>> and we can make a query that gets the answer. In appendix a I explain how</FONT>
<BR><FONT SIZE=2>>> one can get this information even without using the IPOIB module.</FONT>
<BR><FONT SIZE=2>>> We will have to decide if we want to take the way from the appendix or</FONT>
<BR><FONT SIZE=2>>> create more changes to IPOIB. In any case, we have to note that this</FONT>
<BR><FONT SIZE=2>>> information changes. No matter how we do it, this makes the problem much</FONT>
<BR><FONT SIZE=2>>> more complicated (if you are pessimistic and much more interesting if you</FONT>
<BR><FONT SIZE=2>>> are optimistic).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>IPoIB has a list of all locally assigned IP addresses.  It currently only</FONT>
<BR><FONT SIZE=2>>support IPv4, but should be simple enough to extend to support IPv6.  The</FONT>
<BR><FONT SIZE=2>>local</FONT>
<BR><FONT SIZE=2>>IP addresses are stored in ipoib_adapter_t::ip_vector, and are of type</FONT>
<BR><FONT SIZE=2>>net_address_item_t.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> The second problem is getting the remote GID from the remote IP. This</FONT>
<BR><FONT SIZE=2>>> information is only known to the IPOIB module. After doing an arp (can be</FONT>
<BR><FONT SIZE=2>>> done easily from user mode and we should have the IP translated to the</FONT>
<BR><FONT SIZE=2>>> remote MAC). To my understanding, all information should already be in</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>> IPOIB driver as an "endpt" (the function __endpt_mgr_ref should return it</FONT>
<BR><FONT SIZE=2>>> immediately).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Right now, IPoIB doesn't sort endpoints by IP address - only GID, LID, and</FONT>
<BR><FONT SIZE=2>>MAC.</FONT>
<BR><FONT SIZE=2>>The code only supports a 1:1:1 mapping at the moment, so a MAC can only</FONT>
<BR><FONT SIZE=2>>have one</FONT>
<BR><FONT SIZE=2>>LID and GID, each LID can only have one associated MAC and GID, etc.  Is</FONT>
<BR><FONT SIZE=2>>this</FONT>
<BR><FONT SIZE=2>>something we need to change?  If we add IP to the endpoints, we will need</FONT>
<BR><FONT SIZE=2>>at</FONT>
<BR><FONT SIZE=2>>least support for many IPs to one endpoint.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>An alternative to adding IP support to IPoIB is to use the network stack to</FONT>
<BR><FONT SIZE=2>>get</FONT>
<BR><FONT SIZE=2>>us from IP to Ethernet MAC, and then perform a lookup based on that.  It is</FONT>
<BR><FONT SIZE=2>>a</FONT>
<BR><FONT SIZE=2>>bit more cumbersome, but certainly possible.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>I believe that this is the straight forward way and this is what should be used. Since there is a function that converts the remote IP to a mac addresses, I believe that we should use it and do the remote query based on this arp addresses.</FONT></P>

<P><FONT SIZE=2>>> As for translating the two gids to a path: This can be easily done by</FONT>
<BR><FONT SIZE=2>>each</FONT>
<BR><FONT SIZE=2>>> ULP and is not something special to the IPOIB driver. Still each ULP has</FONT>
<BR><FONT SIZE=2>>to</FONT>
<BR><FONT SIZE=2>>> do it, so it might be a good idea to also do the path lookup. To my</FONT>
<BR><FONT SIZE=2>>filling</FONT>
<BR><FONT SIZE=2>>> it makes things somewhat complicated, and we can avoid it, but as I said,</FONT>
<BR><FONT SIZE=2>>it</FONT>
<BR><FONT SIZE=2>>> can be done.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>I think initially supporting just the lookup from IP (or MAC) pair to GID</FONT>
<BR><FONT SIZE=2>>pair</FONT>
<BR><FONT SIZE=2>>is good enough initially.  We can extend this later to add support for</FONT>
<BR><FONT SIZE=2>>returning</FONT>
<BR><FONT SIZE=2>>the path so that we save on SA queries, or we can add caching to the access</FONT>
<BR><FONT SIZE=2>>layer for common SA records (like paths, node info, port info, etc).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> This also rises the question of doing it sync or non sync</FONT>
<BR><FONT SIZE=2>>> (which will make things even more complicated).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Assuming we're dealing with IRPs here and not a direct call interface, sync</FONT>
<BR><FONT SIZE=2>>or</FONT>
<BR><FONT SIZE=2>>async is trivial - all we need to do is follow IRP processing rules.  If</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>request is going to take some time we need to mark the IRP pending and</FONT>
<BR><FONT SIZE=2>>return</FONT>
<BR><FONT SIZE=2>>(this is critical to allow clients to call this at DISPATCH_LEVEL).  Once</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>request completes, complete the IRP.  It is then up to the caller to decide</FONT>
<BR><FONT SIZE=2>>whether to block waiting for a completion or use I/O completion</FONT>
<BR><FONT SIZE=2>>notifications.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>I would expect that for lookups into the IPoIB adapter's internal cache,</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>operations would pretty much always complete immediately.  If we ever add</FONT>
<BR><FONT SIZE=2>>logic</FONT>
<BR><FONT SIZE=2>>in IPoIB to send ARPs to resolve missing entries, asynchronous processing</FONT>
<BR><FONT SIZE=2>>will</FONT>
<BR><FONT SIZE=2>>likely be necessary.  In any case, the only requirement on us is that we</FONT>
<BR><FONT SIZE=2>>don't</FONT>
<BR><FONT SIZE=2>>perform any blocking operations in any of the IOCTL paths.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>The function that will convert the remote IP to the remote mac will very likely do the arp by itself, so I don't expect any blocking operation.</FONT></P>

<P><FONT SIZE=2>>> Path validation - I'm not sure that I understand the question, if I have</FONT>
<BR><FONT SIZE=2>>a</FONT>
<BR><FONT SIZE=2>>> path to validate, I can simply ask for the new path to be created and</FONT>
<BR><FONT SIZE=2>>> compare them, or is there anything else in this?</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>The idea of path validation is that if you receive a connection request</FONT>
<BR><FONT SIZE=2>>that</FONT>
<BR><FONT SIZE=2>>claims to have a certain source and destination IP address pair, the</FONT>
<BR><FONT SIZE=2>>recipient</FONT>
<BR><FONT SIZE=2>>needs to validate that those IP addresses are valid for the path record</FONT>
<BR><FONT SIZE=2>>provided</FONT>
<BR><FONT SIZE=2>>by the CM in the REQ callback.  Basically, the code would do a lookup of</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>source and destination IP addresses and compare the resulting GIDs to the</FONT>
<BR><FONT SIZE=2>>source</FONT>
<BR><FONT SIZE=2>>and destination GIDs in the path record provided by the CM.  This provides</FONT>
<BR><FONT SIZE=2>>a</FONT>
<BR><FONT SIZE=2>>level of validation to prevent malicious apps from pretending to have</FONT>
<BR><FONT SIZE=2>>certain</FONT>
<BR><FONT SIZE=2>>trusted IP addresses to establish a connection when they otherwise should</FONT>
<BR><FONT SIZE=2>>not be</FONT>
<BR><FONT SIZE=2>>allowed to.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>However, thinking about it more, there's nothing that prevents the</FONT>
<BR><FONT SIZE=2>>application</FONT>
<BR><FONT SIZE=2>>from doing the IP to GID lookup itself, and then comparing the results to</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>path it received.  So please disregard this "feature".</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> So to summarize:</FONT>
<BR><FONT SIZE=2>>> 1)     Get all locale ip addresses, We can do it or not do it, I</FONT>
<BR><FONT SIZE=2>>recommend</FONT>
<BR><FONT SIZE=2>>> to do it in the IPOIB. As the information changes, it would be better to</FONT>
<BR><FONT SIZE=2>>> create some notification mechanism, I suggest not implementing this</FONT>
<BR><FONT SIZE=2>>> mechanism at start.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>IPoIB already has this information, so I agree we should provide a way to</FONT>
<BR><FONT SIZE=2>>get to</FONT>
<BR><FONT SIZE=2>>it - the WSD provider certainly needs it.  We don't need to implement any</FONT>
<BR><FONT SIZE=2>>notification mechanisms for when the addresses change, as the existing</FONT>
<BR><FONT SIZE=2>>stack</FONT>
<BR><FONT SIZE=2>>already handles that.  Specifically, it doesn't matter for DAPL case</FONT>
<BR><FONT SIZE=2>>because</FONT>
<BR><FONT SIZE=2>>DAPL is static.  For WSD, the switch already polls the providers when it</FONT>
<BR><FONT SIZE=2>>detects</FONT>
<BR><FONT SIZE=2>>that an update is needed.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>The alternative is to use the IP helper functions, but there are missing</FONT>
<BR><FONT SIZE=2>>headers</FONT>
<BR><FONT SIZE=2>>from the DDK that prevent that form working properly without manually</FONT>
<BR><FONT SIZE=2>>copying</FONT>
<BR><FONT SIZE=2>>headers from the platform SDK into the DDK directories (<mprapi.h> is one</FONT>
<BR><FONT SIZE=2>>such</FONT>
<BR><FONT SIZE=2>>header).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>I think we probably want two calls here.  The first would return all CA and</FONT>
<BR><FONT SIZE=2>>port</FONT>
<BR><FONT SIZE=2>>GUIDs in use by IPoIB, with no input parameter.  The output would be</FONT>
<BR><FONT SIZE=2>>something</FONT>
<BR><FONT SIZE=2>>like an array <CA GUID, PORT NUMBER, PORT GUID> tupples.  This allows a</FONT>
<BR><FONT SIZE=2>>client</FONT>
<BR><FONT SIZE=2>>to open the CA (using the CA GUID), create a QP bound to the proper port</FONT>
<BR><FONT SIZE=2>>(using</FONT>
<BR><FONT SIZE=2>>the port number), and query for IP addresses (using the port GUID).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>The second call would take as input a port GUID, and return an array of IP</FONT>
<BR><FONT SIZE=2>>addresses assigned to that port.  The array entries should probably be 16</FONT>
<BR><FONT SIZE=2>>bytes</FONT>
<BR><FONT SIZE=2>>to accommodate IPv6 addresses, and use the standard method of storing IPv4</FONT>
<BR><FONT SIZE=2>>addresses (prefix with zero).</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Does that make sense?</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>This does make sense, however there is one thing that we might consider changing: it seems to me that the application will first do the first part and later do a query on all ports to get their IP's. Therefore I believe that we can have one function that returns all this information and save some time passing from user mode to kernel. I'm not really sure if that code would look better.</FONT></P>

<P><FONT SIZE=2>>> 2)     Get remote IP - we must implement.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Assuming this takes a source and destination IP as input and returns a</FONT>
<BR><FONT SIZE=2>>source</FONT>
<BR><FONT SIZE=2>>and destination GID as output, I agree.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>How does something like this for the IOCTL input and output buffers sound:</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>struct _IPOIB_AT_IN</FONT>
<BR><FONT SIZE=2>>{</FONT>
<BR><FONT SIZE=2>>       UCHAR           SrcIp[16];</FONT>
<BR><FONT SIZE=2>>       UCHAR           DstIp[16];</FONT>
<BR><FONT SIZE=2>>};</FONT>
<BR><FONT SIZE=2>>struct _IPOIB_AT_OUT</FONT>
<BR><FONT SIZE=2>>{</FONT>
<BR><FONT SIZE=2>>       GID             SrcGid;</FONT>
<BR><FONT SIZE=2>>       GID             DstGid;</FONT>
<BR><FONT SIZE=2>>};</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>As I said before I believe that the functionality that we are really looking for is the remote mac addresses, translated into a remote lid. (This is the information that we have). So the interface should look like: </FONT></P>

<P><FONT SIZE=2>struct _IPOIB_AT_IN</FONT>
<BR><FONT SIZE=2>{</FONT>
<BR>        <FONT SIZE=2>UCHAR           DstMac[6]; // Do we want this longer ?</FONT>
<BR><FONT SIZE=2>};</FONT>
<BR><FONT SIZE=2>>struct _IPOIB_AT_OUT</FONT>
<BR><FONT SIZE=2>{</FONT>
<BR>        <FONT SIZE=2>GID             DstGid;</FONT>
<BR><FONT SIZE=2>};</FONT>
</P>

<P><FONT SIZE=2>Does this make sense?</FONT>
</P>

<P><FONT SIZE=2>>> 3)     Get/verify path we can implement but I believe that we shouldn't</FONT>
<BR><FONT SIZE=2>>do</FONT>
<BR><FONT SIZE=2>>> it.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Yep, this isn't necessary - with the IP to GID lookup support an</FONT>
<BR><FONT SIZE=2>>application can</FONT>
<BR><FONT SIZE=2>>easily implement this functionality itself.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> Appendix A - How to get all the locale IP addresses (and even to map them</FONT>
<BR><FONT SIZE=2>>to</FONT>
<BR><FONT SIZE=2>>> InfiniBand ports):</FONT>
<BR><FONT SIZE=2>>> Windows provides the function GetAdaptersInfo which gives all IP adapters</FONT>
<BR><FONT SIZE=2>>as</FONT>
<BR><FONT SIZE=2>>> well as their locale IP. For each adapter there is a "name" that is</FONT>
<BR><FONT SIZE=2>>actually</FONT>
<BR><FONT SIZE=2>>> a guid that uniquely describes the adapter. In the registry there is a</FONT>
<BR><FONT SIZE=2>>key</FONT>
<BR><FONT SIZE=2>>> named:</FONT>
<BR><FONT SIZE=2>>> HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-</FONT>
<BR><FONT SIZE=2>>E325-1</FONT>
<BR><FONT SIZE=2>>> 1CE-BFC1-08002BE10318} that has an entry for each adapter. For each of</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>> adapters there is a sub key call Connection. Under this there is a value</FONT>
<BR><FONT SIZE=2>>> that is called PnpInstanceID this value starts with IBA\IPOIB for</FONT>
<BR><FONT SIZE=2>>InfiniBand</FONT>
<BR><FONT SIZE=2>>> devices, so we know that this is "our" card. Next there is the guid of</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>> port.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Thanks for the information - the documentation doesn't really explain what</FONT>
<BR><FONT SIZE=2>>the</FONT>
<BR><FONT SIZE=2>>name represents.  So I take it that given the name, we could query the</FONT>
<BR><FONT SIZE=2>>registry</FONT>
<BR><FONT SIZE=2>>to find out if it's an IPoIB device, and if so we could even extract the</FONT>
<BR><FONT SIZE=2>>port</FONT>
<BR><FONT SIZE=2>>GUID from the PnpInstanceId.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>> Please note that since adapters (and more likely IP addresses) change</FONT>
<BR><FONT SIZE=2>>with</FONT>
<BR><FONT SIZE=2>>> time, it is not that simple to cache the information in user mode.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>The NotifyAddrChange IPHelper function can provide the notification</FONT>
<BR><FONT SIZE=2>>mechanism</FONT>
<BR><FONT SIZE=2>>needed.  For the case of WSD, however, the switch can be used to drive</FONT>
<BR><FONT SIZE=2>>this.</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>Thanks for the details!</FONT>
<BR><FONT SIZE=2>></FONT>
<BR><FONT SIZE=2>>- Fab</FONT>
</P>

</BODY>
</HTML>