Sunday, March 18, 2012

One step forward, two steps back


So this past week was spent mostly investigating and understanding how exactly a packet arrives at the DE4. We did spend a good time writing a simple algorithm to route packets but unfortunately, we probably won't end up using this as this was more to learn how the routing process works. In doing this, we found a major flaw in our program.

First, we started by tracing how a packet arrives. First we found that it seems to all start in the TK_ENTRY() function defined in netmain() in netmain.c. Here it polls for a change in the queue (rcvdq.q_len) to see if it changed. If the length changed, it will call the function pktdemux() which should then call the ip_rcv function to demux and then ip_rcv_phase2() which will attempt to route the packet.
Next we looked into how the queue is changed. First, there is an interrupt function called from tse_sgdmaRx_isr inside ins_tse_mac.c. Inside thsi function, it checks if there is room inside rcvdq and looks at the SGDMA status. If allowed, it will then go into the tse_mac_rcv(). Inside this function, the bits are adjusted to form a correct frame length and then puts the packet into the queue.

After we understood how the packet arrives, we wanted to write a simple packet sniffer such that every packet coming in is printed out. Instead, we just ran ipdump() at the ip_recv function. Next we wanted to use this information and try to rewrite headers and send out the modified packet using raw_send() from the PACKET struct. At the same time, we haven't been able to thoroughly test this since a packet not destined for the device does not get to the ip_recv function because of a problem.
It was here we saw problems sprout. The first problem we saw was that raw_send() didn't seem to send out the type of packet we wanted to. The next problem was that we finally realized that with our previous configuration, all packets were sent out only through one interface.
The final, more immediately important, problem was that we found that any packet with the destination that wasn't the interface it was sent to would have a different offset in the IP header. An example would be if we send a ping from 192.168.0.104 to 192.168.0.102 (eth1 on the DE4 board), the board would read this correctly .If we send a ping from 192.168.0.104 to 192.168.0.137, the board would not read this correctly and the packet header would show that the source was 118.226.192.168 and the destination was 0.4.0.0. This is the important issue right now because any packet coming in that isn't destined for the devices on the board will not be read in correctly and will not be analyzed by the ip_rcv function.

NIOSII-Week6

This week I am working on getting the SSS working for the board.
I was able to run Hello World on SRAM, so the sram works.
I was able to get SSS loaded on the board, but DHCP was get the IP address.
DHCP times out and goes back to static. I was not able to telnet or ping it.
Not sure what the problems is I checked the pins, SOPC builder and  SSS C code.
I was able to get SSS working with DHCP and was able to telnet it and make it
change the LED lights. Now I am trying to get the second ethernet port on the daughter card.
I was able to figure out the pins for the ethernet daughter card. I was not able to get the second
ethernet port to work.

Saturday, March 10, 2012

Stratix Subproject progress (Week 5)

This week was largely spent on attempting to change the pin layouts from the older version to the newer one. The problem was that pins were set to the locations based on the old names in the previous project's version. In the new version, different names were used. Thus, it was necessary to intuitively shift the pin locations to the newer names. This PDF file from Altera's website (especially page 20) served as a guide in determining pin purpose and locations. The Pin Planner in quartus was used to effect the actual changes.

Simon discovered that some of the shared signals were unnecessary, and after the appropriate changes were made in SOPC builder (and after the system was regenerated) the pins were correctly set.

Now, work continues on the software portion of the project, on the C program files.

More on multiple ethernet ports

Here is a blog post just detailing David's explanation and perhaps going a little bit more in depth in the steps we took to get where we were at.

The first thing we tried to do was make sure we had our Verilog and sopc files correct. In SOPC, a new TSE_MAC device was added along with two SGDMAs for receiving and transferring. In Verilog, we just made sure both of our ethernet devices were being defined correctly with "arrays".

Next, we started with the Simple Socket Server template given to us from Eclipse. The first problem we encountered was that from just the template, a MAC address was not being assigned. Instead, it would ask for a serial number and when anything was typed in, it would just assign the MAC address to FF:FF:FF:FF:FF:FF. Because of this, we looked into exactly where the ethernet device was initialized at first. We traced it down to the bsp/alt_sys_init.c file and saw that the TSE_MAC device was initialized in the function alt_sys_init(). This wasn't much help at first so we backtracked a bit to look at the all the functions which actually modified the MAC address. We found these in sss/network_utilities.c. The first thing we modified here was to get rid of any calls to a serial number but this didn't really solve anything. The MAC address would still be the same. We didn't want to define the MAC address exactly because we knew that there was at least one MAC address in flash. We spent a while trying to open in flash and ended up giving up for a while on that and instead just assigned a random MAC address to our ethernet port. This meant we just modified one of the function calls inside sss/network_utilities.c such that a random serial number would be generated and a random MAC address would be assigned based off of this random serial number. Once we got this MAC address up, the SSS was working exactly how we wanted it to.

