Beispiel #1
0
        /// <summary>
        /// Transforms a raw frame (i.e., byte sequence) into the abstraction we use for NetFPGA's data+metadata, and sets in the input port metadata to a specific port number.
        /// </summary>
        /// <param name="tdata_e">The raw frame data</param>
        /// <param name="intfNumber">The 0-based port number the frame is arriving on</param>
        /// <remarks>
        /// Note that this involves copying the data (into a ulong array).
        /// </remarks>
        public static NetFPGA_Data CreateData(IEnumerable <byte> tdata_e, int intfNumber)
        {
            var d = new NetFPGA_Data();

            var tdata_b = tdata_e.ToArray();
            var length  = (int)Math.Ceiling(tdata_b.Length / 8.0);

            Buffer.BlockCopy(tdata_b, 0, d.tdata, 0, tdata_b.Length);

            var tkeep = Enumerable.Repeat((byte)0xff, length - 1).Append((byte)~(~0 << tdata_b.Length % 8)).ToArray();

            Array.Copy(tkeep, d.tkeep, tkeep.Length);

            var tlast = Enumerable.Repeat(false, length - 1).Append(true).ToArray();

            Array.Copy(tlast, d.tlast, tlast.Length);

            var tuser_hi = Enumerable.Repeat(0uL, length).ToArray();

            Array.Copy(tuser_hi, d.tuser_hi, tuser_hi.Length);

            var tuser_low = Enumerable.Repeat(((1uL << (intfNumber * 2)) << 16) | (byte)tdata_b.Length, length).ToArray();

            Array.Copy(tuser_low, d.tuser_low, tuser_low.Length);

            return(d);
        }
Beispiel #2
0
        /// <summary>
        ///   Update the metadata to broadcast the frame (to all ports except the
        ///   one that the frame was received on).
        /// </summary>
        public static void Broadcast(ref NetFPGA_Data dataplane)
        {
            ulong broadcast_ports = ((dataplane.tuser_low[0] ^ NetFPGA_Data.default_oqs) >> 8) << 16 | dataplane.tuser_low[0];

            dataplane.tuser_low[0] = (ulong)(broadcast_ports | dataplane.tuser_low[0]);
            return;
        }
Beispiel #3
0
 /// <summary>
 ///   Set the output port to a specific value.
 ///   (i.e., the port to which we are forwarding the frame.)
 /// </summary>
 public static void Set_Output_Port(ref NetFPGA_Data dataplane, ulong value)
 {
     // FIXME we currently don't one-hot encode "value"
     value = value << NetFPGA_Data.tuser_low_destination_port;
     dataplane.tuser_low[0] = (ulong)(value | dataplane.tuser_low[0]);
     return;
 }
Beispiel #4
0
        // Extract the frame from NetFPGA_Data into a byte array.
        public static void Get_Frame(NetFPGA_Data src, ref byte[] dst)
        {
            // FIXME we don't check the bounds of dst.
            // FIXME we don't null unused locations in dst.
            int offset = 0;

            for (int i = 0; i < src.tdata.Length; i++)
            {
                byte[] bs = BitConverter.GetBytes(src.tdata[i]);
                for (int j = 0; j < bs.Length; j++)
                {
                    if (src.tlast[i] && NetFPGA.to_keep(src, i) > j)
                    {
                        break;
                    }

                    dst[offset] = bs[j];
                    offset++;
                }

                if (src.tlast[i])
                {
                    break;
                }
            }
        }
