#include "../xen/xen.h" /****************************************************************************** * netif.h * * Unified network-device I/O interface for Xen guest OSes. * * Copyright (c) 2003-2004, Keir Fraser */ #ifndef __SHARED_NETIF_H__ #define __SHARED_NETIF_H__ typedef struct { memory_t addr; /* 0: Machine address of packet. */ MEMORY_PADDING; u16 id; /* 8: Echoed in response message. */ u16 size; /* 10: Packet size in bytes. */ } netif_tx_request_t; /* 12 bytes */ typedef struct { u16 id; /* 0 */ s8 status; /* 2 */ u8 __pad; /* 3 */ } netif_tx_response_t; /* 4 bytes */ typedef struct { u16 id; /* 0: Echoed in response message. */ } netif_rx_request_t; /* 2 bytes */ typedef struct { memory_t addr; /* 0: Machine address of packet. */ MEMORY_PADDING; u16 id; /* 8: */ s16 status; /* 10: -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */ } netif_rx_response_t; /* 12 bytes */ /* * We use a special capitalised type name because it is _essential_ that all * arithmetic on indexes is done on an integer type of the correct size. */ typedef u32 NETIF_RING_IDX; /* * Ring indexes are 'free running'. That is, they are not stored modulo the * size of the ring buffer. The following macros convert a free-running counter * into a value that can directly index a ring-buffer array. */ #define MASK_NETIF_RX_IDX(_i) ((_i)&(NETIF_RX_RING_SIZE-1)) #define MASK_NETIF_TX_IDX(_i) ((_i)&(NETIF_TX_RING_SIZE-1)) #define NETIF_TX_RING_SIZE 256 #define NETIF_RX_RING_SIZE 256 /* This structure must fit in a memory page. */ typedef struct { /* * Frontend places packets into ring at tx_req_prod. * Frontend receives event when tx_resp_prod passes tx_event. */ NETIF_RING_IDX req_prod; /* 0 */ NETIF_RING_IDX req_cons; NETIF_RING_IDX resp_prod; /* 8*/ NETIF_RING_IDX event; /* 12 */ union { /* 16 */ netif_tx_request_t req; netif_tx_response_t resp; } ring[NETIF_TX_RING_SIZE]; } netif_tx_interface_t; /* This structure must fit in a memory page. */ typedef struct { /* * Frontend places empty buffers into ring at rx_req_prod. * Frontend receives event when rx_resp_prod passes rx_event. */ NETIF_RING_IDX req_prod; /* 0 */ NETIF_RING_IDX resp_prod; /* 4 */ NETIF_RING_IDX event; /* 8 */ union { /* 12 */ netif_rx_request_t req; netif_rx_response_t resp; } ring[NETIF_RX_RING_SIZE]; } netif_rx_interface_t; /* Descriptor status values */ #define NETIF_RSP_DROPPED -2 #define NETIF_RSP_ERROR -1 #define NETIF_RSP_OKAY 0 /* xen 2.0 defs ... this needs to get out of here soon but this is a hack for 2.0 * for OSDI 2004 :-) */ /****************************************************************************** * NETWORK-INTERFACE FRONTEND DEFINITIONS */ /* Messages from domain controller to guest. */ #define CMSG_NETIF_FE_INTERFACE_STATUS 0 /* * CMSG_NETIF_FE_INTERFACE_STATUS: * Notify a guest about a status change on one of its network interfaces. * If the interface is CLOSED or DOWN then the interface is disconnected: * 1. The shared-memory frame is available for reuse. * 2. Any unacknowledged messgaes pending on the interface were dropped. */ typedef struct { u32 handle; /* 0 */ u32 status; /* 4 */ u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */ u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */ domid_t domid; /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */ } PACKED netif_fe_interface_status_t; /* 18 bytes */ /* * CMSG_NETIF_FE_DRIVER_STATUS: * Notify the domain controller that the front-end driver is DOWN or UP. * When the driver goes DOWN then the controller will send no more * status-change notifications. * If the driver goes DOWN while interfaces are still UP, the domain * will automatically take the interfaces DOWN. * * NB. The controller should not send an INTERFACE_STATUS message * for interfaces that are active when it receives an UP notification. We * expect that the frontend driver will query those interfaces itself. */ typedef struct { /* IN */ u32 status; /* 0: NETIF_DRIVER_STATUS_??? */ /* OUT */ /* Driver should query interfaces [0..max_handle]. */ u32 max_handle; /* 4 */ } PACKED netif_fe_driver_status_t; /* 8 bytes */ /* * CMSG_NETIF_FE_INTERFACE_CONNECT: * If successful, the domain controller will acknowledge with a * STATUS_CONNECTED message. */ typedef struct { u32 handle; /* 0 */ u32 __pad; /* 4 */ memory_t tx_shmem_frame; /* 8 */ MEMORY_PADDING; memory_t rx_shmem_frame; /* 16 */ MEMORY_PADDING; } PACKED netif_fe_interface_connect_t; /* 24 bytes */ /* * CMSG_NETIF_FE_INTERFACE_DISCONNECT: * If successful, the domain controller will acknowledge with a * STATUS_DISCONNECTED message. */ typedef struct { u32 handle; /* 0 */ } PACKED netif_fe_interface_disconnect_t; /* 4 bytes */ /* * CMSG_NETIF_FE_INTERFACE_QUERY: */ typedef struct { /* IN */ u32 handle; /* 0 */ /* OUT */ u32 status; /* 4 */ u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */ u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */ domid_t domid; /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */ } PACKED netif_fe_interface_query_t; /* 18 bytes */ #endif /****************************************************************************** * arch/xen/drivers/netif/backend/common.h */ #ifdef NOT #define __NETIF__BACKEND__COMMON_H__ typedef struct netif_st { /* Unique identifier for this interface. */ domid_t domid; unsigned int handle; /* Physical parameters of the comms window. */ unsigned long tx_shmem_frame; unsigned long rx_shmem_frame; unsigned int evtchn; int irq; /* The shared rings and indexes. */ netif_tx_interface_t *tx; netif_rx_interface_t *rx; /* Private indexes into shared ring. */ NETIF_RING_IDX rx_req_cons; NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */ NETIF_RING_IDX tx_req_cons; NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */ /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ unsigned long credit_bytes; unsigned long credit_usec; unsigned long remaining_credit; // struct timer_list credit_timeout; /* Miscellaneous private stuff. */ enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; /* * DISCONNECT response is deferred until pending requests are ack'ed. * We therefore need to store the id from the original request. */ u8 disconnect_rspid; struct netif_st *hash_next; Ref refcnt; Lock rx_lock, tx_lock, wlock; int attached; struct Ether *dev; } netif_t; void netif_create(netif_be_create_t *create); void netif_destroy(netif_be_destroy_t *destroy); void netif_connect(netif_be_connect_t *connect); int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id); void __netif_disconnect_complete(netif_t *netif); netif_t *netif_find_by_handle(domid_t domid, unsigned int handle); #define netif_get(_b) (atomic_inc(&(_b)->refcnt)) #define netif_put(_b) \ do { \ if ( atomic_dec_and_test(&(_b)->refcnt) ) \ __netif_disconnect_complete(_b); \ } while (0) void netif_interface_init(void); void netif_ctrlif_init(void); void netif_deschedule(netif_t *netif); int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev); void netif_be_int(int irq, void *dev_id, struct pt_regs *regs); #endif /* __NETIF__BACKEND__COMMON_H__ */