예제 #1
0
        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);
        }
    }