Beispiel #5
0
        /// <summary>
        ///   Read the output ports that are currently set in the metadata.
        ///   (i.e., the port(s) to which we are forwarding the frame.)
        /// </summary>
        public static byte Get_Output_Ports(ref NetFPGA_Data dataplane,
                                            ref int[] output_ports, int?max_ports = null)
        {
            ulong value = dataplane.tuser_low[0];

            value = (value >> NetFPGA_Data.tuser_low_destination_port);
            bool nf0 = (value & 0x01L) > 0;
            bool nf1 = (value & 0x04L) > 0;
            bool nf2 = (value & 0x10L) > 0;
            bool nf3 = (value & 0x40L) > 0;

            // FIXME code in this function is a bit dirty -- can be tidied up?

            byte dim = 0;

            if (nf0)
            {
                dim++;
            }
            if (nf1 && max_ports.HasValue && max_ports.Value > 1)
            {
                dim++;
            }
            if (nf2 && max_ports.HasValue && max_ports.Value > 2)
            {
                dim++;
            }
            if (nf3 && max_ports.HasValue && max_ports.Value > 3)
            {
                dim++;
            }

            Debug.Assert(dim == output_ports.Length);

            int i = 0;

            if (nf0)
            {
                output_ports[i] = 0;
                i++;
            }
            if (nf1)
            {
                output_ports[i] = 1;
                i++;
            }
            if (nf2)
            {
                output_ports[i] = 2;
                i++;
            }
            if (nf3)
            {
                output_ports[i] = 3;
                i++;
            }

            return(dim);
        }
Beispiel #6
0
        // 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
        protected static uint ReceiveFrame()
        {
            var frame = FrameController.ReceiveFrame();

            dataplane = frame.Data;
            uint size = (uint)Math.Min(dataplane.tdata.Length, dataplane.tlast.TakeWhile(x => !x).Count() + 1); // Length of frame in ulongs

            return(size);
        }
Beispiel #7
0
        public static NetFPGA_Data DeepClone(this NetFPGA_Data src)
        {
            var r = new NetFPGA_Data();

            Array.Copy(src.tdata, r.tdata, src.tdata.Length);
            Array.Copy(src.tkeep, r.tkeep, src.tkeep.Length);
            Array.Copy(src.tlast, r.tlast, src.tlast.Length);
            Array.Copy(src.tuser_hi, r.tuser_hi, src.tuser_hi.Length);
            Array.Copy(src.tuser_low, r.tuser_low, src.tuser_low.Length);
            return(r);
        }
Beispiel #8
0
        /// <summary>
        /// Send a frame. Uses the network interface specified by the supplied metadata.
        /// </summary>
        /// <param name="data">The data of the frame to send.</param>
        public void SendFrame(NetFPGA_Data data)
        {
            // Use the current timestamp for this frame
            var frame = new FrameInfo(data, sw.Elapsed);

            // Notify listeners of frame being sent
            OnSendFrame?.Invoke(this, new FrameEventArgs(frame, sw.Elapsed));

            // Log that the frame was sent
            _SentFrames.Add(frame);
        }
Beispiel #9
0
        /// <summary>
        /// Converts the data (<see cref="NetFPGA_Data.tdata"/>) into a binary string, with a title,
        /// and each ulong on a new line.
        /// </summary>
        public static string ToBinaryString(this NetFPGA_Data d)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("tdata:");
            for (int i = 0; i < d.tdata.Length && !d.tlast[i]; i++)
            {
                sb.Append("  ");
                sb.AppendLine(d.tdata[i].ToBinaryString());
            }

            return(sb.ToString());
        }
Beispiel #10
0
        /// <summary>
        /// Converts the data (<see cref="NetFPGA_Data.tdata"/>) into a hex string, with a title,
        /// and each ulong on a new line.
        /// </summary>
        public static string ToHexString(this NetFPGA_Data d)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("tdata:");
            for (int i = 0; i < d.tdata.Length; i++)
            {
                sb.Append("  ");
                sb.AppendLine(d.tdata[i].ToString("X16"));
                if (d.tlast[i])
                {
                    break;
                }
            }

            return(sb.ToString());
        }
Beispiel #11
0
        public static void Write48(this NetFPGA_Data dataplane, ulong v, int offset)
        {
            int index64 = offset / 8;
            int offset1 = offset % 8 * 8;

            ulong data1 = v << offset1;
            ulong mask1 = ~(0x0000FFFFFFFFFFFFuL << offset1);

            dataplane.tdata[index64] = (dataplane.tdata[index64] & mask1) | data1;

            index64++;
            offset1 = 64 - offset1;
            ulong data2 = offset1 >= 64 ? 0 : v >> offset1;
            ulong mask2 = offset1 >= 64 ? ~0uL : ~(0x0000FFFFFFFFFFFFuL >> offset1);

            dataplane.tdata[index64] = (dataplane.tdata[index64] & mask2) | data2;
        }
