-----------------------------------------------------------------------
-- receiver -- Ethernet Packet Receiver
-- Copyright (C) 2016-2024 Stephane Carrez
-- Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-----------------------------------------------------------------------
with Ada.Real_Time;
with Ada.Synchronous_Task_Control;
with Net.Buffers;
with Net.Protos.Arp;
with Net.Protos.Dispatchers;
with Net.Headers;
package body Net.Generic_Receiver is
Ready : Ada.Synchronous_Task_Control.Suspension_Object;
ONE_US : constant Ada.Real_Time.Time_Span := Ada.Real_Time.Microseconds (1);
ETHERTYPE_ARP : constant Net.Uint16 :=
Net.Headers.To_Network (Net.Protos.ETHERTYPE_ARP);
ETHERTYPE_IP : constant Net.Uint16 :=
Net.Headers.To_Network (Net.Protos.ETHERTYPE_IP);
-- ------------------------------
-- Start the receiver loop.
-- ------------------------------
procedure Start is
begin
Ada.Synchronous_Task_Control.Set_True (Ready);
end Start;
task body Controller is
use type Ada.Real_Time.Time;
use type Ada.Real_Time.Time_Span;
use type Net.Uint64;
Packet : Net.Buffers.Buffer_Type;
Ether : Net.Headers.Ether_Header_Access;
Now : Ada.Real_Time.Time;
Dt : Us_Time;
Total : Net.Uint64 := 0;
Count : Net.Uint64 := 0;
begin
-- Wait until the Ethernet driver is ready.
Ada.Synchronous_Task_Control.Suspend_Until_True (Ready);
-- Loop receiving packets and dispatching them.
Min_Receive_Time := Us_Time'Last;
Max_Receive_Time := Us_Time'First;
loop
if Packet.Is_Null then
Net.Buffers.Allocate (Packet);
end if;
if not Packet.Is_Null then
Ifnet.Receive (Packet);
Now := Ada.Real_Time.Clock;
Ether := Packet.Ethernet;
if Ether.Ether_Type = ETHERTYPE_ARP then
Net.Protos.Arp.Receive (Ifnet, Packet);
elsif Ether.Ether_Type = ETHERTYPE_IP then
Net.Protos.Dispatchers.Receive (Ifnet, Packet);
end if;
-- Compute the time taken to process the packet in microseconds.
Dt := Us_Time ((Ada.Real_Time.Clock - Now) / ONE_US);
-- Compute average, min and max values.
Count := Count + 1;
Total := Total + Net.Uint64 (Dt);
Avg_Receive_Time := Us_Time (Total / Count);
if Dt < Min_Receive_Time then
Min_Receive_Time := Dt;
end if;
if Dt > Max_Receive_Time then
Max_Receive_Time := Dt;
end if;
else
delay until Ada.Real_Time.Clock + Ada.Real_Time.Milliseconds (100);
end if;
end loop;
end Controller;
end Net.Generic_Receiver;