linux-support 0.0.25

Comprehensive Linux support for namespaces, cgroups, processes, scheduling, parsing /proc, parsing /sys, signals, hyper threads, CPUS, NUMA nodes, unusual file descriptors, PCI devices and much, much more
// This file is part of linux-support. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/linux-support/master/COPYRIGHT. No part of linux-support, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2020 The developers of linux-support. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/linux-support/master/COPYRIGHT.


#[doc(hidden)]
#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CommonExpressDataPathSocket<ROTOB: ReceiveOrTransmitOrBoth>(ROTOB);

impl<ROTOB: ReceiveOrTransmitOrBoth> CommonExpressDataPathSocket<ROTOB>
{
	/// Based on `libbpf`'s `xsk_socket__create()`.
	fn new<RingQueueDepths: CreateReceiveOrTransmitOrBoth<ReceiveOrTransmitOrBoth=ROTOB>>(express_data_path_socket_file_descriptor: &ExpressDataPathSocketFileDescriptor, network_interface_index: NetworkInterfaceIndex, receive_or_transmit_or_both_ring_queue_depths: RingQueueDepths, owned_or_shared: XdpSocketAddressFlags, force_copy: bool, force_zero_copy: bool, user_memory_socket_file_descriptor: &ExpressDataPathSocketFileDescriptor, queue_identifier: QueueIdentifier, redirect_map_and_attached_program: &RedirectMapAndAttachedProgram, arguments: RingQueueDepths::Arguments) -> Result<ManuallyDrop<Self>, ExpressDataPathSocketCreationError>
	{
		// NOTE: Needs to happen before the socket is bound below.
		let receive_or_transmit_or_both =
		{
			receive_or_transmit_or_both_ring_queue_depths.set_ring_queue_depths(express_data_path_socket_file_descriptor);
			
			// NOTE: Valid memory map offsets are not available until the socket options in `ring_queue_depths.set_ring_queue_depths()` have been set.
			let memory_map_offsets = express_data_path_socket_file_descriptor.get_memory_map_offsets();
			
			receive_or_transmit_or_both_ring_queue_depths.create_receive_or_transmit_or_both(express_data_path_socket_file_descriptor, &memory_map_offsets, queue_identifier, redirect_map_and_attached_program, arguments)
		}?;
		
		{
			let socket_address = sockaddr_xdp
			{
				sxdp_family: AF_XDP as u16,
				sxdp_flags: owned_or_shared.sxdp_flags(force_copy, force_zero_copy, true),
				sxdp_ifindex: network_interface_index,
				sxdp_queue_id: ExpressDataPathQueueIdentifier::from_queue_identifier(queue_identifier),
				sxdp_shared_umem_fd: user_memory_socket_file_descriptor.as_raw_fd(),
			};
			bind_socket(express_data_path_socket_file_descriptor, &socket_address)?;
		}
		
		Ok(ManuallyDrop::new(Self(receive_or_transmit_or_both)))
	}
}

impl<'a, ROTOB: 'a + ReceiveOrTransmitOrBoth<RP=RP> + Receives<CommonReceiveOnly<RP>>, RP: 'a + ReceivePoll> CommonExpressDataPathSocket<ROTOB>
{
	#[inline(always)]
	fn receive_queue(&'a self) -> &'a ReceiveQueue
	{
		self.receive().receive_queue()
	}
	
	#[inline(always)]
	fn frames_received(&'a self) -> u64
	{
		self.receive().frames_received()
	}
	
	#[inline(always)]
	fn increase_frames_received(&'a self, number_of_frames: NonZeroU32)
	{
		self.receive().increase_frames_received(number_of_frames)
	}
	
	#[inline(always)]
	fn remove_receive_map_queue_identifier<FFQ: FreeFrameQueue>(&'a self, instance: &ExpressDataPathInstance<ROTOB, FFQ>)
	{
		let _ignored = self.receive().remove_receive_map_queue_identifier(&instance.redirect_map_and_attached_program);
	}
	
	#[inline(always)]
	fn receive(&'a self) -> &'a CommonReceiveOnly<ROTOB::RP>
	{
		self.0.receive()
	}
	
	#[inline(always)]
	fn receive_poll(&'a self)
	{
		self.receive().receive_poll()
	}
}

impl<'a, ROTOB: 'a + ReceiveOrTransmitOrBoth<TS=TS> + Transmits<CommonTransmitOnly<TS>>, TS: 'a + TransmitSend> CommonExpressDataPathSocket<ROTOB>
{
	#[inline(always)]
	fn transmit_queue(&'a self) -> &'a TransmitQueue
	{
		self.transmit().transmit_queue()
	}
	
	#[inline(always)]
	fn frames_transmitted(&'a self) -> u64
	{
		self.transmit().frames_transmitted()
	}
	
	#[inline(always)]
	fn outstanding_frames_to_transmit(&'a self) -> u32
	{
		self.transmit().outstanding_frames_to_transmit()
	}
	
	#[inline(always)]
	fn increment_outstanding_frames_to_transmit(&'a self, number_of_frames: NonZeroU32)
	{
		self.transmit().increment_outstanding_frames_to_transmit(number_of_frames)
	}
	
	#[inline(always)]
	fn change_frames_transmitted(&'a self, completed_number_of_frames: NonZeroU32)
	{
		self.transmit().decrement_outstanding_frames_to_transmit(completed_number_of_frames);
		self.transmit().increase_frames_transmitted(completed_number_of_frames);
	}
	
	#[inline(always)]
	fn transmit(&'a self) -> &'a CommonTransmitOnly<TS>
	{
		self.0.transmit()
	}
	
	#[inline(always)]
	fn transmit_send(&'a self)
	{
		self.transmit().transmit_send()
	}
}