Example #1
0
        public static int GetKeepLength(this NetFPGA_Data data)
        {
            // Get the length in terms of whole ulongs
            int len64 = 0;

            for (int i = 0; i < data.tlast.Length; i++)
            {
                if (data.tlast[i])
                {
                    len64 = i;
                    break;
                }
            }

            // Get the number of bytes used in the last ulong
            int used_in_last_ulong = 8;

            if (len64 < data.tdata.Length)
            {
                byte tkeep = data.tkeep[len64];
                for (int i = 0; i < 8; i++)
                {
                    if (((0x01 << i) & tkeep) == 0)
                    {
                        used_in_last_ulong = i;
                        break;
                    }
                }
            }

            return(len64 * 8 + used_in_last_ulong);
        }
Example #2
0
        public static int GetOutputPortNumber(this NetFPGA_Data data)
        {
            byte output = data.GetSendIntf();

            if ((output & 0x01) != 0)
            {
                return(0);
            }
            else if ((output & 0x04) != 0)
            {
                return(1);
            }
            else if ((output & 0x10) != 0)
            {
                return(2);
            }
            else if ((output & 0x40) != 0)
            {
                return(3);
            }
            else
            {
                return(-1); // Drop - no (physical) output port specified
            }
        }
Example #3
0
    // NOTE currently this is specific to the version of NetFPGA SUME we're using.
    override public ForwardingDecision process_packet(int in_port, ref Packet packet)
    {
        // Set metadata.
        NetFPGA_Data dataplane = instance.Get_Data();

        NetFPGA.Set_Input_Port(ref dataplane, (ulong)in_port);
        Debug.Assert(in_port == (int)NetFPGA.Read_Input_Port(dataplane));
        byte[] bs = packet.Bytes;
        NetFPGA.Set_Frame(bs, ref dataplane);
        instance.Set_Data(dataplane);

        // Run the logic!
        instance.SwitchLogic();

        dataplane = instance.Get_Data();
        // Retrieve frame.
        bs = new byte[NetFPGA_Data.BUF_SIZE * sizeof(ulong)];
        NetFPGA.Get_Frame(dataplane, ref bs);

        // NOTE assuming Ethernet link layer.
        packet = Packet.ParsePacket(LinkLayers.Ethernet, bs);
        // Retrieve forwarding decision.
        int[] outs             = new int[NetFPGA_Data.NET_PORTS];
        int   outputs          = NetFPGA.Get_Output_Ports(ref dataplane, ref outs, max_ports: PaxConfig_Lite.no_interfaces);
        ForwardingDecision fwd = null;

        // Trim away unused array space.
        Array.Resize <int>(ref outs, outputs);

        fwd = new ForwardingDecision.MultiPortForward(outs);

        return(fwd);
    }
Example #4
0
 public static NetFPGA_Data DeepClone(this NetFPGA_Data src, NetFPGA_Data target = null)
 {
     target = target ?? new NetFPGA_Data();
     Array.Copy(src.tdata, target.tdata, src.tdata.Length);
     Array.Copy(src.tkeep, target.tkeep, src.tkeep.Length);
     Array.Copy(src.tlast, target.tlast, src.tlast.Length);
     Array.Copy(src.tuser_hi, target.tuser_hi, src.tuser_hi.Length);
     Array.Copy(src.tuser_low, target.tuser_low, src.tuser_low.Length);
     return(target);
 }
Example #5
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++;
        }
    }
Example #6
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++;
            }
        }
    }
 override public void Set_Data(NetFPGA_Data data)
 {
     Reference_Switch_Lite.dataplane = data;
 }
Example #8
0
 public static ushort GetFrameSize(this NetFPGA_Data data)
 {
     return((ushort)((data.tuser_low[0]) >> NetFPGA_Data.tuser_low_frame_size));
 }
Example #9
0
 public static byte GetSendIntf(this NetFPGA_Data data)
 {
     return((byte)((data.tuser_low[0]) >> NetFPGA_Data.tuser_low_destination_port));
 }
Example #10
0
 public static byte GetReceiveIntf(this NetFPGA_Data data)
 {
     return((byte)((data.tuser_low[0]) >> NetFPGA_Data.tuser_low_source_port));
 }