@@ -28,6 +28,11 @@ void ebbrt::IxgbeDriver::Create(pci::Device& dev) {
2828  ixgbe_dev->ebb_  =
2929      IxgbeDriverRep::Create (ixgbe_dev, ebb_allocator->AllocateLocal ());
3030
31+   //  only even core numbers
32+   if (static_cast <int >(Cpu::Count ()) > 1 ) {
33+     kassert (static_cast <int >(Cpu::Count ()) % 2  == 0 );
34+   }
35+ 
3136  //  initialize per core rx and tx queues
3237  for  (size_t  i = 0 ; i < Cpu::Count (); i++) {
3338    ixgbe_dev->SetupMultiQueue (i);
@@ -44,7 +49,47 @@ const ebbrt::EthernetAddress& ebbrt::IxgbeDriver::GetMacAddress() {
4449  return  mac_addr_;
4550}
4651
52+ void  ebbrt::IxgbeDriver::DumpStats () {
53+   for  (size_t  i = 0 ; i < Cpu::Count (); i++) {
54+     ebbrt::kprintf (" Core %d STATS:\n " int )i);
55+     ebbrt::kprintf (" \t  num_recv_itrs:%lld\n " stat_num_itr );
56+     ebbrt::kprintf (" \t  num_send:%lld\n " stat_num_send );
57+     ebbrt::kprintf (" \t  num_rx_desc_proc:%lld\n " stat_num_rx );
58+     ebbrt::kprintf (" \t  num_tx_desc_proc:%lld\n " stat_num_tx );
59+ 
60+     //  reset to 0
61+     ixgmq[i]->stat_num_itr  = 0 ;
62+     ixgmq[i]->stat_num_send  = 0 ;
63+     ixgmq[i]->stat_num_rx  = 0 ;
64+     ixgmq[i]->stat_num_tx  = 0 ;
65+ 
66+     if (ixgmq[i]->stat_perf  == false ) {
67+       ixgmq[i]->perfCycles  = ebbrt::perf::PerfCounter (ebbrt::perf::PerfEvent::cycles);
68+       ixgmq[i]->perfCycles .Start ();
69+       ixgmq[i]->perfInst  = ebbrt::perf::PerfCounter (ebbrt::perf::PerfEvent::instructions);
70+       ixgmq[i]->perfInst .Start ();
71+       ixgmq[i]->stat_perf  =true ;
72+     } else  {
73+       ixgmq[i]->perfCycles .Stop ();
74+       ixgmq[i]->perfInst .Stop ();
75+       double  cyc = static_cast <double >(ixgmq[i]->perfCycles .Read ());
76+       double  inst = static_cast <double >(ixgmq[i]->perfInst .Read ());
77+ 
78+       ebbrt::kprintf (" Core %d PMC:\n " int )i);
79+       ebbrt::kprintf (" \t  cycles:%llf \n " 
80+       ebbrt::kprintf (" \t  instructions:%llf\n " 
81+       ebbrt::kprintf (" \t  ipc: %llf\n " 
82+       ixgmq[i]->stat_perf  = false ;
83+     }
84+   }
85+ }
86+ 
4787void  ebbrt::IxgbeDriver::Send (std::unique_ptr<IOBuf> buf, PacketInfo pinfo) {
88+ #ifdef  STATS_EN
89+   if (pinfo.get_stats ) {
90+     DumpStats ();
91+   }
92+ #endif 
4893  ebb_->Send (std::move (buf), std::move (pinfo));
4994}
5095
@@ -175,14 +220,21 @@ void ebbrt::IxgbeDriverRep::AddTx(uint64_t pa, uint64_t len,
175220
176221  ixgmq_.tx_last_tail_  = ixgmq_.tx_tail_ ;
177222  ixgmq_.tx_tail_  = (tail + 1 ) % ixgmq_.tx_size_ ;
223+ #ifdef  STATS_EN
224+   ixgmq_.stat_num_tx  ++;
225+ #endif 
178226}
179227
180228void  ebbrt::IxgbeDriverRep::Send (std::unique_ptr<IOBuf> buf, PacketInfo pinfo) {
181229  bool  ip_cksum = false ;
182230  bool  tcpudp_cksum = false ;
183231  uint64_t  data;
184232  size_t  len, count;
185-   int  mcore = (int )Cpu::GetMine ();
233+   uint32_t  mcore = static_cast <uint32_t >(Cpu::GetMine ());
234+ 
235+ #ifdef  STATS_EN
236+   ixgmq_.stat_num_send  ++;
237+ #endif 
186238
187239//  TODO threshold for triggering reclaim tx buffers
188240#ifndef  TX_HEAD_WB
@@ -765,6 +817,7 @@ void ebbrt::IxgbeDriver::WritePsrtypeZero(uint32_t n) {
765817//  4*n, n=0...31; RW)
766818void  ebbrt::IxgbeDriver::WriteReta (uint32_t  n, uint32_t  m) {
767819  bar0_.Write32 (0x0EB00  + 4  * n, m);
820+   ebbrt::kprintf (" WriteReta(n=%d) = 0x%08X\n " 
768821}
769822
770823//  8.2.3.7.6 Receive Filter Control Register — RFCTL (0x05008; RW)
@@ -1276,6 +1329,7 @@ void ebbrt::IxgbeDriver::GlobalReset() {
12761329 **/  
12771330void  ebbrt::IxgbeDriver::Init () {
12781331  uint64_t  d_mac;
1332+   uint32_t  ncore = static_cast <uint32_t >(Cpu::Count ());
12791333
12801334  ebbrt::kprintf (" %s " 
12811335  bar0_.Map ();  //  allocate virtual memory
@@ -1419,6 +1473,10 @@ void ebbrt::IxgbeDriver::Init() {
14191473
14201474#ifndef  RSC_EN
14211475  WriteRxcsum (0x1  << 12 );  //  IP payload checksum enable
1476+ #else 
1477+   //  note: PCSD: The Fragment Checksum and IP Identification fields are mutually exclusive with
1478+   //  the RSS hash. Only one of the two options is reported in the Rx descriptor.
1479+   WriteRxcsum (0x2000 );
14221480#endif 
14231481//  TODO RQTC
14241482
@@ -1432,10 +1490,48 @@ void ebbrt::IxgbeDriver::Init() {
14321490    WriteMpsar (i, 0x0 );
14331491  }
14341492
1435-   //  TODO RSSRK
1436- 
1437-   for  (auto  i = 0 ; i < 32 ; i++) {
1438-     WriteReta (i, 0x0 );
1493+   //  RSSRK - random seeds taken from Linux
1494+   WriteRssrk (0 , 0xA38DD80F );
1495+   WriteRssrk (1 , 0xD107C3DC );
1496+   WriteRssrk (2 , 0x8CEB19C4 );
1497+   WriteRssrk (3 , 0xA41E1B6B );
1498+   WriteRssrk (4 , 0xB7218638 );
1499+   WriteRssrk (5 , 0x6B8B6155 );
1500+   WriteRssrk (6 , 0xDC8D08B5 );
1501+   WriteRssrk (7 , 0xD2E8684B );
1502+   WriteRssrk (8 , 0xECEF8417 );
1503+   WriteRssrk (9 , 0xE56C84D5 );
1504+ 
1505+   //  Fill in RSS redirection table (128 entries), sets which core the lowest 7 bits of hashed output goes to
1506+   //  hacky atm
1507+   for  (auto  i = 0 ; i < 32 ; i += 4 ) {
1508+     //  all route to core 0
1509+     if (ncore == 1 ) {
1510+       WriteReta (i, 0x0000000 );
1511+       WriteReta (i+1 , 0x0000000 );
1512+       WriteReta (i+2 , 0x0000000 );
1513+       WriteReta (i+3 , 0x0000000 );
1514+     } else  if (ncore == 2 ) {
1515+       WriteReta (i, 0x1010100 );
1516+       WriteReta (i+1 , 0x1010100 );
1517+       WriteReta (i+2 , 0x1010100 );
1518+       WriteReta (i+3 , 0x1010100 );
1519+     } else  if (ncore == 4 ) {
1520+       WriteReta (i, 0x3020100 );
1521+       WriteReta (i+1 , 0x3020100 );
1522+       WriteReta (i+2 , 0x3020100 );
1523+       WriteReta (i+3 , 0x3020100 );
1524+     } else  if (ncore == 8 ) {
1525+       WriteReta (i, 0x3020100 );
1526+       WriteReta (i+1 , 0x7060504 );
1527+       WriteReta (i+2 , 0x3020100 );
1528+       WriteReta (i+3 , 0x7060504 );
1529+     } else  {
1530+       WriteReta (i, 0x3020100 );
1531+       WriteReta (i+1 , 0x7060504 );
1532+       WriteReta (i+2 , 0xB0A0908 );
1533+       WriteReta (i+3 , 0xF0E0D0C );
1534+     }
14391535  }
14401536
14411537  for  (auto  i = 0 ; i < 128 ; i++) {
@@ -1486,7 +1582,8 @@ void ebbrt::IxgbeDriver::Init() {
14861582  for  (auto  i = 1 ; i < 8 ; i++) {
14871583    WriteRxpbsize (i, 0x0 );
14881584  }
1489-   WriteMrqc (0x0 );
1585+   WriteMrqc (0x330001 );
1586+ 
14901587  WritePfqde (0x0 );
14911588  WriteRtrup2tc (0x0 );
14921589  WriteMflcn (0x0  << 2 );
@@ -1570,6 +1667,8 @@ void ebbrt::IxgbeDriver::SetupMultiQueue(uint32_t i) {
15701667  WritePsrtype (i, 0x1  << 4 );  //  Split received TCP packets after TCP header.
15711668#endif 
15721669
1670+   //  In NON-IOV, only psrtype[0] is used
1671+   WritePsrtype (0 , 0x40001330 );
15731672  //  Set head and tail pointers
15741673  WriteRdt_1 (i, 0x0 );
15751674  WriteRdh_1 (i, 0x0 );
@@ -1583,6 +1682,8 @@ void ebbrt::IxgbeDriver::SetupMultiQueue(uint32_t i) {
15831682  //  setup RX interrupts for queue i
15841683  dev_.SetMsixEntry (i, rcv_vector, ebbrt::Cpu::GetByIndex (i)->apic_id ());
15851684
1685+   ebbrt::kprintf (" Core %d: BSIZEPACKET=%d bytes NTXDESCS=%d NRXDESCS=%d ITR_INTERVAL=%dus RCV_VECTOR=%d APIC_ID=%d \n " int ) (IxgbeDriver::ITR_INTERVAL * 2 ), (int )rcv_vector, (int )(ebbrt::Cpu::GetByIndex (i)->apic_id ()));
1686+ 
15861687  //  don't set up interrupts for tx since we have head writeback??
15871688  auto  qn = i / 2 ;  //  put into correct IVAR
15881689
@@ -1597,7 +1698,7 @@ void ebbrt::IxgbeDriver::SetupMultiQueue(uint32_t i) {
15971698
15981699  //  must be greater than rsc delay
15991700  //  WriteEitr(i, 0x80 << 3); // 7 * 2us = 14 us
1600-   WriteEitr (i, (IxgbeDriver::ITR_INTERVAL << 3 ));
1701+   WriteEitr (i, (IxgbeDriver::ITR_INTERVAL << 3 ) | IXGBE_EITR_CNT_WDIS );
16011702
16021703  //  7.3.1.4 - Note that there are no EIAC(1)...EIAC(2) registers.
16031704  //  The hardware setting for interrupts 16...63 is always auto clear.
@@ -1880,7 +1981,9 @@ uint32_t ebbrt::IxgbeDriverRep::GetRxBuf(uint32_t* len, uint64_t* bAddr,
18801981
18811982    //  bump head ptr
18821983    ixgmq_.rx_head_  = (ixgmq_.rx_head_  + 1 ) % ixgmq_.rx_size_ ;
1883- 
1984+ #ifdef  STATS_EN
1985+     ixgmq_.stat_num_rx  ++;
1986+ #endif 
18841987    return  0 ;
18851988  }
18861989#endif 
@@ -1896,7 +1999,9 @@ void ebbrt::IxgbeDriverRep::ReceivePoll() {
18961999  uint32_t  count;
18972000  uint32_t  rnt;
18982001  process_rsc = false ;
1899- 
2002+ #ifdef  STATS_EN
2003+   ixgmq_.stat_num_itr  ++;
2004+ #endif 
19002005  rxflag = 0 ;
19012006  count = 0 ;
19022007  rnt = 0 ;
0 commit comments