From 99411e36da52884257c8645beda2f601827fbb22 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 13 Sep 2007 13:34:38 +0100 Subject: Added netdev_priv() to ease Linux driver compatibility. --- src/include/gpxe/netdevice.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/include/gpxe') diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index d82c6d8f4..b96b3c041 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -326,6 +326,17 @@ netdev_put ( struct net_device *netdev ) { ref_put ( &netdev->refcnt ); } +/** + * Get driver private area for this network device + * + * @v netdev Network device + * @ret priv Driver private area for this network device + */ +static inline __attribute__ (( always_inline )) void * +netdev_priv ( struct net_device *netdev ) { + return netdev->priv; +} + extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); extern void netdev_tx_complete_err ( struct net_device *netdev, struct io_buffer *iobuf, int rc ); -- cgit v1.2.3-55-g7522 From f09173326c3ec710764769e782859dba79afe945 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 17 Sep 2007 18:38:04 +0100 Subject: Moved iobuf.h assertions outside the static inline functions, so that the assert message's file and line number gives some clue as to the real location of the problem. Added similar assertions to list.h. --- src/include/gpxe/iobuf.h | 28 ++++++++++++++++++++++++---- src/include/gpxe/list.h | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) (limited to 'src/include/gpxe') diff --git a/src/include/gpxe/iobuf.h b/src/include/gpxe/iobuf.h index e3db01ac2..ff7877544 100644 --- a/src/include/gpxe/iobuf.h +++ b/src/include/gpxe/iobuf.h @@ -67,9 +67,13 @@ struct io_buffer { static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) { iobuf->data += len; iobuf->tail += len; - assert ( iobuf->tail <= iobuf->end ); return iobuf->data; } +#define iob_reserve( iobuf, len ) ( { \ + void *__result; \ + __result = iob_reserve ( (iobuf), (len) ); \ + assert ( (iobuf)->tail <= (iobuf)->end ); \ + __result; } ) /** * Add data to start of I/O buffer @@ -80,9 +84,13 @@ static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) { */ static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) { iobuf->data -= len; - assert ( iobuf->data >= iobuf->head ); return iobuf->data; } +#define iob_push( iobuf, len ) ( { \ + void *__result; \ + __result = iob_push ( (iobuf), (len) ); \ + assert ( (iobuf)->data >= (iobuf)->head ); \ + __result; } ) /** * Remove data from start of I/O buffer @@ -96,6 +104,11 @@ static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) { assert ( iobuf->data <= iobuf->tail ); return iobuf->data; } +#define iob_pull( iobuf, len ) ( { \ + void *__result; \ + __result = iob_pull ( (iobuf), (len) ); \ + assert ( (iobuf)->data <= (iobuf)->tail ); \ + __result; } ) /** * Add data to end of I/O buffer @@ -107,9 +120,13 @@ static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) { static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) { void *old_tail = iobuf->tail; iobuf->tail += len; - assert ( iobuf->tail <= iobuf->end ); return old_tail; } +#define iob_put( iobuf, len ) ( { \ + void *__result; \ + __result = iob_put ( (iobuf), (len) ); \ + assert ( (iobuf)->tail <= (iobuf)->end ); \ + __result; } ) /** * Remove data from end of I/O buffer @@ -119,8 +136,11 @@ static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) { */ static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) { iobuf->tail -= len; - assert ( iobuf->tail >= iobuf->data ); } +#define iob_unput( iobuf, len ) do { \ + iob_unput ( (iobuf), (len) ); \ + assert ( (iobuf)->tail >= (iobuf)->data ); \ + } while ( 0 ) /** * Empty an I/O buffer diff --git a/src/include/gpxe/list.h b/src/include/gpxe/list.h index 0e65901c8..602382be6 100644 --- a/src/include/gpxe/list.h +++ b/src/include/gpxe/list.h @@ -10,6 +10,7 @@ */ #include +#include /* * Simple doubly linked list implementation. @@ -62,6 +63,11 @@ static inline void __list_add ( struct list_head *new, static inline void list_add ( struct list_head *new, struct list_head *head ) { __list_add ( new, head, head->next ); } +#define list_add( new, head ) do { \ + assert ( (head)->next->prev == (head) ); \ + assert ( (head)->prev->next == (head) ); \ + list_add ( (new), (head) ); \ + } while ( 0 ) /** * Add a new entry to the tail of a list @@ -76,6 +82,11 @@ static inline void list_add_tail ( struct list_head *new, struct list_head *head ) { __list_add ( new, head->prev, head ); } +#define list_add_tail( new, head ) do { \ + assert ( (head)->next->prev == (head) ); \ + assert ( (head)->prev->next == (head) ); \ + list_add_tail ( (new), (head) ); \ + } while ( 0 ) /* * Delete a list entry by making the prev/next entries @@ -101,6 +112,13 @@ static inline void __list_del ( struct list_head * prev, static inline void list_del ( struct list_head *entry ) { __list_del ( entry->prev, entry->next ); } +#define list_del( entry ) do { \ + assert ( (entry)->prev != NULL ); \ + assert ( (entry)->next != NULL ); \ + assert ( (entry)->next->prev == (entry) ); \ + assert ( (entry)->prev->next == (entry) ); \ + list_del ( (entry) ); \ + } while ( 0 ) /** * Test whether a list is empty -- cgit v1.2.3-55-g7522 From af303db75d467e1268806303766db02150d101d6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 13 Sep 2007 01:53:04 +0100 Subject: Use RFC4390 whenever hardware address exceeds 16 bytes; this allows us to construct DHCP packets suitable for Infiniband. --- src/include/gpxe/dhcp.h | 7 +++++++ src/net/udp/dhcp.c | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) (limited to 'src/include/gpxe') diff --git a/src/include/gpxe/dhcp.h b/src/include/gpxe/dhcp.h index 43bccf185..18baa86ad 100644 --- a/src/include/gpxe/dhcp.h +++ b/src/include/gpxe/dhcp.h @@ -432,6 +432,13 @@ struct dhcphdr { /** Opcode for a reply from server to client */ #define BOOTP_REPLY 2 +/** BOOTP reply must be broadcast + * + * Clients that cannot accept unicast BOOTP replies must set this + * flag. + */ +#define BOOTP_FL_BROADCAST 0x8000 + /** DHCP magic cookie */ #define DHCP_MAGIC_COOKIE 0x63825363UL diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 9e48fe11b..8e34ccb6c 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -298,6 +298,7 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype, void *data, size_t max_len, struct dhcp_packet *dhcppkt ) { struct dhcphdr *dhcphdr = data; + unsigned int hlen; int rc; /* Sanity check */ @@ -309,9 +310,17 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype, dhcphdr->xid = dhcp_xid ( netdev ); dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE ); dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto ); - dhcphdr->hlen = netdev->ll_protocol->ll_addr_len; - memcpy ( dhcphdr->chaddr, netdev->ll_addr, dhcphdr->hlen ); dhcphdr->op = dhcp_op[msgtype]; + /* If hardware length exceeds the chaddr field length, don't + * use the chaddr field. This is as per RFC4390. + */ + hlen = netdev->ll_protocol->ll_addr_len; + if ( hlen > sizeof ( dhcphdr->chaddr ) ) { + hlen = 0; + dhcphdr->flags = htons ( BOOTP_FL_BROADCAST ); + } + dhcphdr->hlen = hlen; + memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen ); /* Initialise DHCP packet structure */ dhcppkt->dhcphdr = dhcphdr; @@ -494,6 +503,14 @@ struct dhcp_netdev_desc { uint16_t device; } __attribute__ (( packed )); +/** DHCP client identifier */ +struct dhcp_client_id { + /** Link-layer protocol */ + uint8_t ll_proto; + /** Link-layer address */ + uint8_t ll_addr[MAX_LL_ADDR_LEN]; +} __attribute__ (( packed )); + /** * Create DHCP request * @@ -511,7 +528,9 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype, struct dhcp_packet *dhcppkt ) { struct device_description *desc = &netdev->dev->desc; struct dhcp_netdev_desc dhcp_desc; + struct dhcp_client_id client_id; size_t dhcp_features_len; + size_t ll_addr_len; int rc; /* Create DHCP packet */ @@ -570,6 +589,21 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype, return rc; } + /* Add DHCP client identifier. Required for Infiniband, and + * doesn't hurt other link layers. + */ + client_id.ll_proto = netdev->ll_protocol->ll_proto; + ll_addr_len = netdev->ll_protocol->ll_addr_len; + assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) ); + memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len ); + if ( ( rc = set_dhcp_packet_option ( dhcppkt, DHCP_CLIENT_ID, + &client_id, + ( ll_addr_len + 1 ) ) ) != 0 ) { + DBG ( "DHCP could not set client ID: %s\n", + strerror ( rc ) ); + return rc; + } + return 0; } -- cgit v1.2.3-55-g7522 From 2ee76d0c938c4b8250a30d606feeaed68788ed6b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 21 Sep 2007 01:19:04 +0100 Subject: Added defines for Infiniband files (which can't be committed to the main tree yet, but reserving the error numbers now avoids problems later). --- src/include/gpxe/errfile.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/include/gpxe') diff --git a/src/include/gpxe/errfile.h b/src/include/gpxe/errfile.h index 4f9e7bc65..1b0ed33f1 100644 --- a/src/include/gpxe/errfile.h +++ b/src/include/gpxe/errfile.h @@ -101,8 +101,10 @@ #define ERRFILE_via_rhine ( ERRFILE_DRIVER | 0x00440000 ) #define ERRFILE_via_velocity ( ERRFILE_DRIVER | 0x00450000 ) #define ERRFILE_w89c840 ( ERRFILE_DRIVER | 0x00460000 ) +#define ERRFILE_ipoib ( ERRFILE_DRIVER | 0x00470000 ) #define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 ) +#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 ) #define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 ) #define ERRFILE_arp ( ERRFILE_NET | 0x00010000 ) @@ -123,6 +125,7 @@ #define ERRFILE_dhcp ( ERRFILE_NET | 0x00100000 ) #define ERRFILE_dns ( ERRFILE_NET | 0x00110000 ) #define ERRFILE_tftp ( ERRFILE_NET | 0x00120000 ) +#define ERRFILE_infiniband ( ERRFILE_NET | 0x00130000 ) #define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 ) #define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 ) -- cgit v1.2.3-55-g7522 From 5793dbe96fc94abe48cfb3303776215f345ccab4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 21 Sep 2007 01:23:57 +0100 Subject: Infinband requires longer link-layer addresses and headers than Ethernet. --- src/include/gpxe/netdevice.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/include/gpxe') diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index d82c6d8f4..2cbd0efb1 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -19,10 +19,10 @@ struct ll_protocol; struct device; /** Maximum length of a link-layer address */ -#define MAX_LL_ADDR_LEN 6 +#define MAX_LL_ADDR_LEN 20 /** Maximum length of a link-layer header */ -#define MAX_LL_HEADER_LEN 16 +#define MAX_LL_HEADER_LEN 32 /** Maximum length of a network-layer address */ #define MAX_NET_ADDR_LEN 4 -- cgit v1.2.3-55-g7522