diff options
author | Michael Brown | 2014-12-11 18:13:38 +0100 |
---|---|---|
committer | Michael Brown | 2014-12-18 15:46:38 +0100 |
commit | 1d2b7c91f780419c805062ccc474967d80dafe96 (patch) | |
tree | 622c179cb8bd25dec8b3fe8ce2f4678829beb815 /src/include | |
parent | [iobuf] Add iob_split() to split an I/O buffer into portions (diff) | |
download | ipxe-1d2b7c91f780419c805062ccc474967d80dafe96.tar.gz ipxe-1d2b7c91f780419c805062ccc474967d80dafe96.tar.xz ipxe-1d2b7c91f780419c805062ccc474967d80dafe96.zip |
[rndis] Add generic RNDIS device abstraction
RNDIS provides an abstraction of a network device on top of a generic
packet transmission mechanism.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/ipxe/errfile.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/netdevice.h | 11 | ||||
-rw-r--r-- | src/include/ipxe/rndis.h | 348 |
3 files changed, 354 insertions, 6 deletions
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index f809337f..fe20b516 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -227,6 +227,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_ping ( ERRFILE_NET | 0x003a0000 ) #define ERRFILE_dhcpv6 ( ERRFILE_NET | 0x003b0000 ) #define ERRFILE_nfs_uri ( ERRFILE_NET | 0x003c0000 ) +#define ERRFILE_rndis ( ERRFILE_NET | 0x003d0000 ) #define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 ) #define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 ) diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index 95ad1cf1..f471e251 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -36,13 +36,12 @@ struct device; /** Maximum length of a link-layer header * - * The longest currently-supported link-layer header is for 802.11: a - * 24-byte frame header plus an 8-byte 802.3 LLC/SNAP header, plus a - * possible 4-byte VLAN header. (The IPoIB link-layer pseudo-header - * doesn't actually include link-layer addresses; see ipoib.c for - * details.) + * The longest currently-supported link-layer header is for RNDIS: an + * 8-byte RNDIS header, a 32-byte RNDIS packet message header, a + * 14-byte Ethernet header and a possible 4-byte VLAN header. Round + * up to 64 bytes. */ -#define MAX_LL_HEADER_LEN 36 +#define MAX_LL_HEADER_LEN 64 /** Maximum length of a network-layer address */ #define MAX_NET_ADDR_LEN 16 diff --git a/src/include/ipxe/rndis.h b/src/include/ipxe/rndis.h new file mode 100644 index 00000000..60ffd10f --- /dev/null +++ b/src/include/ipxe/rndis.h @@ -0,0 +1,348 @@ +#ifndef _IPXE_RNDIS_H +#define _IPXE_RNDIS_H + +/** @file + * + * Remote Network Driver Interface Specification + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdint.h> +#include <ipxe/netdevice.h> +#include <ipxe/iobuf.h> + +/** Maximum time to wait for a transaction to complete + * + * This is a policy decision. + */ +#define RNDIS_MAX_WAIT_MS 1000 + +/** RNDIS message header */ +struct rndis_header { + /** Message type */ + uint32_t type; + /** Message length */ + uint32_t len; +} __attribute__ (( packed )); + +/** RNDIS initialise message */ +#define RNDIS_INITIALIZE_MSG 0x00000002UL + +/** RNDIS initialise message */ +struct rndis_initialize_message { + /** Request ID */ + uint32_t id; + /** Major version */ + uint32_t major; + /** Minor version */ + uint32_t minor; + /** Maximum transfer size */ + uint32_t mtu; +} __attribute__ (( packed )); + +/** RNDIS initialise completion */ +#define RNDIS_INITIALISE_CMPLT 0x80000002UL + +/** RNDIS initialise completion */ +struct rndis_initialise_completion { + /** Request ID */ + uint32_t id; + /** Status */ + uint32_t status; + /** Major version */ + uint32_t major; + /** Minor version */ + uint32_t minor; + /** Device flags */ + uint32_t flags; + /** Medium */ + uint32_t medium; + /** Maximum packets per transfer */ + uint32_t max_pkts; + /** Maximum transfer size */ + uint32_t mtu; + /** Packet alignment factor */ + uint32_t align; + /** Reserved */ + uint32_t reserved; +} __attribute__ (( packed )); + +/** RNDIS halt message */ +#define RNIS_HALT_MSG 0x00000003UL + +/** RNDIS halt message */ +struct rndis_halt_message { + /** Request ID */ + uint32_t id; +} __attribute__ (( packed )); + +/** RNDIS query OID message */ +#define RNDIS_QUERY_MSG 0x00000004UL + +/** RNDIS set OID message */ +#define RNDIS_SET_MSG 0x00000005UL + +/** RNDIS query or set OID message */ +struct rndis_oid_message { + /** Request ID */ + uint32_t id; + /** Object ID */ + uint32_t oid; + /** Information buffer length */ + uint32_t len; + /** Information buffer offset */ + uint32_t offset; + /** Reserved */ + uint32_t reserved; +} __attribute__ (( packed )); + +/** RNDIS query OID completion */ +#define RNDIS_QUERY_CMPLT 0x80000004UL + +/** RNDIS query OID completion */ +struct rndis_query_completion { + /** Request ID */ + uint32_t id; + /** Status */ + uint32_t status; + /** Information buffer length */ + uint32_t len; + /** Information buffer offset */ + uint32_t offset; +} __attribute__ (( packed )); + +/** RNDIS set OID completion */ +#define RNDIS_SET_CMPLT 0x80000005UL + +/** RNDIS set OID completion */ +struct rndis_set_completion { + /** Request ID */ + uint32_t id; + /** Status */ + uint32_t status; +} __attribute__ (( packed )); + +/** RNDIS reset message */ +#define RNDIS_RESET_MSG 0x00000006UL + +/** RNDIS reset message */ +struct rndis_reset_message { + /** Reserved */ + uint32_t reserved; +} __attribute__ (( packed )); + +/** RNDIS reset completion */ +#define RNDIS_RESET_CMPLT 0x80000006UL + +/** RNDIS reset completion */ +struct rndis_reset_completion { + /** Status */ + uint32_t status; + /** Addressing reset */ + uint32_t addr; +} __attribute__ (( packed )); + +/** RNDIS indicate status message */ +#define RNDIS_INDICATE_STATUS_MSG 0x00000007UL + +/** RNDIS diagnostic information */ +struct rndis_diagnostic_info { + /** Status */ + uint32_t status; + /** Error offset */ + uint32_t offset; +} __attribute__ (( packed )); + +/** RNDIS indicate status message */ +struct rndis_indicate_status_message { + /** Status */ + uint32_t status; + /** Status buffer length */ + uint32_t len; + /** Status buffer offset */ + uint32_t offset; + /** Diagnostic information (optional) */ + struct rndis_diagnostic_info diag[0]; +} __attribute__ (( packed )); + +/** RNDIS status codes */ +enum rndis_status { + /** Device is connected to a network medium */ + RNDIS_STATUS_MEDIA_CONNECT = 0x4001000bUL, + /** Device is disconnected from the medium */ + RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000cUL, +}; + +/** RNDIS keepalive message */ +#define RNDIS_KEEPALIVE_MSG 0x00000008UL + +/** RNDIS keepalive message */ +struct rndis_keepalive_message { + /** Request ID */ + uint32_t id; +} __attribute__ (( packed )); + +/** RNDIS keepalive completion */ +#define RNDIS_KEEPALIVE_CMPLT 0x80000008UL + +/** RNDIS keepalive completion */ +struct rndis_keepalive_completion { + /** Request ID */ + uint32_t id; + /** Status */ + uint32_t status; +} __attribute__ (( packed )); + +/** RNDIS packet message */ +#define RNDIS_PACKET_MSG 0x00000001UL + +/** RNDIS packet field */ +struct rndis_packet_field { + /** Offset */ + uint32_t offset; + /** Length */ + uint32_t len; +} __attribute__ (( packed )); + +/** RNDIS packet message */ +struct rndis_packet_message { + /** Data */ + struct rndis_packet_field data; + /** Out-of-band data records */ + struct rndis_packet_field oob; + /** Number of out-of-band data records */ + uint32_t oob_count; + /** Per-packet information record */ + struct rndis_packet_field ppi; + /** Reserved */ + uint32_t reserved; +} __attribute__ (( packed )); + +/** RNDIS packet record */ +struct rndis_packet_record { + /** Length */ + uint32_t len; + /** Type */ + uint32_t type; + /** Offset */ + uint32_t offset; +} __attribute__ (( packed )); + +/** OID for packet filter */ +#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010eUL + +/** Packet filter bits */ +enum rndis_packet_filter { + /** Unicast packets */ + RNDIS_FILTER_UNICAST = 0x00000001UL, + /** Multicast packets */ + RNDIS_FILTER_MULTICAST = 0x00000002UL, + /** All multicast packets */ + RNDIS_FILTER_ALL_MULTICAST = 0x00000004UL, + /** Broadcast packets */ + RNDIS_FILTER_BROADCAST = 0x00000008UL, + /** All packets */ + RNDIS_FILTER_PROMISCUOUS = 0x00000020UL +}; + +/** OID for media status */ +#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL + +/** OID for permanent MAC address */ +#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101UL + +/** OID for current MAC address */ +#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102UL + +struct rndis_device; + +/** RNDIS device operations */ +struct rndis_operations { + /** + * Open RNDIS device + * + * @v rndis RNDIS device + * @ret rc Return status code + */ + int ( * open ) ( struct rndis_device *rndis ); + /** + * Close RNDIS device + * + * @v rndis RNDIS device + */ + void ( * close ) ( struct rndis_device *rndis ); + /** + * Transmit packet + * + * @v rndis RNDIS device + * @v iobuf I/O buffer + * @ret rc Return status code + * + * If this method returns success then the RNDIS device must + * eventually report completion via rndis_tx_complete(). + */ + int ( * transmit ) ( struct rndis_device *rndis, + struct io_buffer *iobuf ); + /** + * Poll for completed and received packets + * + * @v rndis RNDIS device + */ + void ( * poll ) ( struct rndis_device *rndis ); +}; + +/** An RNDIS device */ +struct rndis_device { + /** Network device */ + struct net_device *netdev; + /** Device name */ + const char *name; + /** RNDIS operations */ + struct rndis_operations *op; + /** Driver private data */ + void *priv; + + /** Request ID for current blocking request */ + unsigned int wait_id; + /** Return status code for current blocking request */ + int wait_rc; +}; + +/** + * Initialise an RNDIS device + * + * @v rndis RNDIS device + * @v op RNDIS device operations + */ +static inline void rndis_init ( struct rndis_device *rndis, + struct rndis_operations *op ) { + + rndis->op = op; +} + +extern void rndis_tx_complete_err ( struct rndis_device *rndis, + struct io_buffer *iobuf, int rc ); +extern int rndis_tx_defer ( struct rndis_device *rndis, + struct io_buffer *iobuf ); +extern void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ); + +extern struct rndis_device * alloc_rndis ( size_t priv_len ); +extern int register_rndis ( struct rndis_device *rndis ); +extern void unregister_rndis ( struct rndis_device *rndis ); +extern void free_rndis ( struct rndis_device *rndis ); + +/** + * Complete message transmission + * + * @v rndis RNDIS device + * @v iobuf I/O buffer + */ +static inline void rndis_tx_complete ( struct rndis_device *rndis, + struct io_buffer *iobuf ) { + + rndis_tx_complete_err ( rndis, iobuf, 0 ); +} + +#endif /* _IPXE_RNDIS_H */ |