public void Parse(CircularFrameBuffer cfb, bool newFrame) { if (newFrame) { _ethParsed = false; _ipParsed1 = false; _ipParsed2 = false; IpVersion = 0; _transportParsed = false; Protocol = 0; } if (!_ethParsed) { if (ep.Parse(cfb) == 0) { _ethParsed = true; if (ep.IsIPv4) { IpVersion = 4; } else if (ep.IsIPv6) { IpVersion = 6; } } } switch (IpVersion) { case 4: if (!_ipParsed1) { _ipParsed1 = true; if (ipv4.Parse(cfb, false) == 0) { _ipParsed2 = true; } } else if (!_ipParsed2) { if (ipv4.Parse(cfb, true) == 0) { _ipParsed2 = true; } } _ipHeaderLength = ipv4.IHL * 4U * 8U; if (_ipParsed2) { Protocol = ipv4.Protocol; } break; case 6: if (!_ipParsed1) { _ipParsed1 = true; if (ipv6.Parse(cfb, false) == 0) { _ipParsed2 = true; } } else if (!_ipParsed2) { if (ipv6.Parse(cfb, true) == 0) { _ipParsed2 = true; } } _ipHeaderLength = 320U; if (_ipParsed2) { Protocol = ipv6.Protocol; } break; default: return; } switch (Protocol) { case 6: tcp.Parse(cfb, _ipHeaderLength); break; case 17: udp.Parse(cfb, _ipHeaderLength); break; default: return; } }
// This method describes the operations required to route the frames public static void switch_logic() { uint i = 0U, ptr = 0U, free = 0U, cnt = 0U; var 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 CircularNetworkFunctions.RecvOne(cfb, true, true); ep.Parse(cfb); mp.Parse(cfb); metadata = ep.Metadata; dst_mac = ep.DestMac; src_mac = ep.SrcMac; // ############################# // # Switch Logic -- START // ############################# tmp = 0UL; tmp1 = 0UL; tmp2 = 0UL; tmp0 = 0UL; ptr = 0U; // Search the LUT for the dst_mac and for the src_mac for (i = 0U; i < LUT_SIZE; i = i + 1U) { tmp1 = LUT[i]; Kiwi.Pause(); // Get the mac address from LUT tmp = tmp1 & 0xffffffffffff0000; // Get the output port from LUT tmp2 = tmp1 & 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 >> 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 InterfaceFunctions.SetDestInterface(LUT_hit ? (byte)OQ : (byte)mp.BroadcastInterfaces, cfb); // Update entry if (exist) { LUT[ptr] = (src_mac << 16) | ((metadata >> 16) & 0x00ff); } Kiwi.Pause(); // Create entry if (!LUT_hit) { LUT[ptr] = (src_mac << 16) | ((metadata >> 16) & 0x00ff); free = free > LUT_SIZE - 1U ? 0U : free = free + 1U; } // ############################# // # Switch Logic -- END // ############################# // Send out this frame and the rest CircularNetworkFunctions.SendAndCut(cfb); } }