Skip to content
Adam edited this page Jan 14, 2013 · 5 revisions

Table of Contents

SCONE Walkthrough

What is SCONE?

The router SCONE ( S oftware Component Of NetFPGA) is a user level router that performs IPv4 forwarding, handles ARPs and various ICMP messages, has telnet (port 23) and web (port 8080) interfaces to handle router control, and also implements a subset of OSPF named PW-OSPF. SCONE mirrors a copy of its MAC addresses, IP addresses, routing table, and ARP table to the NetFPGA card which hardware accelerates the forwarding path.

How to use SCONE?

  1. Ensure your NETFPGA is programmed with the Reference Router bitfile
  2. Check that your nf2c0, nf2c1, nf2c2, nfc3 interfaces are up and do not have an assigned IPv4 address
    • To remove an IPv4 address from an interface run 'ifconfig nf2cX 0.0.0.0' replacing X with the interface name
  1. Setup the cpuhw file
    • A text file named cpuhw must exist in the sw directory that you execute the scone binary. The format is as follows:
      • <interface name> <ip address> <ip mask> <mac address>
    • An example:
      • eth0 192.168.0.2 255.255.255.0 00:00:00:00:00:01
    • Inside SCONE the interfaces are typically named and referred to as eth0-3, which correspond to the nf2c0-3 ports.
  1. (Optional) Specify a text file containing static routes
    • A text file containing static routes to be added on startup can be specified from the command line using the '-r' parameter, ie '-r rtable.netfpga'. The format is as follows:
      • <net> <next hop> <mask> <outgoing interface name>
    • An example:
      • 192.168.130.14 192.168.130.9 255.255.255.254 eth1
  1. (Optional) Specify a file to log packets in pcap format
    • Specify a file using the '-l' command line parameter, ie '-l scone.log', all packets received by SCONE will be logged using pcap format to this file. This file can be opened and examined using Wireshark. Note packets that take the hardware forwarding path will not appear in this log file.
"SCONE's web interface"

To modify the way SCONE operates after launch, use the telnet command line interface, or the web interface. The web interface supports all the commands available from the telnet interface, and provides AJAX style capabilities to keep the data current as the router runs. To use either of these interfaces, connect to one of the IP addresses specified in the cpuhw file on port 23 for telnet, or port 8080 for http. To get a list of commands using telnet issue the ? command. A graphical version of this printout is available from the Command List link of the web interface. For help with a command enter the command and put ? for its arguments. IE 'show ip ?'. Many of the commands are documented in the Required Commands section here.

How does SCONE work with NetFPGA?

For an incoming packet to take the hardware forwarding path the packet must get a hit on the destination MAC address table, the routing table, and the ARP table for the next hop. SCONE builds and maintains the routing table containing static and dynamic routes, and the ARP table in software. When changes are detected in the software tables, SCONE copies them down into the NetFPGA's hardware tables. If you want packets to be passed up to software that match the IP addresses assigned to the interfaces you must also push these IP addresses down into a hardware table. Following are some code snippets for writing to these various tables. In general to write you first write the registers representing the data for the row, then you write the row number into the corresponding WR register. To read a row, first write the row number you want into the RD register, then read the data from the corresponding registers.

Writing MAC Addresses to the NetFPGA

uint8_t mac_addr[6];
unsigned int mac_hi = 0;
unsigned int mac_lo = 0;
mac_hi |= ((unsigned int)mac_addr[0]) << 8;
mac_hi |= ((unsigned int)mac_addr[1]);
mac_lo |= ((unsigned int)mac_addr[2]) << 24;
mac_lo |= ((unsigned int)mac_addr[3]) << 16;
mac_lo |= ((unsigned int)mac_addr[4]) << 8;
mac_lo |= ((unsigned int)mac_addr[5]);

writeReg(&netfpga, ROUTER_OP_LUT_MAC_0_HI_REG, mac_hi);
writeReg(&netfpga, ROUTER_OP_LUT_MAC_0_LO_REG, mac_lo);
// 1,2,3 can be substituted in for 0 to set the MAC for the other ports

