You are here: Foswiki>NetFPGA/OneGig Web>DecacheForwarder (12 Jan 2009, Jnaous)EditAttach

Decache Forwarder

Show Contents...Hide Contents...

Port Numbering

These are notes for using the Decache forwarder:

  • The NetFPGA has 8 input/output Queues.
  • i/o queues 0,2,4,6 are connected to the Ethernet ports 0,1,2,3
  • i/o queues 1,3,5,7 are connected to the CPU interfaces nf2c0/1/2/3
  • Packets that arrive to Ethernet queue 2i and need to go to software go to queue 2i+1 and are received on nf2ci
  • Packets sent from nf2ci go out on queue 2i to the Ethernet port i.

This affects the way entries are written. Input ports are binary-encoded while outputs are specified as a bitmask .

For example, if an entry requires input queue 2 (i.e. Ethernet port 1), then the input port written should be 2. If the output is queue 4 (i.e. Ethernet port 2) then the output written should be 1<<4. The output mask thus allows multiple bits to be set to 1 to do multicast.

Masks

  • For rule masks, a 1 in a bit position specifies a don't care meaning that bit will match anything.
  • For replacement masks, a 1 bit specifies that a replacement should be done on that bit using the supplied replacement data. If a bit in the replacement mask is 0, the corresponding bit in a packet is not replaced.

Perl Code

Here is the API used in Perl:

 # bytes consists of:
 #  72 bytes rule
 #  72 bytes rule_mask
 #  72 bytes replacement data
 #  72 bytes replacement mask
 # The first 8 bytes corresponds to the IOQ module hdr
 # The rest correspond to the pkt bytes.
 sub insertEntry {
   my $idx  = shift;
   die "bytes input should be at least 72*4=288 bytes. Found ".scalar @_ if(scalar @_ != 72*4);
   die "Index should be between 0 and 31. Found $idx" unless ($idx >=0 && $idx < 32);
   print "insertEntry: to index $idx\n";
   my $cnt=0;
   foreach (@_) {
     printf("$cnt-%02x ", $_);
     $cnt++;
   }
   # write rule
   for(my $i=0; $i<9; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $i*512 + $idx*16 + main
WILDCARD_LOOKUP_BASE_REG(); NF2
PacketGen
nf_PCI_write32($addr, $word);
     printf "  Writing %08x into %08x\n", $word, $addr;
     $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
     $addr += 4;
NF2
PacketGen
nf_PCI_write32($addr, $word);
     printf "  Writing %08x into %08x\n", $word, $addr;
   }
 
   # write rule_mask
   for(my $i=0; $i<9; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $i*512 + 8 + $idx*16 + main
WILDCARD_LOOKUP_BASE_REG(); NF2
PacketGen
nf_PCI_write32($addr, $word);
     printf "  Writing %08x into %08x\n", $word, $addr;
     $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
     $addr += 4;
NF2
PacketGen
nf_PCI_write32($addr, $word);
     printf "  Writing %08x into %08x\n", $word, $addr;
   }
 
   # write data and data_mask
   for(my $i=0; $i<18*2; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $idx*512 + $i*4 + main
WILDCARD_ACTION_BASE_REG(); NF2
PacketGen
nf_PCI_write32($addr, $word);
     printf "  Writing %08x into %08x\n", $word, $addr;
   }
 
   # reset counters and timestamp
my $addr = $idx*512 + main
WILDCARD_ACTION_BASE_REG() + main
WILDCARD_LOOKUP_PKTS_HIT_SKIP(); NF2
PacketGen
nf_PCI_write32($addr, 0); NF2
PacketGen
nf_PCI_write32($addr+4, 0); NF2
PacketGen
nf_PCI_write32($addr+8, 0);
   printf "  Writing 0 into %08x\n", $addr;
   printf "  Writing 0 into %08x\n", $addr+4;
   printf "  Writing 0 into %08x\n", $addr+8;
 
   return 6*9+3;
 }
 
 sub readEntry {
   my $idx  = shift;
   die "bytes input should be at least 72*4=288 bytes. Found ".scalar @_ if(scalar @_ != 72*4);
   die "Index should be between 0 and 31. Found $idx" unless ($idx >=0 && $idx < 32);
 
   # read rule
   for(my $i=0; $i<9; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $i*512 + $idx*16 + main
WILDCARD_LOOKUP_BASE_REG(); NF2
PacketGen
nf_PCI_read32($addr, $word);
     $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
     $addr += 4;
NF2
PacketGen
nf_PCI_read32($addr, $word);
   }
 
   # read rule_mask
   for(my $i=0; $i<9; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $i*512 + 8 + $idx*16 + main
WILDCARD_LOOKUP_BASE_REG(); NF2
PacketGen
nf_PCI_read32($addr, $word);

     $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
     $addr += 4;
NF2
PacketGen
nf_PCI_read32($addr, $word);
   }
 
   # read data and data_mask
   for(my $i=0; $i<18*2; $i++) {
     my $word = (shift() << 24) + (shift() << 16) + (shift() << 8) + shift();
my $addr = $idx*512 + $i*4 + main
WILDCARD_ACTION_BASE_REG(); NF2
PacketGen
nf_PCI_read32($addr, $word);
   }
 
   return 6*9+3;
 }
 
 sub readCounters {
   my $idx = shift;
   my $pkt_count = shift;
   my $byte_count = shift;
 
my $addr = $idx*512 + main
WILDCARD_ACTION_BASE_REG() + main
WILDCARD_LOOKUP_PKTS_HIT_SKIP(); NF2
PacketGen
nf_PCI_read32($addr, $pkt_count); NF2
PacketGen
nf_PCI_read32($addr+4, $byte_count);
 }

Here is an example of how it is used:

my $pkt = NFUtils
SimplePacket->new(NFUtils
SimplePacket
PKT_TYPE() => NFUtils
SimplePacket
PKT_TYPE_UDP());

 my @pkt_bytes = $pkt->bytes();
 
 my $input_queue = 2;
 my $output_queue = 4;
 
 my @rule = @pkt_bytes[0..63];
 my @rule_mask = (0xff) x 64;
 my @pkt_replacement = (1..64);
 my @replacement_mask = ((0xff) x 32, (0x00) x 16, (0xff) x 16);
 my $idx = 2;
 
 my $entry = [$idx,
 	     # rule
 	     0, 0, 0, 0, 0, $input_queue, 0, 0, # IOQ hdr
 	     @rule,
 	     # rule mask
 	     0xff, 0xff, 0xff, 0xff, 0, 0, 0xff, 0xff, # IOQ hdr
 	     @rule_mask,
 	     # replacement
 	     0, (1 << $output_queue), 0, 0, 0, 0, 0, 0, # IOQ hdr
 	     @pkt_replacement,
 	     # replacement mask
 	     0xff, 0xff, 0, 0, 0, 0, 0, 0, # IOQ hdr
 	     @replacement_mask,
 	    ];
 
DecacheLib
insertEntry(@{$entry});

 my $input_port = ($input_queue/2) + 1;
 my $output_port = ($output_queue/2) + 1;
 
 # transform pkt
 my @exp_bytes = ();
 my $i;
 for($i=0; $isize()-1];

LiveCD

If you want to get on with stuff quickly, got to LiveCD, burn a copy and boot from it. It should have all the utilities you need.

Files

You can download a tarball from here This tarball has:

  • bitfile
  • DecacheLib.pm with functions used for simulation
  • make_pkts.pl that uses DecacheLib.pm
  • .h files for C development
  • .ph files for Perl development
Topic revision: r1 - 12 Jan 2009 - 02:54:45 - Jnaous