// This procedure calculates the checksum of a given byte stream // It returns the result in big endianess format // It doenst compute the 1's complement static public void calc_UDP_checksum(ulong data) { ulong tmp0 = 0x00, tmp1 = 0x00, tmp2 = 0x00, tmp3 = 0x00, sum0 = 0, sum1 = 0, sum = 0, chk = 0; chk = chksum_UDP; // The ICMP header & payload start from this packet number if (true) { // extract every 16-bit from the stream for addition and reorder it to big endianess tmp0 = ((ulong)(data >> 0) & (ulong)0x00ff) << 8 | ((ulong)(data >> 0) & (ulong)0x00ff00) >> 8; tmp1 = ((ulong)(data >> 16) & (ulong)0x00ff) << 8 | ((ulong)(data >> 16) & (ulong)0x00ff00) >> 8; tmp2 = ((ulong)(data >> 32) & (ulong)0x00ff) << 8 | ((ulong)(data >> 32) & (ulong)0x00ff00) >> 8; tmp3 = ((ulong)(data >> 48) & (ulong)0x00ff) << 8 | ((ulong)(data >> 48) & (ulong)0x00ff00) >> 8; // check for carry and add it if its needed sum0 = (ulong)((tmp0 + tmp1) & (ulong)0x00ffff) + (ulong)((tmp0 + tmp1) >> 16); sum1 = (ulong)((tmp2 + tmp3) & (ulong)0x00ffff) + (ulong)((tmp2 + tmp3) >> 16); Kiwi.Pause(); // check for carry and add it if its needed sum = (ulong)((sum0 + sum1) & (ulong)0x00ffff) + (ulong)((sum0 + sum1) >> 16); // add the current sum to the previous sums chksum_UDP = (ulong)((sum + chk) & (ulong)0x00ffff) + (ulong)((sum + chk) >> 16); } }
// This method describes the operations required to tx a frame over the AXI4-Stream. static void SendFrame(uint pkt_size) { // ############################# // # Transmit the frame // ############################# m_axis_tvalid = true; m_axis_tlast = false; m_axis_tdata = (ulong)tdata[0]; m_axis_tkeep = (byte)tkeep[0]; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)tuser_low[0]; uint i = 1U; Kiwi.Pause(); while (i <= pkt_size) { if (m_axis_tready) { m_axis_tdata = tdata[i]; m_axis_tkeep = (i == pkt_size) ? tkeep[pkt_size] : (byte)0xff; m_axis_tlast = i == pkt_size; m_axis_tuser_hi = 0UL; m_axis_tuser_low = 0UL; i++; } Kiwi.Pause(); } m_axis_tvalid = false; m_axis_tlast = false; m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; Kiwi.Pause(); }
/* * Function: SendOne * Description: Send a single segment of the buffered ethernet frame. */ public static uint SendOne(CircularFrameBuffer cfb, bool stop = true, bool movepeek = false, bool checkready = true) { if (cfb.CanPop(movepeek) && (!checkready || Emu.m_axis_tready)) { Emu.Status = 11; SetData(cfb, movepeek, true); var done = cfb.PopData.Tlast; Emu.Status = 3; Kiwi.Pause(); if (stop) { Reset(); } if (done) { Emu.PktOut++; Emu.Status = 12; return(2U); } Emu.Status = 13; return(0U); } Emu.Status = 14; if (stop) { Reset(); } return(3U); }
// This method describes the operations required to route the frames static public void switch_logic() { metadata = 0UL; src_mac = 0UL; dst_mac = 0UL; LUT_hit = false; while (true) { ReceiveFrameSegm(); // ############################# // # Switch Logic -- START // ############################# broadcast_ports = ((metadata & (ulong)0x00FF0000) ^ DEFAULT_oqs) << (byte)8; CAM_check_n_learn(dst_mac, src_mac << 16); Kiwi.Pause(); tuser_low = LUT_hit ? (ulong)(OQ << 24 | metadata) : (ulong)(broadcast_ports | metadata); //############################# // # Switch Logic -- END // ############################# // Send out this frame and the rest SendFrame(); // End of frame, ready for next frame LUT_hit = false; metadata = 0UL; src_mac = 0UL; dst_mac = 0UL; LUT_hit = false; OQ = 0UL; } }
// This method describes the operations required to tx a frame over the AXI4-Stream. static void SendFrame(uint psize) { // ############################# // # Transmit the frame // ############################# m_axis_tvalid = true; m_axis_tlast = false; m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; uint i = 0U; while (i <= psize) { if (m_axis_tready) { m_axis_tdata = tdata[i]; m_axis_tkeep = tkeep[i]; m_axis_tlast = i == (psize); m_axis_tuser_hi = tuser_hi[i]; m_axis_tuser_low = tuser_low[i]; i = i + 1U; } Kiwi.Pause(); } m_axis_tvalid = false; m_axis_tlast = false; m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; Kiwi.Pause(); }
// This method describes the operations required to tx a frame over the AXI4-Stream. protected static void SendFrame(uint fm_size) { m_axis_tvalid = true; m_axis_tlast = false; m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; uint i = 0; while (i <= fm_size) { if (m_axis_tready) { m_axis_tdata = dataplane.tdata[i]; m_axis_tkeep = dataplane.tkeep[i]; // -- BUG DONT USE //m_axis_tlast = (i==fm_size) ? true : false; //if (i==fm_size) m_axis_tlast = true; m_axis_tlast = i == (fm_size); m_axis_tuser_hi = dataplane.tuser_hi[i]; m_axis_tuser_low = dataplane.tuser_low[i]; i++; } Kiwi.Pause(); } m_axis_tvalid = false; m_axis_tlast = false; m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; Kiwi.Pause(); }
// This method describes the operations required to rx a frame over the AXI4-Stream. // and extract basic information such as dst_MAC, src_MAC, dst_port, src_port public void ReceiveFrame() { s_axis_tready = true; // The start condition uint cnt = 0U; bool doneReading = true; // ############################# // # Receive the frame // ############################# //Kiwi.Pause(); while (doneReading) { if (s_axis_tvalid) { packet_size = (uint)(s_axis_tuser_low & (ulong)0x00ffff); new_pkt_arrived = cnt == 0U; // Condition to stop receiving data doneReading = !s_axis_tlast && s_axis_tvalid; cnt = s_axis_tlast ? 0 : cnt + 1U; // Create backpresure to whatever sends data to us //s_axis_tready = s_axis_tlast ? false : true; } else { new_pkt_arrived = false; } Kiwi.Pause(); } new_pkt_arrived = false; //s_axis_tready = false; }
public bool recvOne(bool check_updated = true) { if ((!check_updated || !s_updated) && Emu.axi_s_axis_tvalid) { s_updated = true; Emu.axi_s_axis_tready = true; axi_s_axis_tdata_0 = Emu.axi_s_axis_tdata_0; axi_s_axis_tdata_1 = Emu.axi_s_axis_tdata_1; axi_s_axis_tdata_2 = Emu.axi_s_axis_tdata_2; axi_s_axis_tdata_3 = Emu.axi_s_axis_tdata_3; axi_s_axis_tstrb = Emu.axi_s_axis_tstrb; axi_s_axis_tkeep = Emu.axi_s_axis_tkeep; axi_s_axis_tlast = Emu.axi_s_axis_tlast; axi_s_axis_tid = Emu.axi_s_axis_tid; axi_s_axis_tdest = Emu.axi_s_axis_tdest; axi_s_axis_tuser_0 = Emu.axi_s_axis_tuser_0; axi_s_axis_tuser_1 = Emu.axi_s_axis_tuser_1; Kiwi.Pause(); Emu.axi_s_axis_tready = false; return(true); } return(false); }
static void Main() { HashCAM.Read(10); HashCAM.Read(10); HashCAM.Write(10, 7); HashCAM.Read(10); HashCAM.Write(10, 7); HashCAM.Read(10); HashCAM.Write(10, 7); HashCAM.Read(10); HashCAM.Write(10, 8); HashCAM.Read(10); HashCAM.Write(10, 7); HashCAM.Read(11); HashCAM.Write(12, 9); for (int i = 0; i < 300; i++) { HashCAM.Write((ulong)i, 1); Kiwi.Pause(); } }
// This procedure perform swap of multiple fields // dst_mac<->src_mac, dst_ip<->src_ip, dst_port<->src_port static void swap_multiple_fields(bool tcp_udp, bool icmp) { ulong tmp; bool tcp_udp_tmp, icmp_tmp; tcp_udp_tmp = tcp_udp; icmp_tmp = icmp; // Ethernet header swap tdata[0] = src_mac | (dst_mac << 48); Kiwi.Pause(); tmp = (tdata[1] & (ulong)0xffffffff00000000) | dst_mac >> 16; Kiwi.Pause(); tdata[1] = tmp; Kiwi.Pause(); // IP header swap + UDP header swap tmp = (tdata[3] & (ulong)0x00ffff) | dst_ip << 16 | src_ip << 48; // tmp = dst_ip<<16 | src_ip<<48; Kiwi.Pause(); tdata[3] = tmp; Kiwi.Pause(); if (tcp_udp_tmp) { // Swap the ports, Memcached - TCP ping tmp = (tdata[4] & (ulong)0xffff000000000000) | src_ip >> 16 | app_src_port << 32 | app_dst_port << 16; } else if (icmp_tmp) { // Set the ICMP echo reply type=0, code=0 and checksum=0x00 tmp = (tdata[4] & (ulong)0xffff000000000000) | src_ip >> 16; } Kiwi.Pause(); tdata[4] = tmp; Kiwi.Pause(); }
public static ulong Write(ulong key_in, ulong value_in) { ulong result = 0; while (write_ready) { Kiwi.Pause(); } HashCAM.key_in = key_in; HashCAM.value_in = value_in; write_enable = true; Kiwi.Pause(); while (!write_ready) { Kiwi.Pause(); } Kiwi.Pause(); matched = match; result = value_out; is_full = full; write_enable = false; Kiwi.Pause(); return(result); }
static int EntryPoint() { // Create and start the thread for receiving and parsing the tuple RX rx = new RX(); Thread rxTh = new Thread(new ThreadStart(rx.start_rx)); rxTh.Start(); TIMER timer = new TIMER(); Thread timerTh = new Thread(new ThreadStart(timer.start_timer)); timerTh.Start(); TABLES tables = new TABLES(); tables.reset_tables(); Thread bw_tmpTh = new Thread(new ThreadStart(tables.update_bw_tmp)); bw_tmpTh.Start(); Thread tablesTh = new Thread(new ThreadStart(tables.update_tables)); tablesTh.Start(); while (true) { if (rst | clear) { timer.reset_timer(); tables.reset_raw_entry(); tables.reset_bw_tmp(); tables.reset_total_entries(); } Kiwi.Pause(); } return(0); }
// This procedure perform basic control operation for the CAM static uint cam_controller(byte mode) { uint tmp_addr = 0x00; // Poll until CAM is ready while (cam_busy) { Kiwi.Pause(); } //addr = mem_controller_cnt; //tmp_key = key; //if(mem_controller_cnt == (uint)(MEM_SIZE-1U)) mem_controller_cnt = 0; switch (mode) { // WRITE operation - returns the address in which the key is stored case SET: // 0x01 // Check if the key exists in the CAM cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); // Perform the store operation cam_din = key; cam_wr_addr = (cam_match) ? (byte)cam_match_addr : (byte)mem_controller_cnt; tmp_addr = (cam_match) ? (byte)cam_match_addr : (byte)mem_controller_cnt; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); break; // READ operation - return the address if we have a match otherwhise MEM_SIZE case GET: // 0x00 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); tmp_addr = (cam_match) ? (uint)cam_match_addr : (uint)MEM_SIZE; break; // DELETE operation - return the address if we have a match otherwhise MEM_SIZE case DELETE: // 0x04 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); if (cam_match) { tmp_addr = (uint)cam_match_addr; } else { tmp_addr = (uint)MEM_SIZE; } Kiwi.Pause(); if (cam_match) { Kiwi.Pause(); cam_din = (ulong)0x00; cam_wr_addr = (byte)tmp_addr; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); } break; default: break; } if (mem_controller_cnt == (uint)(MEM_SIZE - 1U)) { mem_controller_cnt = 0; } else { mem_controller_cnt += 1U; } return(tmp_addr); }
// This procedure creates the DELETE response packet static public uint Memcached_DELETE(bool err) { ulong tmp = 0x00, tmp2 = 0x00; // DELETE - Fixed size of key(6B) if (!err) { tmp = ((ulong)(ulong)((IP_total_length >> 8) | (IP_total_length << 8 & (ulong)0x00ff00)) - (ulong)6) & (ulong)0x00ffff; } else // add length of textual error code (8B) { tmp = ((ulong)(ulong)((IP_total_length >> 8) | (IP_total_length << 8 & (ulong)0x00ff00)) + (ulong)2) & (ulong)0x00ffff; } tmp2 = tdata[2] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[2] = tmp2 | (tmp >> 8) | (tmp << 8 & (ulong)0x00ff00); Kiwi.Pause(); // Set the checksum to 0x00, calculate later tmp = tdata[3] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[3] = tmp; // DELETE - Fixed size of key(6B) if (!err) { tmp = ((ulong)(ulong)((UDP_total_length >> 8) | (UDP_total_length << 8 & (ulong)0x00ff00)) - (ulong)6); } else { tmp = ((ulong)(ulong)((UDP_total_length >> 8) | (UDP_total_length << 8 & (ulong)0x00ff00)) + (ulong)2); } tmp2 = tdata[4] & (ulong)0x0000ffffffffffff; Kiwi.Pause(); tdata[4] = tmp2 | ((tmp & (ulong)0xff00) << 40) | (tmp << 56); Kiwi.Pause(); // Reset the UDP checksum tmp = tdata[5]; Kiwi.Pause(); tdata[5] = tmp & ~(ulong)0x00ffff; Kiwi.Pause(); tmp = tdata[6] & (ulong)0x00ffff; Kiwi.Pause(); //set DELETE magic number + opcode tdata[6] = (ulong)DELETE << 24 | (ulong)RESPONSE << 16 | tmp; Kiwi.Pause(); // Set the status code = key not found IPv4 // and the opaque - DELETE response if (err) { tmp = (tdata[7] & 0xffff000000000000) | (ulong)0x0000080000000100; } else { tmp = (tdata[7] & 0xffff000000000000); } Kiwi.Pause(); tdata[7] = tmp; Kiwi.Pause(); // Fill up the rest of the response packet if (!err) { tmp = tdata[8] & 0x000000000000ffff; Kiwi.Pause(); tdata[8] = tmp; Kiwi.Pause(); tdata[9] = (ulong)0x00; // Set the correct metadata for the datapath // Fixed size response packet for DELETE success tuser_low[0] = (src_port << 24) | (src_port << 16) | (ulong)74; tkeep[9] = (byte)0x03; //pkt_size = 8; return(9U); } else { tmp = (tdata[8] & 0x000000000000ffff); Kiwi.Pause(); tdata[8] = tmp; Kiwi.Pause(); tdata[9] = ERROR_MSG << 16; Kiwi.Pause(); tdata[10] = ERROR_MSG >> 48; // Set the correct metadata for the datapath // Fixed size response packet for DELETE failure tuser_low[0] = (src_port << 24) | (src_port << 16) | (ulong)82; tkeep[10] = (byte)0x03; //pkt_size = 9; return(10U); } }
// This procedure creates the GET response packet static public uint Memcached_GET(bool err) { ulong tmp = 0x00, tmp2 = 0x00; // Set the correct IP packet length (little endianess) // GET - Fixed size of extras(4B)[only flag] + key(6B) + value(8B) if (!err) { tmp = ((ulong)(ulong)((IP_total_length >> 8) | (IP_total_length << 8 & (ulong)0x00ff00)) + (ulong)6) & (ulong)0x00ffff; } else { // in case of an error we must adjust the length accordinlgy // add length of textual error code (8B) tmp = ((ulong)(ulong)((IP_total_length >> 8) | (IP_total_length << 8 & (ulong)0x00ff00)) + (ulong)2) & (ulong)0x00ffff; } tmp2 = tdata[2] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[2] = tmp2 | (tmp >> 8) | (tmp << 8 & (ulong)0x00ff00); Kiwi.Pause(); // Set the checksum to 0x00, calculate later tmp = tdata[3] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[3] = tmp; // Set the correct UDP packet length (little endianess) // GET - Fixed size of extras(4B)[only flag] + key(6B) + value(8B) // in case of an error we must adjust the length accordinlgy if (!err) { tmp = ((ulong)(ulong)((UDP_total_length >> 8) | (UDP_total_length << 8 & (ulong)0x00ff00)) + (ulong)6); } else { tmp = ((ulong)(ulong)((UDP_total_length >> 8) | (UDP_total_length << 8 & (ulong)0x00ff00)) + (ulong)2); } tmp2 = tdata[4] & (ulong)0x0000ffffffffffff; Kiwi.Pause(); tdata[4] = tmp2 | ((tmp & (ulong)0xff00) << 40) | (tmp << 56); Kiwi.Pause(); // Reset the UDP checksum tmp = tdata[5]; Kiwi.Pause(); tdata[5] = tmp & ~(ulong)0x00ffff; Kiwi.Pause(); tmp = tdata[6] & (ulong)0x00ffff; Kiwi.Pause(); // set GET magic number + opcode // set also the extras length(4b) if (!err) { tdata[6] = ((ulong)GET << 24 | (ulong)RESPONSE << 16 | ((ulong)0x0004) << 48) | tmp; } else { tdata[6] = ((ulong)GET << 24 | (ulong)RESPONSE << 16) | tmp; } Kiwi.Pause(); // Set the opaque // Set the status code = key not found // and the opaque - GET response if (err) { // total length is fixed (error msg(8B) = 0x14) tmp = (tdata[7] & 0xffff000000000000) | (ulong)0x0000080000000100; } else // total length is fixed (flag(4B)+key_value(8B)= 0x0c) { tmp = (tdata[7] & 0xffff000000000000) | (ulong)0x00000c0000000000; } Kiwi.Pause(); tdata[7] = tmp; Kiwi.Pause(); // Fill up the rest of the response packet if (err) { tmp = (tdata[8] & 0x000000000000ffff); Kiwi.Pause(); tdata[8] = tmp; Kiwi.Pause(); tdata[9] = ERROR_MSG << 16; Kiwi.Pause(); tdata[10] = ERROR_MSG >> 48; // Set the correct metadata for the datapath // Fixed size response packet for GET/DELETE failure tuser_low[0] = (src_port << 24) | (src_port << 16) | (ulong)82; tkeep[10] = (byte)0x03; //pkt_size = 9; } else { tdata[9] = (((ulong)flag >> 16) & (ulong)0x00ffffffff0000) | (ulong)key_value << 48; Kiwi.Pause(); tdata[10] = (ulong)key_value >> 16; //&(ulong)0x00ffffffffffff; tuser_low[0] = (src_port << 24) | (src_port << 16) | (ulong)86; tkeep[10] = (byte)0x3f; //pkt_size = 9; } return(10U); }
// This method describes the operations required to rx a frame over the AXI4-Stream. // and extract basic information such as dst_MAC, src_MAC, dst_port, src_port static public uint ReceiveFrame() { m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tlast = false; m_axis_tvalid = false; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; s_axis_tready = true; segm_num = 0U; icmp_header = false; //num = (uint)0x01; Kiwi.Pause(); // The start condition uint cnt = 0; uint psize = 0; bool start = s_axis_tvalid && s_axis_tready; bool doneReading = true; bool receive = s_axis_tvalid; ulong data = 0x00; byte data2 = 0x00; // ############################# // # Receive the frame // ############################# cnt = 0; doneReading = true; while (doneReading) { if (s_axis_tvalid) { //Extract_data(segm_num++) <-- BUG //Extract_data(cnt+1); //Extract_data(); // shared_tdata = s_axis_tdata; // shared_tuser = s_axis_tuser_low; // // if(cnt==4U) calc_UDP_checksum(s_axis_tdata >> 16); // if(cnt>4U) calc_UDP_checksum(s_axis_tdata); tdata[cnt] = s_axis_tdata; tkeep[cnt] = s_axis_tkeep; tlast[cnt] = s_axis_tlast; tuser_hi[cnt] = s_axis_tuser_hi; tuser_low[cnt] = s_axis_tuser_low; segm_num += 1U; psize = cnt++; doneReading = !s_axis_tlast && s_axis_tvalid; // Create backpresure to whatever sends data to us s_axis_tready = s_axis_tlast ? false : true; } //else icmp_header=false; Kiwi.Pause(); } icmp_header = false; data = tdata[psize]; data2 = tkeep[psize]; Kiwi.Pause(); /* * if(data2==0x01){ tdata[psize] = data & (ulong)0x00ff; Kiwi.Pause();} * else if(data2==0x03){ tdata[psize] = data & (ulong)0x00ffff; Kiwi.Pause();} * else if(data2==0x07){ tdata[psize] = data & (ulong)0x00ffffff; Kiwi.Pause();} * else if(data2==0x0f){ tdata[psize] = data & (ulong)0x00ffffffff; Kiwi.Pause();} * else if(data2==0x1f){ tdata[psize] = data & (ulong)0x00ffffffffff; Kiwi.Pause();} * else if(data2==0x3f){ tdata[psize] = data & (ulong)0x00ffffffffffff; Kiwi.Pause();} * else if(data2==0x7f){ tdata[psize] = data & (ulong)0x00ffffffffffffff; Kiwi.Pause();} * else{;} */ switch (data2) { case 0x01: tdata[psize] = data & (ulong)0x00ff; break; case 0x03: tdata[psize] = data & (ulong)0x00ffff; break; case 0x07: tdata[psize] = data & (ulong)0x00ffffff; break; case 0x0f: tdata[psize] = data & (ulong)0x00ffffffff; break; case 0x1f: tdata[psize] = data & (ulong)0x00ffffffffff; break; case 0x3f: tdata[psize] = data & (ulong)0x00ffffffffffff; break; case 0x7f: tdata[psize] = data & (ulong)0x00ffffffffffffff; break; default: break; } Kiwi.Pause(); s_axis_tready = false; cnt = 0; segm_num = 0; //last = false; //start = false; return(psize); }
// This method describes the operations required to route the frames static public void switch_logic() { uint i = 0U, ptr = 0U, free = 0U, cnt = 0U; uint pkt_size = 0U; bool exist = false, doneReading; IP = false; metadata = 0UL; src_mac = 0UL; dst_mac = 0UL; LUT_hit = false; while (true) // Process packets indefinately { // Procedure call for receiving the first frame of the packet m_axis_tdata_0 = (ulong)0x0; m_axis_tdata_1 = (ulong)0x0; m_axis_tdata_2 = (ulong)0x0; m_axis_tdata_3 = (ulong)0x0; m_axis_tkeep = (uint)0x0; m_axis_tlast = false; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; s_axis_tready = true; cnt = 0U; Kiwi.Pause(); doneReading = true; while (doneReading) { if (s_axis_tvalid) { tdata_0[cnt] = s_axis_tdata_0; tdata_1[cnt] = s_axis_tdata_1; tdata_2[cnt] = s_axis_tdata_2; tdata_3[cnt] = s_axis_tdata_3; tkeep[cnt] = s_axis_tkeep; tlast[cnt] = s_axis_tlast; tuser_hi[cnt] = s_axis_tuser_hi; tuser_low[cnt] = s_axis_tuser_low; if (cnt == 0U) { metadata = s_axis_tuser_low; dst_mac = s_axis_tdata_0 << (byte)16; src_mac = ((s_axis_tdata_0 >> (byte)48) & (ulong)0x00ffff) | (s_axis_tdata_1 & (ulong)0x00ffffffff) << (byte)16; s_axis_tready = false; doneReading = false; break; } cnt++; } Kiwi.Pause(); } // ############################# // # Switch Logic -- START // ############################# tmp = 0UL; tmp1 = 0UL; tmp2 = 0UL; tmp0 = 0UL; ptr = 0U; broadcast_ports = ((metadata & (ulong)0x00FF0000) ^ DEFAULT_oqs) << (byte)8; // Search the LUT for the dst_mac and for the src_mac for (i = 0U; (uint)i < (uint)LUT_SIZE; i = i + 1U) { tmp1 = LUT[i]; Kiwi.Pause(); // Get the mac address from LUT tmp = tmp1 & (ulong)0xffffffffffff0000; // Get the output port from LUT tmp2 = tmp1 & (ulong)0x00000000000000ff; // Check if we have a hit in the LUT for the dst_mac if (dst_mac == tmp) { // Get the engress port numnber from the LUT OQ = tmp2 << 24; LUT_hit = true; //break; } // Here we check if we need to update an entry based on the src_mac // Get rid off the oq, keep only the mac if (src_mac == tmp >> (byte)16) { // Update if needed // tmp0 = tmp | (metadata & (ulong)0x00ff0000)>>(byte)16; exist = true; ptr = i; //break; } // Save some cycles (maybe) if (LUT_hit && exist) { break; } } // If we have a LUT hit prepare the appropriate output port in the metadata, otherwise flood tuser_low[0] = LUT_hit ? (ulong)(OQ | metadata) : (ulong)(broadcast_ports | metadata); // Update entry if (exist) { LUT[ptr] = src_mac << (byte)16 | (ulong)((metadata >> (byte)16) & (ulong)0x00ff); } Kiwi.Pause(); // Create entry if (!LUT_hit) { LUT[ptr] = src_mac << (byte)16 | (ulong)((metadata >> (byte)16) & (ulong)0x00ff); free = (free > (uint)(LUT_SIZE - 1U)) ? 0U : free = free + 1U; } // ############################# // # Switch Logic -- END // ############################# // Send out this frame and the rest SendFrame(0); // End of frame, ready for next frame IP = false; metadata = 0UL; src_mac = 0UL; dst_mac = 0UL; LUT_hit = false; OQ = 0UL; exist = false; } }
// This procedure creates the GET response packet static public uint Memcached_GET(bool err) { ulong tmp = 0x00, tmp2 = 0x00; // Set the correct IP packet length (little endianess) // GET - Fixed size // Error - size 41B // !Error - size 71B tmp = (err) ? (ulong)0x002900 : (ulong)0x004700; tmp2 = tdata[2] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[2] = tmp2 | tmp; Kiwi.Pause(); // Set the checksum to 0x00, calculate later tmp = tdata[3] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[3] = tmp; Kiwi.Pause(); // Set the correct UDP packet length (little endianess) // GET - Fixed size // in case of an error we must adjust the length accordinlgy // Error - size 21B - 0x15 // !Error - size 51B - 0x33 tmp = (err) ? (ulong)0x1500000000000000 : (ulong)0x3300000000000000; tmp2 = tdata[4] & (ulong)0x0000ffffffffffff; Kiwi.Pause(); tdata[4] = tmp2 | tmp; Kiwi.Pause(); // Reset the UDP checksum tmp = tdata[5]; Kiwi.Pause(); tdata[5] = tmp & ~(ulong)0x00ffff; Kiwi.Pause(); // Set the response // VALUE <key> <flags> <bytes>\r\n // <data block>\r\n // END\r\n tmp = tdata[6] & (ulong)0x00ffff; Kiwi.Pause(); // set GET magic number + opcode // set also the extras length(4b) if (!err) { tdata[6] = tmp | (ulong)0x2045554c41560000; // VALUE Kiwi.Pause(); tdata[7] = key; // <key> Kiwi.Pause(); tdata[8] = (ulong)0x00000a0d38203020 | key_value << 48; // <flags> + <bytes> + <data_block> Kiwi.Pause(); tdata[9] = key_value >> 16 | (ulong)0x0a0d000000000000; // <data block>\r\n Kiwi.Pause(); tdata[10] = (ulong)0x000a0d444e45; } else { tdata[6] = tmp | (ulong)0x000a0d444e450000; // END\r\n } Kiwi.Pause(); // Fill up the rest of the response packet if (!err) { // Set the correct metadata for the datapath // Fixed size response packet for GET/DELETE failure tuser_low[0] = (dst_port << 24) | (src_port << 16) | (ulong)85; tkeep[10] = (byte)0x1f; return(10); } else { tuser_low[0] = (dst_port << 24) | (src_port << 16) | (ulong)55; tkeep[6] = (byte)0x7f; return(6); } }
// This procedure perform basic control operation for the CAM static uint cam_controller(byte mode) { uint tmp_addr = 0x00; // Poll until CAM is ready while (cam_busy) { Kiwi.Pause(); } switch (mode) { // WRITE operation - returns the address in which the key is stored case SET: // 0x01 // Check if the key exists in the CAM cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); // Perform the store operation // If exist, uoate the entry, otherwise store if (!cam_match) { Kiwi.Pause(); cam_din = key; cam_wr_addr = (byte)mem_controller_cnt; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); } tmp_addr = (cam_match) ? (byte)cam_match_addr : (byte)mem_controller_cnt; // Increase the counter if we done have any match if (!cam_match) { mem_controller_cnt += 1U; } break; // READ operation - return the address if we have a match otherwhise MEM_SIZE case GET: // 0x02 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); tmp_addr = (cam_match) ? (uint)cam_match_addr : (uint)MEM_SIZE; break; // DELETE operation - return the address if we have a match otherwhise MEM_SIZE case DELETE: // 0x03 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); tmp_addr = (cam_match) ? (uint)cam_match_addr : (uint)MEM_SIZE; Kiwi.Pause(); if (cam_match) { Kiwi.Pause(); cam_din = (ulong)0x00; cam_wr_addr = (byte)tmp_addr; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); } break; default: break; } if (mem_controller_cnt == (uint)(MEM_SIZE - 1U)) { mem_controller_cnt = 0; // else mem_controller_cnt += 1U; } return(tmp_addr); }
// This method describes the operations required to rx a frame over the AXI4-Stream. // and extract basic information such as dst_MAC, src_MAC, dst_port, src_port static public uint ReceiveFrame() { m_axis_tdata = (ulong)0x0; m_axis_tkeep = (byte)0x0; m_axis_tlast = false; m_axis_tvalid = false; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; s_axis_tready = true; segm_num = 0U; icmp_header = false; Kiwi.Pause(); // The start condition uint cnt = 0; uint psize = 0; bool start = s_axis_tvalid && s_axis_tready; bool doneReading = true; bool receive = s_axis_tvalid; ulong data = 0x00; byte data2 = 0x00; // ############################# // # Receive the frame // ############################# cnt = 0; doneReading = true; while (doneReading) { if (s_axis_tvalid) { tdata[cnt] = s_axis_tdata; tkeep[cnt] = s_axis_tkeep; tlast[cnt] = s_axis_tlast; //tuser_hi[cnt] = s_axis_tuser_hi; tuser_low[cnt] = s_axis_tuser_low; segm_num += 1U; psize = cnt++; doneReading = !s_axis_tlast && s_axis_tvalid; // Create backpresure to whatever sends data to us s_axis_tready = s_axis_tlast ? false : true; } Kiwi.Pause(); } icmp_header = false; data = tdata[psize]; data2 = tkeep[psize]; Kiwi.Pause(); switch (data2) { case 0x01: tdata[psize] = data & (ulong)0x00ff; break; case 0x03: tdata[psize] = data & (ulong)0x00ffff; break; case 0x07: tdata[psize] = data & (ulong)0x00ffffff; break; case 0x0f: tdata[psize] = data & (ulong)0x00ffffffff; break; case 0x1f: tdata[psize] = data & (ulong)0x00ffffffffff; break; case 0x3f: tdata[psize] = data & (ulong)0x00ffffffffffff; break; case 0x7f: tdata[psize] = data & (ulong)0x00ffffffffffffff; break; default: break; } Kiwi.Pause(); s_axis_tready = false; cnt = 0; segm_num = 0; return(psize); }
public static void Main() { bool kpp = true; elimit = limit; Kiwi.KppMark("START", "INITIALISE"); // Waypoint Console.WriteLine("Primes Up To " + limit); Kiwi.Pause(); PA[0] = vol > 0; // Process some runtime input data on this thread - prevents Kiwic running the whole program at compile time. Kiwi.Pause(); // Clear array count1 = 2; count = 0; // RESET VALUE FAILED AT ONE POINT: HENCE NEED THIS LINE for (int woz = 0; woz < limit; woz++) { Kiwi.Pause(); PA[woz] = true; Console.WriteLine("Setting initial array flag to hold : addr={0} readback={1}", woz, PA[woz]); // Read back and print. } Kiwi.KppMark("wp2", "CROSSOFF"); // Waypoint int i, j; for (i = 2; i < limit; i++) // Can our predictor cope with the standard optimisations? { Kiwi.Pause(); // Cross off the multiples - optimise by skipping where the base is already crossed off. if (evariant_master > 0) { bool pp = PA[i]; Console.WriteLine(" tnow={2}: scaning up for live factor {0} = {1} ", i, pp, Kiwi.tnow); if (!pp) { continue; } count1 += 1; } // Can further optimise by commencing the cross-off at the factor squared. j = (evariant_master > 1) ? i * i : i + i; if (j >= limit) { Console.WriteLine("Skip out on square"); break; } for (; j < limit; j += i) { Console.WriteLine("Cross off {0} {1} (count1={2})", i, j, count1); Kiwi.Pause(); PA[j] = false; } } Kiwi.KppMark("wp3", "COUNTING"); // Waypoint Console.WriteLine("Now counting"); // Count how many there were and store them consecutively in the output array. for (int w = 0; w < limit; w++) { Kiwi.Pause(); if (PA[w]) { count += 1; if (false) { // PY[count] = (uint)w; // PZ1[count] = w; // PZ2[count] = w; } } Console.WriteLine("Tally counting {0} {1}", w, count); //Console.WriteLine("Tally counting {0} {1} at {2}", w, count, Kiwi.tnow); } Console.WriteLine("There are {0} primes below the natural number {1}.", count, limit); Console.WriteLine("Optimisation variant={1} (count1 is {0}).", count1, evariant_master); Kiwi.Pause(); Kiwi.Pause(); Kiwi.KppMark("FINISH"); // Waypoint Kiwi.Pause(); finished = true; Kiwi.Pause(); }
void Start() { m_dynamiteAdapterObj = m_dynamiteAdapterObj.GetComponent<DynamiteAdapter>(); m_kiwiObj = m_kiwiObj.GetComponent<Kiwi>(); m_banaobj = m_kiwiObj.GetComponent<Banana>(); m_pumpkin = m_kiwiObj.GetComponent<Pumpkin>(); }
// This method describes the operations required to tx a frame over the AXI4-Stream. static void SendFrame(uint psize) { // ############################# // # Transmit the frame // ############################# m_axis_tvalid = false; s_axis_tready = false; uint i = 0U, ttkeep; bool done = false, valid = false, ttlast; ulong a = 0UL, ttdata_0, ttdata_1, ttdata_2, ttdata_3, ttuser_hi, ttuser_low; byte b = 0; bool c = false; // transmit the first frame that we have already read do { m_axis_tdata_0 = tdata_0[0]; m_axis_tdata_1 = tdata_1[0]; m_axis_tdata_2 = tdata_2[0]; m_axis_tdata_3 = tdata_3[0]; m_axis_tkeep = tkeep[0]; m_axis_tlast = tlast[0]; m_axis_tuser_hi = 0U; m_axis_tuser_low = tuser_low[0]; m_axis_tvalid = true; Kiwi.Pause(); }while(!m_axis_tready); m_axis_tvalid = false; s_axis_tready = true; // Continue with the rest of the frames, as a cut through do { if (m_axis_tready && s_axis_tvalid) { m_axis_tdata_0 = s_axis_tdata_0; m_axis_tdata_1 = s_axis_tdata_1; m_axis_tdata_2 = s_axis_tdata_2; m_axis_tdata_3 = s_axis_tdata_3; m_axis_tkeep = s_axis_tkeep; m_axis_tlast = s_axis_tlast; m_axis_tuser_hi = 0U; m_axis_tuser_low = 0U; m_axis_tvalid = true; s_axis_tready = true; done = s_axis_tlast && s_axis_tvalid; } else { s_axis_tready = false; m_axis_tvalid = false; } Kiwi.Pause(); m_axis_tvalid = false; s_axis_tready = false; Kiwi.Pause(); }while(!done); s_axis_tready = false; m_axis_tvalid = false; m_axis_tlast = false; m_axis_tdata_0 = (ulong)0x0; m_axis_tdata_1 = (ulong)0x0; m_axis_tdata_2 = (ulong)0x0; m_axis_tdata_3 = (ulong)0x0; m_axis_tkeep = (uint)0x0; m_axis_tuser_hi = (ulong)0x0; m_axis_tuser_low = (ulong)0x0; Kiwi.Pause(); }
// This method describes the main logic functionality of the Server static public void memcached_logic() { ulong d, u; uint i = 0U; byte local_command_type = 0; uint pkt_size = 0U; bool is_ipv4 = false, is_udp = false, is_icmp = false; uint addr = 0U; bool good_IP_checksum = false, error = false; while (true) // Process packets indefinately { // Store the packet into the buffer pkt_size = ReceiveFrame(); Kiwi.Pause(); // Extract information from the Ethernet, IP, TCP, UDP frames // Currently this information is located in the buffer entries 0-9 for (i = 0; i <= pkt_size; i++) { d = tdata[i]; u = tuser_low[i]; Kiwi.Pause(); Extract_headers(i, d, u); Kiwi.Pause(); } // We need to store the shared-threat variables here // otherwise if we use it explicity we get long compilation times is_ipv4 = IPv4; is_udp = proto_UDP; is_icmp = false; local_command_type = command_type; Kiwi.Pause(); // ############################# // # Server Logic -- START // ############################# // ####################################################################################### // # MEMCACHED SERVER if (is_ipv4 && is_udp) //&& (local_command_type!=0x00) ) { // Calculate the IP checksum chksum_IP = calc_IP_checksum(); good_IP_checksum = (chksum_IP == (ulong)0x00); Kiwi.Pause(); if (local_command_type != NONE && good_IP_checksum) { // Give to the controller the command to perform an action addr = cam_controller(local_command_type); error = addr == (uint)MEM_SIZE; Kiwi.Pause(); if (!error) { // Store/get the value in/from the RAM switch (local_command_type) { case SET: VALUES_MEM[addr] = key_value; break; case GET: key_value = VALUES_MEM[addr]; break; case DELETE: VALUES_MEM[addr] = 0UL; break; default: break; } } Kiwi.Pause(); chksum_UDP = (ulong)0x00; chksum_IP = 0x00; // Swap the fields in the Ethernet frame swap_multiple_fields(is_udp, is_icmp); Kiwi.Pause(); // Create the response packet + reset appropriate fields(ex. UDP checksum) switch (local_command_type) { case SET: pkt_size = Memcached_SET(); break; case GET: pkt_size = Memcached_GET(error); break; case DELETE: pkt_size = Memcached_DELETE(error); break; default: break; } Kiwi.Pause(); tmp = tdata[3]; Kiwi.Pause(); chksum_IP = calc_IP_checksum(); Kiwi.Pause(); // Set the new IP checksum - as we dont change any info in the IP header, // the checksum should remane the same - but anyway recalc and put it back tdata[3] = (chksum_IP >> 8 | (chksum_IP & (ulong)0x00ff) << 8) | tmp; Kiwi.Pause(); // Here is the UDP checksum - clear it and preserve the other data tmp = tdata[5]; //we have already clear the UDP checksum Kiwi.Pause(); // The 4th element in the buffer is the start of the UDP frame for (i = 4; i <= pkt_size; i++) { tmp2 = (i != 4) ? tdata[i] : tdata[i] >> 16; Kiwi.Pause(); calc_UDP_checksum(tmp2); } // Here is the new UDP length + proto type tmp3 = (tdata[4] & (ulong)0xffff000000000000) | (ulong)0x001100; // (optimization) src, dst IPs - pseudo header tmp2 = src_ip << 32 | dst_ip; Kiwi.Pause(); // (optimization) 11U = 0x11 = UDP proto_type , UDP length - pseudo header calc_UDP_checksum(tmp3); Kiwi.Pause(); calc_UDP_checksum(tmp2); Kiwi.Pause(); // 1's complement of the result tmp2 = (ulong)((chksum_UDP ^ ~(ulong)0x00) & (ulong)0x00ffff); Kiwi.Pause(); // make it back to little endian tmp3 = (ulong)((tmp2 >> 8) | (ulong)(tmp2 & (ulong)0x00ff) << 8); // Set the new UDP checksum tdata[5] = tmp | tmp3; } } //# //########################################################################################### //############################# //# Server Logic -- END //############################# // Procedure to send out the packet if (pkt_size != 0U) { SendFrame(pkt_size); } // End of frame, ready for next frame command_type = NONE; IPv4 = false; proto_UDP = false; chksum_UDP = 0x00; pkt_size = 0x00; error = false; } }
// This method describes the main logic functionality of the Server static public void switch_logic() { ulong local_icmp_code_type, local_chksum_udp, d, u;//, ipv4; uint i = 0, pointer = 0; byte ii = 0, local_magic_num = 0, local_opcode = 0; uint pkt_size = 0, p_size = 0; bool is_ipv4 = false, is_udp = false, is_icmp = false; uint cam_addr = 0, tmp_addr = 0, addr = 0; bool good_IP_checksum = false, error = false; ulong local_key_value, local_extras, local_flag; while (true) // Process packets indefinately { pkt_size = ReceiveFrame(); // Extract information from the Ethernet, IP, TCP, UDP frames for (i = 0; i <= pkt_size; i++) { d = tdata[i]; u = tuser_low[i]; Kiwi.Pause(); Extract_headers(i, d, u); } Kiwi.Pause(); // We need to store the shared-threat variables here // otherwise if we use it explicity we get long compilation times is_ipv4 = IPv4; is_udp = proto_UDP; is_icmp = proto_ICMP; // local_magic_num = magic_num; // local_opcode = opcode; // local_icmp_code_type = ICMP_code_type; local_chksum_udp = chksum_UDP; // local_key_value = key_value; // local_extras = extras; // local_flag = flag; Kiwi.Pause(); // ############################# // # Server Logic -- START // ############################# // ####################################################################################### // # DNS SERVER if (is_ipv4 && is_udp) { chksumIP = calc_IP_checksum(); good_IP_checksum = (chksumIP == (ulong)0x00); //Kiwi.Pause(); // We have already validate part of the UDP checksum while we were receiving the packet // now we need also to add the IP pseudo header + UDP length + prototype(UDP=0x0011) // tmp = (ulong)(src_ip<<32 | dst_ip); // tmp2= (ulong)0x001100 | UDP_total_length<<32; // Kiwi.Pause(); // calc_UDP_checksum(tmp2); // (optimization) 11U = 0x11 = UDP proto_type , UDP length // Kiwi.Pause(); // calc_UDP_checksum(tmp); // (optimization) src, dst IPs // local_chksum_udp = ((tdata[5]&(ulong)0x00ffff)==0x00) ? (ulong)0x00ffff : chksum_UDP; // Check if the UDP checksum is disabled // Kiwi.Pause(); if (good_IP_checksum && one_question && std_query) { chksum_UDP = (ulong)0x00; chksumIP = 0x00; exist_rest = false; swap_multiple_fields(is_udp, is_icmp); Kiwi.Pause(); // Fisrt pattern of the IP name tmp = tdata[7]; Kiwi.Pause(); pointer = MEM_SIZE; for (i = 0; i < MEM_SIZE; i++) { // lookup the first pattern of the IP name tmp1 = DNS_part_0[i]; tmp2 = DNS_part_1[i]; tmp3 = DNS_part_2[i]; // Second part of the IP name tmp4 = tdata[8]; Kiwi.Pause(); if (tmp == tmp1) { if (pkt_size == 9U) { // Third pattern of the IP name tmp5 = tdata[9]; Kiwi.Pause(); exist_rest = ((tmp4 == tmp2) && (tmp5 == tmp3)); } else { exist_rest = (tmp4 == tmp2); } pointer = i; break; } } // Extract the size of the packet from the tuser_low p_size = (uint)(tuser_low[0] & (ulong)0x00ffff); // Preserve the transaction ID and the number of questions and flags, reset the UDP checksum tmp = tdata[5] & ~(ulong)0x00ffff; Kiwi.Pause(); // Set the response bit in the flag field tdata[5] = tmp | (ulong)0x008000000000; Kiwi.Pause(); // Set the response packet with the IP address if (start_parsing && exist_rest) { // Set the number of response answers field tmp = tdata[6] & ~(ulong)0x00ffff; Kiwi.Pause(); tdata[6] = tmp | (ulong)0x000100; // set the number of answers to 1 // Build the answer that we need to append to the end of the packet // Currrenlty the answer is: // 1. pointer(2B) + type(2B) + class(2B) + part of TTL(2B) // 2. part of TTL(2B) + length(2B) + IP(4B) tmp1 = (ulong)0x0000010001000cc0; tmp2 = (ulong)IPs[pointer] << 32 | (ulong)0x000400100e; Kiwi.Pause(); if (last_tkeep == 0x00) { tdata[pkt_size + 1U] = tmp1; Kiwi.Pause(); tdata[pkt_size + 2U] = tmp2; tkeep[pkt_size + 1U] = (byte)0xff; Kiwi.Pause(); tkeep[pkt_size + 2U] = (byte)0xff; } else { tmp3 = tdata[pkt_size] | tmp1 << (last_tkeep * 0x08); tkeep[pkt_size] = 0xff; Kiwi.Pause(); tdata[pkt_size] = tmp3; Kiwi.Pause(); tdata[pkt_size + 1U] = tmp1 >> (((byte)0x08 - last_tkeep) * 0x08) | tmp2 << ((last_tkeep) * 0x08); tkeep[pkt_size + 1U] = 0xff; Kiwi.Pause(); tdata[pkt_size + 2U] = tmp2 >> (((byte)0x08 - last_tkeep) * 0x08); tkeep[pkt_size + 2U] = (byte)(0xff >> ((byte)0x08 - last_tkeep)); Kiwi.Pause(); } // Calculate the new IP length tmp = IP_total_length >> 8 | (IP_total_length & (ulong)0x00ff) << 8; tmp2 = tdata[2] & ~(ulong)0x00ffff; // Reset the IP length Kiwi.Pause(); IP_total_length = tmp + 16U; tdata[2] = tmp2 | (IP_total_length >> 8 | (IP_total_length & (ulong)0x00ff) << 8); // Calculate the new UDP length tmp = UDP_total_length >> 8 | (UDP_total_length & (ulong)0x00ff) << 8; tmp2 = tdata[4] & (ulong)0x0000ffffffffffff; // Reset the UDP length Kiwi.Pause(); UDP_total_length = tmp + 16U; tdata[4] = tmp2 | (UDP_total_length >> 8 | (UDP_total_length & (ulong)0x00ff) << 8) << 48; // Set the output port with the new packet size tuser_low[0] = (src_port << 24) | (src_port << 16) | p_size + 16U; pkt_size += 2U; } // Set the response packet with an error message else { // Set the error code = 0x03 "no such name" , and the response flag tdata[5] = tmp | (ulong)0x00038000000000; tmp5 = tuser_low[0]; Kiwi.Pause(); // Set the output port tuser_low[0] = (src_port << 24) | tmp5; } // Calculate the new IP checksum tmp = tdata[3] & ~(ulong)0x00ffff; Kiwi.Pause(); tdata[3] = tmp; Kiwi.Pause(); chksumIP = calc_IP_checksum(); Kiwi.Pause(); tdata[3] = (chksumIP >> 8 | (chksumIP & (ulong)0x00ff) << 8) | tmp; Kiwi.Pause(); // Here is the UDP checksum - clear it and preserve the other data tmp = tdata[5]; //we have already clear the UDP checksum Kiwi.Pause(); // The 4th element in the buffer is the start of the UDP frame for (i = 4; i <= pkt_size; i++) { tmp2 = (i != 4) ? tdata[i] : tdata[i] >> 16; Kiwi.Pause(); calc_UDP_checksum(tmp2); } tmp3 = (tdata[4] & (ulong)0xffff000000000000) | (ulong)0x001100; // Here is the new UDP length + proto type tmp2 = src_ip << 32 | dst_ip; // (optimization) src, dst IPs Kiwi.Pause(); calc_UDP_checksum(tmp3); // (optimization) 11U = 0x11 = UDP proto_type , UDP length Kiwi.Pause(); calc_UDP_checksum(tmp2); Kiwi.Pause(); // 1's complement of the result tmp2 = (ulong)((chksum_UDP ^ ~(ulong)0x00) & (ulong)0x00ffff); Kiwi.Pause(); // make it back to little endian tmp3 = (ulong)((tmp2 >> 8) | (ulong)(tmp2 & (ulong)0x00ff) << 8); // Set the new UDP checksum tdata[5] = tmp | tmp3; } } // # // ########################################################################################### Kiwi.Pause(); // # // ########################################################################################### // ############################# // # Server Logic -- END // ############################# // Procedure calchksum_ICMPl for transmiting packet SendFrame(pkt_size); //End of frame, ready for next frame one_question = false; std_query = false; start_parsing = false; IPv4 = false; proto_UDP = false; proto_ICMP = false; chksum_UDP = 0x00; pkt_size = 0x00; exist_rest = false; } }
// This procedure creates the DELETE response packet static public uint Memcached_DELETE(bool err) { ulong tmp = 0x00, tmp2 = 0x00; // DELETE - Fixed size total IP length tmp = (!err) ? (ulong)0x002d00 : (ulong)0x002f00; tmp2 = tdata[2] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[2] = tmp2 | tmp; Kiwi.Pause(); // Set the checksum to 0x00, calculate later tmp = tdata[3] & (ulong)0xffffffffffff0000; Kiwi.Pause(); tdata[3] = tmp; // DELETE - Fixed size UDP length ( IP_length - 20B) tmp = (!err) ? (ulong)0x1900000000000000 : (ulong)0x1b00000000000000; tmp2 = tdata[4] & (ulong)0x0000ffffffffffff; Kiwi.Pause(); tdata[4] = tmp2 | tmp; Kiwi.Pause(); // Reset the UDP checksum tmp = tdata[5]; Kiwi.Pause(); tdata[5] = tmp & ~(ulong)0x00ffff; Kiwi.Pause(); // Fill up the rest of the response packet if (!err) { tmp = tdata[6] & 0x000000000000ffff; Kiwi.Pause(); tdata[6] = (ulong)0x4554454c45440000; // DELETE Kiwi.Pause(); tdata[7] = (ulong)0x000a0d44; // D\r\n Kiwi.Pause(); // Set the correct metadata for the datapath // Fixed size response packet for DELETE success tuser_low[0] = (src_port << 24) | (src_port << 16) | (ulong)59; tkeep[7] = (byte)0x07; //pkt_size = 8; return(7U); } else { tmp = tdata[6] & 0x000000000000ffff; Kiwi.Pause(); tdata[6] = (ulong)0x4f465f544f4e0000; // NOT_FO Kiwi.Pause(); tdata[7] = (ulong)0x000a0d444e55; // UND\r\n Kiwi.Pause(); // Set the correct metadata for the datapath // Fixed size response packet for DELETE success tuser_low[0] = (dst_port << 24) | (src_port << 16) | (ulong)61; tkeep[7] = (byte)0x1f; return(7U); } }
// This procedure performs the basic control operation for the CAM. protected static uint CAM_Control(Memory_Operation mode, ulong key) { uint tmp_addr = 0x00, addr = 0x00; ulong tmp_key; //tmp_addr=0x00; bool busy = true; // 1 cycle read latency, 16 cycles write latency // mode=true , WRITE operation //Kiwi.Pause(); // Poll until CAM is ready while (cam_busy) { Kiwi.Pause(); } //addr = mem_controller_cnt; //tmp_key = key; //if(mem_controller_cnt == (uint)(MEM_SIZE-1U)) mem_controller_cnt = 0; switch (mode) { // WRITE operation - returns the address in which the key is stored case Memory_Operation.SET: // 0x01 cam_din = key; cam_wr_addr = (byte)mem_controller_cnt; tmp_addr = (byte)mem_controller_cnt; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); break; // READ operation - return the address if we have a match otherwhise MEM_SIZE case Memory_Operation.GET: // 0x00 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); tmp_addr = (cam_match) ? (uint)cam_match_addr : (uint)MEM_SIZE; break; // DELETE operation - return the address if we have a match otherwhise MEM_SIZE case Memory_Operation.DELETE: // 0x04 cam_cmp_din = key; Kiwi.Pause(); cam_cmp_din = key; Kiwi.Pause(); if (cam_match) { tmp_addr = (uint)cam_match_addr; } else { tmp_addr = (uint)MEM_SIZE; } Kiwi.Pause(); if (cam_match) { Kiwi.Pause(); cam_din = (ulong)0x00; cam_wr_addr = (byte)tmp_addr; Kiwi.Pause(); cam_we = true; Kiwi.Pause(); cam_we = false; Kiwi.Pause(); } break; default: break; } if (mem_controller_cnt == (uint)(MEM_SIZE - 1U)) { mem_controller_cnt = 0; } else { mem_controller_cnt += 1U; } return(tmp_addr); }
protected void SeedData(InheritanceContext context) { var kiwi = new Kiwi { Species = "Apteryx haastii", Name = "Great spotted kiwi", IsFlightless = true, FoundOn = Island.South }; var eagle = new Eagle { Species = "Aquila chrysaetos canadensis", Name = "American golden eagle", Group = EagleGroup.Booted }; eagle.Prey.Add(kiwi); var rose = new Rose { Species = "Rosa canina", Name = "Dog-rose", HasThorns = true }; var daisy = new Daisy { Species = "Bellis perennis", Name = "Common daisy" }; var nz = new Country { Id = 1, Name = "New Zealand" }; nz.Animals.Add(kiwi); var usa = new Country { Id = 2, Name = "USA" }; usa.Animals.Add(eagle); context.Set <Animal>().Add(kiwi); context.Set <Bird>().Add(eagle); context.Set <Country>().Add(nz); context.Set <Country>().Add(usa); context.Set <Rose>().Add(rose); context.Set <Daisy>().Add(daisy); context.AddRange( new Tea { HasMilk = true, CaffeineGrams = 1 }, new Lilt { SugarGrams = 4, Carbination = 7 }, new Coke { SugarGrams = 6, CaffeineGrams = 4, Carbination = 5 }); context.SaveChanges(); }
/*FIXME would like to do this to push the compiler to inline as much as it can, * but this annotation seems to require .NET 4.5: * [MethodImpl(MethodImplOptions.AggressiveInlining)]*/ override public void Apply(ref NetFPGA_Data dataplane) { bool dstmac_lut_hit = false; bool srcmac_lut_exist = false; ulong lut_element_op = 0; // Output port // Get the destination MAC from the buffer. ulong dst_mac = dataplane.tdata.Destination_MAC(); //We structure "srcmac_port" as follows: src_mac_hi | src_mac_low | src_port; ulong srcmac_port = (dataplane.tdata.Source_MAC() << 16) | ((dataplane.tuser_low[0] >> 16) & 0xff); Kiwi.Pause(); // Once we have the destination MAC, check if it exists in the LUT. // We will later set the appropriate metadata into the tuser field accordingly. // We also check if the source MAC is in our LUT. If it isn't then we will // later add it, to map to the source port number. // FIXME how to make an API that can be backed by a CAM rather than this loop for look-up? foreach (ulong lut_element in LUT) { // Get the mac address from LUT ulong lut_element_mac = lut_element.Extract_Bytes(length: 6); // Get the output port from LUT lut_element_op = lut_element.Extract_Bytes(from_byte: 6, length: 2); Kiwi.Pause(); if (!dstmac_lut_hit && lut_element_mac == dst_mac) { dstmac_lut_hit = true; } if (!srcmac_lut_exist && srcmac_port == lut_element) { srcmac_lut_exist = true; } } Kiwi.Pause(); // If the frame does not contain an IPv4 packet then we do not set its // output port; this implicitly drops the frame. if (dataplane.tdata.EtherType_Is(Ethernet.EtherTypes.IPv4)) { // Configure the metadata such that if we have a hit then set the appropriate output // port in the metadata, otherwise broadcast. if (dstmac_lut_hit) { NetFPGA.Set_Output_Port(ref dataplane, lut_element_op); } else { NetFPGA.Broadcast(ref dataplane); } } Kiwi.Pause(); // Add source MAC to our LUT if it's not already there, thus the switch "learns". if (!srcmac_lut_exist) { LUT[free] = srcmac_port; free = (free > (LUT_SIZE - 1)) ? 0 : free++; } }
// This method describes the main logic functionality of TCP response static public void tcp_ping_logic() { ulong local_icmp_code_type, local_chksum_udp; uint i = 0, free = 0, mem_cnt = 0; byte ii = 0, local_magic_num = 0, local_opcode = 0; uint pkt_size = 0; bool exist = false, is_ipv4 = false, is_udp = false, is_icmp = false, is_tcp = false; uint cam_addr = 0, tmp_addr = 0, addr = 0, random_seq_num = 100U; bool good_IP_checksum = false, error = false; ulong local_key_value, local_extras, local_flag, local_TCP_length; random_seq_num = 100U; while (true) // Process packets indefinately { pkt_size = ReceiveFrame(); for (i = 0; i <= 5; i++) { Extract_headers(i, tdata[i], tuser_low[i]); Kiwi.Pause(); } is_ipv4 = IPv4; is_udp = proto_UDP; is_icmp = proto_ICMP; is_tcp = proto_TCP; local_icmp_code_type = ICMP_code_type; Kiwi.Pause(); // ########################################################################################### // # TCP - PING if (is_ipv4 && is_tcp) { // Validate the IP checksum chksumIP = calc_IP_checksum(); Kiwi.Pause(); good_IP_checksum = (chksumIP == (ulong)0x00); // Set the IP total length to big endianess and subtract 20B (IP header) tmp1 = (IP_total_length >> 8 | (IP_total_length & (ulong)0x00ff) << 8) - 20U; // Turn it back to little endian - TCP length local_TCP_length = tmp1 >> 8 | (tmp1 & (ulong)0x00ff) << 8; // Include in the TCP checksum the IP pseudo header tmp = (ulong)(src_ip << 32 | dst_ip); tmp2 = (ulong)0x000600 | local_TCP_length << 32; Kiwi.Pause(); calc_checksum(tmp2); // (optimization) 6U = 0x06 = TCP proto_type , TCP length Kiwi.Pause(); calc_checksum(tmp); // (optimization) src, dst IPs // Validate the TCP checksum for (i = 4; i <= pkt_size; i++) { tmp2 = (i != 4) ? tdata[i] : tdata[i] >> 16; Kiwi.Pause(); calc_checksum(tmp2); } Kiwi.Pause(); // TCP - echo request if (TCP_SYN_flag && good_IP_checksum && chksum_UDP == (ulong)0x00ffff) { swap_multiple_fields(is_udp | is_tcp, is_icmp); chksum_UDP = (ulong)0x00; // Set the seq_num to big endian and add 1 tmp1 = (TCP_seq_num >> 24 | (TCP_seq_num & (ulong)0x00ff0000) >> 8 | (TCP_seq_num & (ulong)0x0000ff00) << 8 | (TCP_seq_num & (ulong)0x00ff) << 24) + 1U; Kiwi.Pause(); TCP_seq_num = (tmp1 >> 24 | (tmp1 & (ulong)0x00ff0000) >> 8 | (tmp1 & (ulong)0x0000ff00) << 8 | (tmp1 & (ulong)0x00ff) << 24); tmp = (ulong)((random_seq_num & (uint)0x00ff00) >> 8 | (random_seq_num & (uint)0x00ff) << 8); // ************************************************** // Set i.the RST-ACK, ii.seq_num, iii.part of ack_num **** RST-ACK **** //*************************************************** tmp2 = (ulong)0x0014 << 56 | TCP_seq_num << 16 | tmp; // ************************************************** // Set i.the SYN-ACK, ii.seq_num, iii.part of ack_num **** SYN-ACK **** // ************************************************** //tmp2 = (ulong)0x0012<<56 | TCP_seq_num<<16 | tmp; tmp3 = tdata[5] & (ulong)0x00ff000000000000; Kiwi.Pause(); // Set the ACK flag + seq num + ack num tmp3 |= tmp2; tdata[5] = tmp3; Kiwi.Pause(); // Set part of the seq_num tmp = tdata[4] & (ulong)0x0000ffffffffffff; Kiwi.Pause(); // Set the seq to the right position tmp |= (ulong)((random_seq_num & (uint)0x00ff0000) << 32 | (random_seq_num & (uint)0x00ff000000) << 32); tdata[4] = tmp; Kiwi.Pause(); // Set the IP total length to big endianess and subtract 20B (IP header) tmp1 = (IP_total_length >> 8 | (IP_total_length & (ulong)0x00ff) << 8) - 20U; // Turn it back to little endian - TCP length local_TCP_length = tmp1 >> 8 | (tmp1 & (ulong)0x00ff) << 8; // Include in the TCP checksum, the IP pseudo header tmp = (ulong)(src_ip << 32 | dst_ip); tmp2 = (ulong)0x000600 | local_TCP_length << 32; Kiwi.Pause(); calc_checksum(tmp2); // (optimization) 6U = 0x06 = TCP proto_type , TCP length Kiwi.Pause(); calc_checksum(tmp); // (optimization) src, dst IPs // Reset the TCP checksum tmp = tdata[6] & (ulong)0xffffffff0000ffff; Kiwi.Pause(); tdata[6] = tmp; // The 4th element in the buffer is the start of the TCP frame for (i = 4; i <= pkt_size; i++) { tmp2 = (i != 4) ? tdata[i] : tdata[i] >> 16; Kiwi.Pause(); calc_checksum(tmp2); } // 1's complement of the result tmp1 = (chksum_UDP ^ ~(ulong)0x00) & (ulong)0x00ffff; Kiwi.Pause(); // make it back to little endian tmp2 = ((tmp1 >> 8) | (tmp1 & (ulong)0x00ff) << 8); // Set the new TCP checksum tdata[6] = tmp | tmp2 << 16; tmp3 = tuser_low[0]; Kiwi.Pause(); // Set the output port tuser_low[0] = (src_port << 24) | (src_port << 16) | tmp3; random_seq_num += 1U; } } Kiwi.Pause(); // # // ########################################################################################### // Procedure calchksum_ICMPl for transmiting packet SendFrame(pkt_size); //End of frame, ready for next frame IPv4 = false; proto_UDP = false; proto_ICMP = false; proto_TCP = false; TCP_SYN_flag = false; chksum_UDP = 0x00; pkt_size = 0x00; } }
/*FIXME would like to do this to push the compiler to inline as much as it can, * but this annotation seems to require .NET 4.5: * [MethodImpl(MethodImplOptions.AggressiveInlining)]*/ override public void Apply(ref NetFPGA_Data dataplane) { bool lut_hit = false; ulong lut_element_op = 0; // Output port ulong tmp = 0; // Get the destination MAC from the buffer. ulong dst_mac = dataplane.tdata.Destination_MAC(); // Once we have the destination MAC, check if it exists in the LUT. // We will later set the appropriate metadata into the tuser field accordingly. foreach (ulong lut_element in LUT) { // Get the mac address from LUT ulong lut_element_mac = lut_element.Extract_Bytes(length: 6); /*LUT[i] & (ulong)0xffffffffffff0000;*/ // Get the output port from LUT lut_element_op = lut_element.Extract_Bytes(from_byte: 6, length: 2); /*LUT[i] & (ulong)0x000000000000ffff*/ Kiwi.Pause(); if (lut_element_mac == dst_mac) { lut_hit = true; break; } } Kiwi.Pause(); // If the frame does not contain an IPv4 packet then we do not set its // output port; this implicitly drops the frame. if (dataplane.tdata.EtherType_Is(Ethernet.EtherTypes.IPv4)) { // Configure the metadata such that if we have a hit then set the appropriate output // port in the metadata, otherwise broadcast. if (lut_hit) { NetFPGA.Set_Output_Port(ref dataplane, lut_element_op); } else { NetFPGA.Broadcast(ref dataplane); } } Kiwi.Pause(); // Check if the source MAC is in our LUT. If it isn't then add it, // to map to the source port number. //We structure "tmp" as follows: src_mac_hi | src_mac_low | src_port; tmp = (dataplane.tdata.Source_MAC() << 16) | ((dataplane.tuser_low[0] >> 16) & 0xff); Kiwi.Pause(); // Check if we need to store a new entry into the LUT if (!lut_hit) { #if Kiwi_Extension // NOTE the Kiwi interpretation of IndexOf might need to insert hard pauses. bool exist = Array.IndexOf(LUT, tmp) > -1 ? true : false; #else bool exist = false; foreach (ulong element in LUT) { Kiwi.Pause(); // Get rid off the oq, keep only the mac if (tmp == element) { exist = true; break; } } #endif if (!exist) { LUT[free] = tmp; free = (free > (LUT_SIZE - 1)) ? 0 : free++; } } }