NOTE : One confusing aspect of using a user level process to control the router is that the MAC addresses of the router will not match the kernel MAC addresses. That is, the MAC addresses of the nf2cX interfaces do not necessarily reflect those that are actually in the hardware. The nf2cX interfaces are software independent entities that do not necessarily reflect the state of the hardware. In the next section we will describe the Router Kit which reflects the Linux's view of the network to HCORR (Hardware Component of Reference Router). This includes the ports' MAC addresses, IP addresses, the routing table, and the ARP cache.

Writing interface IP Addresses to the NetFPGA

The HCORR has a table that stores IP addresses called the destination IP filter table. Packets whose destination IP address matches an entry in this table will be sent to the hardware. The number of entries in this table can be found in the Register Map. We use this table to filter out the IP addresses of the router and the IP addresses of PW-OSPF multicast packets. We write into the table as follows:

struct in_addr ip;
writeReg(&rs->netfpga, ROUTER_OP_LUT_DST_IP_FILTER_IP_REG, ntohl(ip.s_addr));
// i is the row to write the IP address to
writeReg(&rs->netfpga, ROUTER_OP_LUT_DST_IP_FILTER_WR_ADDR_REG, i);

Writing routing entries to the NetFPGA

Writing to the Routing table is similar to writing to the Destination IP filter table. Note that the output port(s) is specified in one-hot-encoded format corresponding to the output port of the User Data Path to the Tx Queues. The function getOneHotPortNumber returns the values (in decimal): 1 , 4, 16, 64 which correspond to physical output ports 0-3 on the NetFPGA card. You can also tell a route to specifically send to software by specifying 2, 8, 32, 128 corresponding to the nf2c0,1,2,3 interfaces. To send out of MAC ports 0 and 1, write 1+4=5 as the output port entry.

struct in_addr ip, mask, gw;</br>
int i;
char* iface;
/* write the ip */
writeReg(&netfpga, ROUTER_OP_LUT_RT_IP_REG, ntohl(ip.s_addr));
/* write the mask */
writeReg(&netfpga, ROUTER_OP_LUT_RT_MASK_REG, ntohl(mask.s_addr));
/* write the next hop */
writeReg(&netfpga, ROUTER_OP_LUT_RT_NEXT_HOP_IP_REG, ntohl(gw.s_addr));
/* write the port */
writeReg(&netfpga, ROUTER_OP_LUT_RT_OUTPUT_PORT_REG, getOneHotPortNumber(iface));
/* write the row number */
writeReg(&netfpga, ROUTER_OP_LUT_RT_LUT_WR_ADDR_REG, i);

Writing ARP entries to the NetFPGA

uint8_t mac_addr[6];
unsigned int mac_hi = 0;
unsigned int mac_lo = 0;
struct in_addr ip;
int i;
mac_hi |= ((unsigned int)mac_addr[0]) << 8;
mac_hi |= ((unsigned int)mac_addr[1]);
mac_lo |= ((unsigned int)mac_addr[2]) << 24;
mac_lo |= ((unsigned int)mac_addr[3]) << 16;
mac_lo |= ((unsigned int)mac_addr[4]) << 8;
mac_lo |= ((unsigned int)mac_addr[5]);
writeReg(&netfpga, ROUTER_OP_LUT_ARP_MAC_HI_REG, mac_hi);
writeReg(&netfpga, ROUTER_OP_LUT_ARP_MAC_LO_REG, mac_lo);
/* write the next hop ip data */
writeReg(&netfpga, ROUTER_OP_LUT_ARP_NEXT_HOP_IP_REG, ntohl(ip.s_addr));
/* set the row */
writeReg(&netfpga, ROUTER_OP_LUT_ARP_LUT_WR_ADDR_REG, i);

What to do From Here

Clone this wiki locally