We moved on to starting to work on getting two ethernet devices up. We had already enabled it all in our Verilog code and SOPC builder so we focused on looking through where in our program we should initialize the devices. We studied through where any device was called and ended up at the bsp/alt_sys_init.c file. The way we got here was we traced how alt_inich_init() was called in our main Simple Socket Server task (in sss/iniche_init.c). In the previously mentioned alt_sys_init() function, all the ethernet devices were being initialized. At first, we couldn't exactly figure out why both devices weren't coming up so we looked into how these devices were setup in the iniche drivers. Through Professor Pak Chan's hint, we started using the function alt_tse_system_add_sys(). To use this, we also had to make sure we initiated each device needed to go into the argument fields of this function. This has been previously discussed in depth by David so I will not get into it. At first, we put all of these statements into SSSInitialTask() in the iniche_init.c file because this is where our SSS would start. When we started testing it, we saw your devices would come up, but our DE4 board seemed to no longer function as a DHCP client. With further investigation, we found that our devices were still sending out DHCP discover packets (found through using Wireshark to trace the packets) but would not accept any packets. I have talked about our troubles with this in a previous post so to make a long story short, we figured out we were not accepting packets because we closed the OpenCore Plus IP dialog box when programming. We next just moved the alt_tse_system_add_sys() calls to bsp/alt_sys_init.c, where the rest of the devices were being setup. After a few tests and some fine tuning to the way we acquire a MAC address, we finally got our SSS server with two ethernet ports up.

While it did take us a long time, all our debugging led us to understand more clearly how an ethernet device is setup, how DHCP works in regards to the ethernet device, and how the MAC address is acquired/assigned. Our next task is to investigate into the way MicroCOS looks and interacts with packets. We will be looking at functions that interact with packets, packet headers, and sending. With our two ethernet devices setup, we will be trying to make a simple forwarding router soon. More updates will come as more progress is made.

NIOSII-Week5

This week I worked on SOPC builder and setting the pins for the components.
Components in the SOPC are
CPU
Tristate Bridge
LAN
RAM/ROM
Timer
Timer 2
JTAG
UART
System ID
FLASH
SRAM
SDRAM
PIO

Added all verilog files from SOPC to project. FPGA pins from SOPC builder are all set.
There was problem when compiling with data0 and tri_state_bus_data being in the same pin.
I looked at the qsf file of the standard layout and found how to fix the problem. I had to add
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" to my qsf file to make it work. I was able to compile. When I try to run hello world
I get error where ELF proccess failed. So that means there is something wrong with the pins/mem/design that maked ELF unable to load.

Fixed ELF proccess failed, reason was the there was no clk. Had to create 50mhz clock in timing analyzer. Was able to run Hello World on onchip mem.

Friday, March 9, 2012

Modified Simple Socket Server (Interfaces)

During the past few weeks I have been continuing on trying to get the second interface to work on the modified simple socket server example.    The verilog file has been changed once again to force enable the opening of the second interface (eth1).  Most of the work trying to get the second interface to work involved manipulating/hacking some files within the Altera BSP plugin in Eclipse.  The main files that I have been looking at were particularly ones inside the driver folder of the board support package provided by Altera, particularly on ins_tse_mac.c, altera_avaolon_tse_system_info.c, altera_avalon_tse.c and their respective C Header files in the 'inc' folder.   ins_tse_mac.c contains the methods used to configure the TSE MACs and the public API for the TSE driver. 


The most important method in that file to enable the use of multiple interfaces is  alt_tse_system_add_sys, which defines and adds a TSE system/interface onto an array that will be read to tell the board that a second interface is available to use.  For now, I am assuming that this method will be used twice; one for the first interface and one for the second interface.  The reason I am using it twice is because the simple socket server's default assignment only allows the use of one interface (eth0), so it must be overridden to make use of more than one interface. The file in which I used the add_sys function is in alt_sys_init.c, which is the HAL initialization source file.  Before add_sys can be called though, the objects used to pass into as parameters for add_sys had to be instantiated, such as 'sys_mac_0 = {TSE_SYSTEM_MAC(TSE_MAC_0)};' with type 'alt_tse_system_mac'.  The name TSE_MAC_0 inside TSE_SYSTEM_MAC comes from the names given by system.h, which is created by the the configuration given by the SOPC builder. In other words, the names used to create these objects for add_sys must be exactly named as configured by the system.h file/SOPC builder.


