mirror of
				https://github.com/xcat2/xNBA.git
				synced 2025-11-04 05:12:33 +00:00 
			
		
		
		
	Initial sketch for the generic data-transfer interface.
This commit is contained in:
		
							
								
								
									
										81
									
								
								src/core/interface.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/core/interface.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <gpxe/interface.h>
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * Object communication interfaces
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Obtain reference to interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v intf		Interface
 | 
			
		||||
 * @ret intf		Interface
 | 
			
		||||
 *
 | 
			
		||||
 * Increases the reference count on the interface.
 | 
			
		||||
 */
 | 
			
		||||
static struct interface * intf_get ( struct interface *intf ) {
 | 
			
		||||
	intf->refcnt ( intf, +1 );
 | 
			
		||||
	return intf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Drop reference to interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v intf		Interface
 | 
			
		||||
 *
 | 
			
		||||
 * Decreases the reference count on the interface.
 | 
			
		||||
 */
 | 
			
		||||
static void intf_put ( struct interface *intf ) {
 | 
			
		||||
	intf->refcnt ( intf, -1 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plug an interface into a new destination interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v intf		Interface
 | 
			
		||||
 * @v dest		New destination interface
 | 
			
		||||
 *
 | 
			
		||||
 * The reference to the existing destination interface is dropped, a
 | 
			
		||||
 * reference to the new destination interface is obtained, and the
 | 
			
		||||
 * interface is updated to point to the new destination interface.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that there is no "unplug" call; instead you must plug the
 | 
			
		||||
 * interface into a null interface.
 | 
			
		||||
 */
 | 
			
		||||
void plug ( struct interface *intf, struct interface *dest ) {
 | 
			
		||||
	intf_put ( intf->dest );
 | 
			
		||||
	intf->dest = intf_get ( dest );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Null update reference count
 | 
			
		||||
 *
 | 
			
		||||
 * @v intf		Interface
 | 
			
		||||
 * @v delta		Change to apply to reference count
 | 
			
		||||
 *
 | 
			
		||||
 * Use this as the refcnt() method for an interface that does not need
 | 
			
		||||
 * to support reference counting.
 | 
			
		||||
 */
 | 
			
		||||
void null_refcnt ( struct interface *intf __unused, int delta __unused ) {
 | 
			
		||||
	/* Do nothing */
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								src/core/xfer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/core/xfer.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <gpxe/xfer.h>
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * Data transfer interfaces
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Deliver datagram
 | 
			
		||||
 *
 | 
			
		||||
 * @v xfer		Data-transfer interface
 | 
			
		||||
 * @v iobuf		Datagram I/O buffer
 | 
			
		||||
 * @ret rc		Return status code
 | 
			
		||||
 */
 | 
			
		||||
int deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
 | 
			
		||||
	struct xfer_interface *dest = xfer_dest ( xfer );
 | 
			
		||||
 | 
			
		||||
	return dest->op->deliver ( dest, xfer, iobuf );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Null deliver datagram
 | 
			
		||||
 *
 | 
			
		||||
 * @v xfer		Data-transfer interface
 | 
			
		||||
 * @v src		Source interface
 | 
			
		||||
 * @v iobuf		Datagram I/O buffer
 | 
			
		||||
 * @ret rc		Return status code
 | 
			
		||||
 */
 | 
			
		||||
static int null_deliver ( struct xfer_interface *xfer __unused,
 | 
			
		||||
			  struct xfer_interface *src __unused,
 | 
			
		||||
			  struct io_buffer *iobuf ) {
 | 
			
		||||
	free_iob ( iobuf );
 | 
			
		||||
	return -EPIPE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Null data transfer interface operations */
 | 
			
		||||
struct xfer_interface_operations null_xfer_ops = {
 | 
			
		||||
	.deliver = null_deliver,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Null data transfer interface
 | 
			
		||||
 *
 | 
			
		||||
 * This is the interface to which data transfer interfaces are
 | 
			
		||||
 * connected when unplugged.  It will never generate messages, and
 | 
			
		||||
 * will silently absorb all received messages.
 | 
			
		||||
 */
 | 
			
		||||
struct xfer_interface null_xfer = {
 | 
			
		||||
	.intf = {
 | 
			
		||||
		.dest = &null_xfer.intf,
 | 
			
		||||
		.refcnt = null_refcnt,
 | 
			
		||||
	},
 | 
			
		||||
	.op = &null_xfer_ops,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										36
									
								
								src/include/gpxe/interface.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/include/gpxe/interface.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#ifndef _GPXE_INTERFACE_H
 | 
			
		||||
#define _GPXE_INTERFACE_H
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * Object communication interfaces
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** An object communication interface */
 | 
			
		||||
struct interface {
 | 
			
		||||
	/** Destination interface
 | 
			
		||||
	 *
 | 
			
		||||
	 * When messages are sent via this interface, they will be
 | 
			
		||||
	 * delivered to the destination interface.
 | 
			
		||||
	 *
 | 
			
		||||
	 * This pointer may never be NULL.  When the interface is
 | 
			
		||||
	 * unplugged, it should point to a null interface.
 | 
			
		||||
	 */
 | 
			
		||||
	struct interface *dest;
 | 
			
		||||
	/** Update reference count
 | 
			
		||||
	 *
 | 
			
		||||
	 * @v intf		Interface
 | 
			
		||||
	 * @v delta		Change to apply to reference count
 | 
			
		||||
	 *
 | 
			
		||||
	 * This method updates the reference count for the object
 | 
			
		||||
	 * containing the interface.
 | 
			
		||||
	 */
 | 
			
		||||
	void ( * refcnt ) ( struct interface *intf, int delta );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern void plug ( struct interface *intf, struct interface *dest );
 | 
			
		||||
 | 
			
		||||
extern void null_refcnt ( struct interface *intf, int delta );
 | 
			
		||||
 | 
			
		||||
#endif /* _GPXE_INTERFACE_H */
 | 
			
		||||
							
								
								
									
										148
									
								
								src/include/gpxe/iobuf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/include/gpxe/iobuf.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,148 @@
 | 
			
		||||
#ifndef _GPXE_IOBUF_H
 | 
			
		||||
#define _GPXE_IOBUF_H
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * I/O buffers
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <gpxe/list.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A persistent I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * This data structure encapsulates a long-lived I/O buffer.  The
 | 
			
		||||
 * buffer may be passed between multiple owners, queued for possible
 | 
			
		||||
 * retransmission, etc.
 | 
			
		||||
 */
 | 
			
		||||
struct io_buffer {
 | 
			
		||||
	/** List of which this buffer is a member
 | 
			
		||||
	 *
 | 
			
		||||
	 * The list must belong to the current owner of the buffer.
 | 
			
		||||
	 * Different owners may maintain different lists (e.g. a
 | 
			
		||||
	 * retransmission list for TCP).
 | 
			
		||||
	 */
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
 | 
			
		||||
	/** Start of the buffer */
 | 
			
		||||
	void *head;
 | 
			
		||||
	/** Start of data */
 | 
			
		||||
	void *data;
 | 
			
		||||
	/** End of data */
 | 
			
		||||
	void *tail;
 | 
			
		||||
	/** End of the buffer */
 | 
			
		||||
        void *end;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reserve space at start of I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @v len	Length to reserve
 | 
			
		||||
 * @ret data	Pointer to new start of buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline void * iob_reserve ( struct io_buffer *iob, size_t len ) {
 | 
			
		||||
	iob->data += len;
 | 
			
		||||
	iob->tail += len;
 | 
			
		||||
	assert ( iob->tail <= iob->end );
 | 
			
		||||
	return iob->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add data to start of I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @v len	Length to add
 | 
			
		||||
 * @ret data	Pointer to new start of buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline void * iob_push ( struct io_buffer *iob, size_t len ) {
 | 
			
		||||
	iob->data -= len;
 | 
			
		||||
	assert ( iob->data >= iob->head );
 | 
			
		||||
	return iob->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove data from start of I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @v len	Length to remove
 | 
			
		||||
 * @ret data	Pointer to new start of buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline void * iob_pull ( struct io_buffer *iob, size_t len ) {
 | 
			
		||||
	iob->data += len;
 | 
			
		||||
	assert ( iob->data <= iob->tail );
 | 
			
		||||
	return iob->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add data to end of I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @v len	Length to add
 | 
			
		||||
 * @ret data	Pointer to newly added space
 | 
			
		||||
 */
 | 
			
		||||
static inline void * iob_put ( struct io_buffer *iob, size_t len ) {
 | 
			
		||||
	void *old_tail = iob->tail;
 | 
			
		||||
	iob->tail += len;
 | 
			
		||||
	assert ( iob->tail <= iob->end );
 | 
			
		||||
	return old_tail;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Remove data from end of I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @v len	Length to remove
 | 
			
		||||
 */
 | 
			
		||||
static inline void iob_unput ( struct io_buffer *iob, size_t len ) {
 | 
			
		||||
	iob->tail -= len;
 | 
			
		||||
	assert ( iob->tail >= iob->data );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Empty an I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline void iob_empty ( struct io_buffer *iob ) {
 | 
			
		||||
	iob->tail = iob->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate length of data in an I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @ret len	Length of data in buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline size_t iob_len ( struct io_buffer *iob ) {
 | 
			
		||||
	return ( iob->tail - iob->data );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate available space at start of an I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @ret len	Length of data available at start of buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline size_t iob_headroom ( struct io_buffer *iob ) {
 | 
			
		||||
	return ( iob->data - iob->head );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate available space at end of an I/O buffer
 | 
			
		||||
 *
 | 
			
		||||
 * @v iob	I/O buffer
 | 
			
		||||
 * @ret len	Length of data available at end of buffer
 | 
			
		||||
 */
 | 
			
		||||
static inline size_t iob_tailroom ( struct io_buffer *iob ) {
 | 
			
		||||
	return ( iob->end - iob->tail );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern struct io_buffer * alloc_iob ( size_t len );
 | 
			
		||||
extern void free_iob ( struct io_buffer *iob );
 | 
			
		||||
extern void iob_pad ( struct io_buffer *iob, size_t min_len );
 | 
			
		||||
 | 
			
		||||
#endif /* _GPXE_IOBUF_H */
 | 
			
		||||
							
								
								
									
										78
									
								
								src/include/gpxe/xfer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/include/gpxe/xfer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#ifndef _GPXE_XFER_H
 | 
			
		||||
#define _GPXE_XFER_H
 | 
			
		||||
 | 
			
		||||
/** @file
 | 
			
		||||
 *
 | 
			
		||||
 * Data transfer interfaces
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <gpxe/interface.h>
 | 
			
		||||
#include <gpxe/iobuf.h>
 | 
			
		||||
 | 
			
		||||
struct xfer_interface;
 | 
			
		||||
 | 
			
		||||
/** Data transfer interface operations */
 | 
			
		||||
struct xfer_interface_operations {
 | 
			
		||||
	/** Deliver datagram
 | 
			
		||||
	 *
 | 
			
		||||
	 * @v xfer		Data-transfer interface
 | 
			
		||||
	 * @v src		Source  interface
 | 
			
		||||
	 * @v iobuf		Datagram I/O buffer
 | 
			
		||||
	 * @ret rc		Return status code
 | 
			
		||||
	 */
 | 
			
		||||
	int ( * deliver ) ( struct xfer_interface *xfer,
 | 
			
		||||
			    struct xfer_interface *src,
 | 
			
		||||
			    struct io_buffer *iobuf );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** A data transfer interface */
 | 
			
		||||
struct xfer_interface {
 | 
			
		||||
	/** Generic object communication interface */
 | 
			
		||||
	struct interface intf;
 | 
			
		||||
	/** Operations for received messages */
 | 
			
		||||
	struct xfer_interface_operations *op;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct xfer_interface null_xfer;
 | 
			
		||||
extern struct xfer_interface_operations null_xfer_ops;
 | 
			
		||||
 | 
			
		||||
static inline struct xfer_interface *
 | 
			
		||||
xfer_dest ( struct xfer_interface *xfer ) {
 | 
			
		||||
	return container_of ( xfer->intf.dest, struct xfer_interface, intf );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Plug a data-transfer interface into a new destination interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v xfer		Data-transfer interface
 | 
			
		||||
 * @v dest		New destination interface
 | 
			
		||||
 */
 | 
			
		||||
static inline void xfer_plug ( struct xfer_interface *xfer,
 | 
			
		||||
			       struct xfer_interface *dest ) {
 | 
			
		||||
	plug ( &xfer->intf, &dest->intf );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unplug a data-transfer interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v xfer		Data-transfer interface
 | 
			
		||||
 */
 | 
			
		||||
static inline void xfer_unplug ( struct xfer_interface *xfer ) {
 | 
			
		||||
	plug ( &xfer->intf, &null_xfer.intf );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Terminate a data-transfer interface
 | 
			
		||||
 *
 | 
			
		||||
 * @v xfer		Data-transfer interface
 | 
			
		||||
 *
 | 
			
		||||
 * After calling this method, no further messages will be received via
 | 
			
		||||
 * the interface.
 | 
			
		||||
 */
 | 
			
		||||
static inline void xfer_terminate ( struct xfer_interface *xfer ) {
 | 
			
		||||
	xfer->op = &null_xfer_ops;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* _GPXE_XFER_H */
 | 
			
		||||
		Reference in New Issue
	
	Block a user