Beispiel #12
0
        // Move the contents of a byte array into the frame field in NetFPGA_Data.
        public static void Set_Frame(byte[] src, ref NetFPGA_Data dst)
        {
            // If not ulong (8-byte) aligned then we indicate this using
            // NetFPGA_Data.tkeep. We indicate the end of the frame by setting
            // NetFPGA_Data.tlast.
            int i   = 0;
            int max = dst.tdata.Length / sizeof(ulong);

            byte[] buf = new byte[sizeof(long)];

            for (i = 0; i < max; i++)
            {
                for (int j = 0; j < sizeof(long); j++)
                {
                    buf[j] = src[i + j];
                }

                dst.tdata[i * sizeof(long)] = BitConverter.ToUInt32(buf, 0);

                dst.tlast[i] = false;
            }

            // Now we handle the last word.
            dst.tlast[i] = true;
            byte to_keep = (byte)(dst.tdata.Length % sizeof(ulong));

            dst.tkeep[i] = one_hot_encode(to_keep);

            // Copy remaining bytes.
            int k = 0;

            for (k = 0; k < to_keep; k++)
            {
                buf[k] = src[i + k];
            }
            // Zero-out the bytes until the word boundary.
            for (; k < sizeof(ulong); k++)
            {
                buf[k] = 0;
            }

            dst.tdata[i * sizeof(long)] = BitConverter.ToUInt32(buf, 0);
        }
Beispiel #13
0
        /// <summary>
        ///  Read the input port (i.e., port on which we received the frame).
        /// </summary>
        public static uint Read_Input_Port(NetFPGA_Data dataplane)
        {
            uint encoded_in_port = (uint)(dataplane.tuser_low[0] >> NetFPGA_Data.tuser_low_source_port);

            encoded_in_port &= 0x00FF; // Zero out the destination port.

            uint in_port = 0;

            while ((encoded_in_port & 1) == 0)
            {
                in_port++;
                encoded_in_port = encoded_in_port >> 2;
            }

            // "in_port" indicates network port index, starting with 0.
            Debug.Assert(in_port < NetFPGA_Data.NET_PORTS);

            return(in_port);
        }
Beispiel #14
0
        // Extract how many bytes we are keeping from a given (8 byte) segment as
        // identified by an offset.
        // This involves looking up the tkeep[offset] value and carrying out
        // the one-hot decoding.
        // NOTE we expect that the bits indicating which bits to keep are
        //      contiguous. We currently don't check this.
        public static int to_keep(NetFPGA_Data src, int offset)
        {
            byte      tkeep          = src.tkeep[offset];
            int       keeping        = 0;
            const int bits_in_a_byte = 8;

            for (int i = 0; i < bits_in_a_byte; i++)
            {
                tkeep = (byte)(tkeep >> i);
                if ((tkeep & 0x1) == 1)
                {
                    keeping++;
                }
                else
                {
                    break;
                }
            }

            return(keeping);
        }
Beispiel #15
0
        /// <summary>
        ///  Set the input port (i.e., port on which we received the frame).
        /// </summary>
        public static void Set_Input_Port(ref NetFPGA_Data dataplane, ulong value)
        {
            // "value" indicates network port index, starting with 0.
            Debug.Assert(value < NetFPGA_Data.NET_PORTS);

            // Map value into a bit-based encoding as described for source/destination
            // ports in NetFPGA_Data.
            ulong encoded_in_port = 1;

            for (int i = (int)value; i > 0; i--)
            {
                encoded_in_port = encoded_in_port << 2;
            }

            // Move into position, in preparation for OR-ing.
            encoded_in_port = encoded_in_port << NetFPGA_Data.tuser_low_source_port;
            // Erase any existing input port.
            dataplane.tuser_low[0] = (ulong)(0xFF00FFFF & dataplane.tuser_low[0]);
            // Write the new input port.
            dataplane.tuser_low[0] = (ulong)(encoded_in_port | dataplane.tuser_low[0]);
        }
Beispiel #16
0
 public FrameInfo(NetFPGA_Data data, TimeSpan time)
 {
     Data = data;
     Time = time;
 }
Beispiel #17
0
 abstract public void Set_Data(NetFPGA_Data data);