After adding the functions mentioned above, Matt and I tried testing out the program on the DE4 board and the board can then detect and prepare two interfaces.  Based on the debug messages from the program, each TSE MAC has their own physical address in memory as it should (and exactly the ones configured in SOPC builder) and links for the PHYs for both interface can be established.  The first time we tested this out though, our DHCP was not working and we got unreasonable IP addresses (not part of the subnet of the router's IP address) that we couldn't even ping/telnet to.  Unfortunately, we found out the reason for all this trouble is because of a dialog box that must not be closed in the JTAG programmer program, which enables the forwarding of packets to the board (OpenCore Plus IP).  Once we realized that, we tested the program out again and DHCP works again.

As of now, the NicheStack has to be modified so messages can be received and queued asynchronously using both interfaces and then processed synchronously by the server.  I am particularly looking at the os_q.c file contained in the UCOSII folder, which contains the queue management functions for the RTOS.  A DHCP server must also be implemented for the board at the moment.

Tuesday, March 6, 2012

DE4: Ethernet accepting packets!

At first (the last week or so), we were having a problem with our DE4 ethernet devices not accept packets. We spent days pouring through each function and trying to find a reason for this. We used Wireshark to make sure it was sending the DHCP requests and to make sure our routers were replying to DHCP requests. After some guidance from Professor Pak Chan, we found ourselves stuck in the same location (except now our MAC addresses were being read from the flash correctly).
We ended up starting over and for some reason, still couldn't receive any packets on our board. So after another few hours of testing, we found that there was no problem with the code or anything. In fact, the problem was that we pressed "Cancel" on the OpenCore Plus IP dialog box after programming onto the board.  As upsetting as this was (we could have finished last week), we at least walk away from this experience knowing more about each function that is being used and an experience of how MicroCOS works.

Now that we know that, we have setup the simple socket server on two interfaces. Right now, we only have two problems that don't exactly meet what we want. The first one is that we need to find the place to read in the MAC address for eth1. As it is now, all we did was move a pointer up based on which number eth device is being initialized. The second problem is that right now, we only have one SSS task running. Ideally, I believe we are supposed to have a task for each device. I'm not exactly sure how to declare a device per task and right now, it seems that it can run SSS at a time (meaning it works on both ports as long as the telnet session is not happening concurrently). We will iron this out soon. A separate write up is on it's way once we iron out all the details.

Friday, March 2, 2012

NIOSII-Week4

2/29/12
Error for NIOS IDE was due to Quartus 5 not work for Window 7. So I have to use Quartus 11.1 to build the SOPC file and C files.

3/2/12
For SSS project need to change variables to match variables in system.h
Got SSS to complie on eclipse.
Since old pin layout pin names are diffrenent have to add pins that have different name than old pin layout.

Packet Generator 3/2/12

Packet Generator

First and foremost, I apologize for taking so long to develop a packet generator.

For this part, the first thing I wanted to do was investigate the pcap library which tcpdump uses. This library allows the program to investigate the IP and link layer packets coming in. This may or may not be necessary but I wanted the program to, in the future, be able to investigate all the packets coming through similar to tcpdump. There is a similar library for Windows called WinPcap which also provides a send function. At first, I thought the Pcap library had it's own specified send function so that it could read in packets. Unfortunately, I was wrong and eventually realized that only a simple send command was necessary. The packet generator is split into two parts, a host and a client:

Host: This host will first be called with the port number and the choice between TCP or UDP packets to send out. (Host <port number> <TCP/UDP>). It will wait for a connection. When it receives a connection, it will spawn a thread and the thread will send a defined set of bits to the client.

Client: The client file will be called with an IP address, port number, and choice between TCP or UDP packets (Client <IP> <port> <TCP/UDP>). It will first establish a connection with the router (depending on TCP or UDP) and then prepare to receive packets. The first packet received will be marked with a time. The client should know how much is being sent over so that the last packet received will also be marked with a time. It will then calculate how many bits it has received and the time passed to calculate speed.


Note: This post will be edited upon completion. At this moment, the calculation of the speed is not working correctly and the way the host and the client interact may need to be changed. Also, as much as I researched the libpcap library, it is not being utilized yet. I plan on perhaps saving all traces to a file. Otherwise, I plan on sending an endless stream of packets from the host to the client to get a constant reading on speed from the interfaces.