Esempio n. 1
0
    /*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++;
        }
    }
Esempio n. 2
0
    /*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++;
            }
        }
    }