Blame iscsiuio/src/unix/nic.h

Packit eace71
/*
Packit eace71
 * Copyright (c) 2009-2011, Broadcom Corporation
Packit eace71
 * Copyright (c) 2014, QLogic Corporation
Packit eace71
 *
Packit eace71
 * Written by:  Benjamin Li  (benli@broadcom.com)
Packit eace71
 *
Packit eace71
 * All rights reserved.
Packit eace71
 *
Packit eace71
 * Redistribution and use in source and binary forms, with or without
Packit eace71
 * modification, are permitted provided that the following conditions
Packit eace71
 * are met:
Packit eace71
 * 1. Redistributions of source code must retain the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer.
Packit eace71
 * 2. Redistributions in binary form must reproduce the above copyright
Packit eace71
 *    notice, this list of conditions and the following disclaimer in the
Packit eace71
 *    documentation and/or other materials provided with the distribution.
Packit eace71
 * 3. All advertising materials mentioning features or use of this software
Packit eace71
 *    must display the following acknowledgement:
Packit eace71
 *      This product includes software developed by Adam Dunkels.
Packit eace71
 * 4. The name of the author may not be used to endorse or promote
Packit eace71
 *    products derived from this software without specific prior
Packit eace71
 *    written permission.
Packit eace71
 *
Packit eace71
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
Packit eace71
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit eace71
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit eace71
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
Packit eace71
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit eace71
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
Packit eace71
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit eace71
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit eace71
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit eace71
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit eace71
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit eace71
 *
Packit eace71
 * nic.h - NIC header file
Packit eace71
 *
Packit eace71
 */
Packit eace71
Packit eace71
#include <errno.h>
Packit eace71
Packit eace71
#ifndef __NIC_H__
Packit eace71
#define __NIC_H__
Packit eace71
Packit eace71
#include <stdint.h>
Packit eace71
#include <netinet/if_ether.h>
Packit eace71
#include <net/if.h>
Packit eace71
#include <linux/limits.h>
Packit eace71
#include <stdlib.h>
Packit eace71
#include <pthread.h>
Packit eace71
Packit eace71
#include "nic_nl.h"
Packit eace71
#include "packet.h"
Packit eace71
#include "uip.h"
Packit eace71
#include "timer.h"
Packit eace71
Packit eace71
#include "iscsi_if.h"
Packit eace71
Packit eace71
/*  Foward declarations */
Packit eace71
struct nic_ops;
Packit eace71
struct nic_lib_handle;
Packit eace71
struct packet;
Packit eace71
struct nic_op;
Packit eace71
Packit eace71
extern pthread_mutex_t nic_lib_list_mutex;
Packit eace71
extern struct nic_lib_handle *nic_lib_list;
Packit eace71
Packit eace71
/*  Used to store a list of active cnic devices */
Packit eace71
extern pthread_mutex_t nic_list_mutex;
Packit eace71
extern struct nic *nic_list;
Packit eace71
Packit eace71
extern void *nl_process_handle_thread(void *arg);
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 *  Constants
Packit eace71
 ******************************************************************************/
Packit eace71
#define MAX_PCI_DEVICE_ENTRIES	64	/* Maxium number of pci_device_id
Packit eace71
					   entries a hw library may contain */
Packit eace71
Packit eace71
#define FREE_CONFIG_NAME	0x0001
Packit eace71
#define FREE_UIO_NAME		0x0002
Packit eace71
#define FREE_ALL_STRINGS	(FREE_CONFIG_NAME | FREE_UIO_NAME)
Packit eace71
#define FREE_NO_STRINGS		0x0000
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * Enumerations
Packit eace71
 ******************************************************************************/
Packit eace71
typedef enum {
Packit eace71
	ALLOW_GRACEFUL_SHUTDOWN = 1,
Packit eace71
	FORCE_SHUTDOWN = 2,
Packit eace71
} NIC_SHUTDOWN_T;
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 * Structure used to hold PCI vendor, device, subvendor and subdevice ID's
Packit eace71
 ******************************************************************************/
Packit eace71
struct pci_device_id {
Packit eace71
	const uint32_t vendor, device;	/* Vendor and device ID or PCI_ANY_ID */
Packit eace71
	const uint32_t subvendor, subdevice;	/* Subsystem ID's/PCI_ANY_ID */
Packit eace71
	const char *device_name;	/* Data private to the driver */
Packit eace71
};
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * NIC statistics structure
Packit eace71
 ******************************************************************************/
Packit eace71
struct nic_stats {
Packit eace71
	uint64_t interrupts;
Packit eace71
	uint64_t missed_interrupts;
Packit eace71
Packit eace71
	struct {
Packit eace71
		uint64_t packets;
Packit eace71
		uint64_t bytes;
Packit eace71
	} tx;
Packit eace71
Packit eace71
	struct {
Packit eace71
		uint64_t packets;
Packit eace71
		uint64_t bytes;
Packit eace71
	} rx;
Packit eace71
};
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * NIC interface structure
Packit eace71
 ******************************************************************************/
Packit eace71
typedef struct nic_interface {
Packit eace71
	struct nic_interface *vlan_next;
Packit eace71
	struct nic_interface *next;
Packit eace71
	struct nic *parent;
Packit eace71
Packit eace71
	uint16_t protocol;
Packit eace71
	uint16_t flags;
Packit eace71
#define NIC_IFACE_PERSIST	(1<<0)
Packit eace71
#define NIC_IFACE_ACQUIRE	(1<<1)
Packit eace71
#define NIC_IFACE_PATHREQ_WAIT1	(1<<2)
Packit eace71
#define NIC_IFACE_PATHREQ_WAIT2 (1<<3)
Packit eace71
#define NIC_IFACE_PATHREQ_WAIT	(NIC_IFACE_PATHREQ_WAIT1 | \
Packit eace71
				 NIC_IFACE_PATHREQ_WAIT2)
Packit eace71
	uint8_t mac_addr[ETH_ALEN];
Packit eace71
	uint8_t vlan_priority;
Packit eace71
	uint16_t vlan_id;
Packit eace71
#define NO_VLAN		0x8000
Packit eace71
Packit eace71
	uint16_t mtu;
Packit eace71
	time_t start_time;
Packit eace71
Packit eace71
	struct uip_stack ustack;
Packit eace71
Packit eace71
#define IFACE_NUM_PRESENT (1<<0)
Packit eace71
#define IFACE_NUM_INVALID -1
Packit eace71
	int iface_num;
Packit eace71
	int request_type;
Packit eace71
} nic_interface_t;
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * NIC lib operations structure
Packit eace71
 ******************************************************************************/
Packit eace71
struct nic_lib_ops {
Packit eace71
	/*  Used to get the NIC library name */
Packit eace71
	void (*get_library_name) (char **library_name,
Packit eace71
				  size_t *library_name_size);
Packit eace71
Packit eace71
	/*  Used to get to the PCI table supported by the NIC library */
Packit eace71
	void (*get_pci_table) (struct pci_device_id **table,
Packit eace71
			       uint32_t *entries);
Packit eace71
Packit eace71
	/*  Used to get the version of this NIC library */
Packit eace71
	void (*get_library_version) (char **version_string,
Packit eace71
				     size_t *version_string_size);
Packit eace71
Packit eace71
	/*  Used to get the NIC library build date */
Packit eace71
	void (*get_build_date) (char **build_date_string,
Packit eace71
				size_t *build_date_string_size);
Packit eace71
Packit eace71
	/*  Used to get the transport name assoicated with this library */
Packit eace71
	void (*get_transport_name) (char **transport_name,
Packit eace71
				    size_t *transport_name_size);
Packit eace71
Packit eace71
	/*  Used to get the uio name assoicated with this library */
Packit eace71
	void (*get_uio_name) (char **uio_name, size_t *uio_name_size);
Packit eace71
Packit eace71
};
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 * NIC op table definition
Packit eace71
 ******************************************************************************/
Packit eace71
typedef struct nic_ops {
Packit eace71
	struct nic_lib_ops lib_ops;
Packit eace71
Packit eace71
	char *description;
Packit eace71
	int (*open) (struct nic *);
Packit eace71
	int (*close) (struct nic *, NIC_SHUTDOWN_T);
Packit eace71
	int (*read) (struct nic *, struct packet *);
Packit eace71
	int (*write) (struct nic *, nic_interface_t *, struct packet *);
Packit eace71
	void *(*get_tx_pkt) (struct nic *);
Packit eace71
	void (*start_xmit) (struct nic *, size_t, u16_t vlan_id);
Packit eace71
	int (*clear_tx_intr) (struct nic *);
Packit eace71
	int (*handle_iscsi_path_req) (struct nic *,
Packit eace71
				      int,
Packit eace71
				      struct iscsi_uevent *ev,
Packit eace71
				      struct iscsi_path *path,
Packit eace71
				      nic_interface_t *nic_iface);
Packit eace71
} net_ops_t;
Packit eace71
Packit eace71
typedef struct nic_lib_handle {
Packit eace71
	struct nic_lib_handle *next;
Packit eace71
Packit eace71
	pthread_mutex_t mutex;
Packit eace71
	struct nic_ops *ops;
Packit eace71
} nic_lib_handle_t;
Packit eace71
Packit eace71
typedef struct nic {
Packit eace71
	struct nic *next;
Packit eace71
Packit eace71
	uint32_t flags;
Packit eace71
#define NIC_UNITIALIZED		0x0001
Packit eace71
#define NIC_INITIALIZED		0x0002
Packit eace71
#define NIC_ENABLED		0x0004
Packit eace71
#define NIC_DISABLED		0x0008
Packit eace71
#define NIC_IPv6_ENABLED	0x0010
Packit eace71
#define NIC_ADDED_MULICAST	0x0020
Packit eace71
#define NIC_LONG_SLEEP		0x0040
Packit eace71
#define NIC_PATHREQ_WAIT	0x0080
Packit eace71
Packit eace71
#define NIC_VLAN_STRIP_ENABLED	0x0100
Packit eace71
#define NIC_MSIX_ENABLED	0x0200
Packit eace71
#define NIC_TX_HAS_SENT		0x0400
Packit eace71
#define NIC_ENABLED_PENDING	0x0800
Packit eace71
Packit eace71
#define NIC_UIO_NAME_MALLOC	0x1000
Packit eace71
#define NIC_CONFIG_NAME_MALLOC	0x2000
Packit eace71
#define NIC_EXIT_MAIN_LOOP	0x4000
Packit eace71
#define NIC_GOING_DOWN		0x8000
Packit eace71
#define NIC_RESET_UIP		0x10000
Packit eace71
Packit eace71
	uint16_t state;
Packit eace71
#define NIC_STOPPED		0x0001
Packit eace71
#define NIC_STARTED_RUNNING	0x0002
Packit eace71
#define NIC_RUNNING		0x0004
Packit eace71
#define NIC_EXIT		0x0010
Packit eace71
Packit eace71
	int fd;			/* Holds the file descriptor to UIO */
Packit eace71
	uint16_t uio_minor;	/* Holds the UIO minor number */
Packit eace71
Packit eace71
	uint32_t host_no;	/* Holds the associated host number */
Packit eace71
Packit eace71
	char *library_name;	/* Name of the library to assoicate with */
Packit eace71
	char *log_name;		/* Human friendly name used in the log
Packit eace71
				   file                                 */
Packit eace71
	char *config_device_name;	/* Name read from the XML configuration
Packit eace71
					   file                         */
Packit eace71
	char eth_device_name[IFNAMSIZ];	/* Network interface name       */
Packit eace71
	char *uio_device_name;	/* UIO device name                      */
Packit eace71
Packit eace71
	uint32_t intr_count;	/* Total UIO interrupt count            */
Packit eace71
Packit eace71
	int page_size;
Packit eace71
Packit eace71
	/* Held for nic ops manipulation */
Packit eace71
	pthread_mutex_t nic_mutex;
Packit eace71
Packit eace71
	/*  iSCSI ring ethernet MAC address */
Packit eace71
	__u8 mac_addr[ETH_ALEN];
Packit eace71
Packit eace71
	/*  Used to manage the network interfaces of this device */
Packit eace71
	__u32 num_of_nic_iface;
Packit eace71
	nic_interface_t *nic_iface;
Packit eace71
Packit eace71
	/*  Wait for the device to be enabled */
Packit eace71
	pthread_cond_t enable_wait_cond;
Packit eace71
Packit eace71
	/*  Wait for the device to be finished enabled */
Packit eace71
	pthread_cond_t enable_done_cond;
Packit eace71
Packit eace71
	/*  Wait for the nic loop to start */
Packit eace71
	pthread_cond_t nic_loop_started_cond;
Packit eace71
Packit eace71
	/*  Wait for the device to be disabled */
Packit eace71
	pthread_cond_t disable_wait_cond;
Packit eace71
Packit eace71
	/* Held when transmitting */
Packit eace71
	pthread_mutex_t xmit_mutex;
Packit eace71
Packit eace71
	/* The thread this device is running on */
Packit eace71
	pthread_t thread;
Packit eace71
Packit eace71
	/* The thread used to enable the device */
Packit eace71
	pthread_t enable_thread;
Packit eace71
Packit eace71
	/* Statistical Information on this device */
Packit eace71
	time_t start_time;
Packit eace71
	struct nic_stats stats;
Packit eace71
Packit eace71
	/*  Number of retrys from iscsid */
Packit eace71
	uint32_t pending_count;
Packit eace71
	uint32_t pathreq_pending_count;
Packit eace71
Packit eace71
#define DEFAULT_RX_POLL_USEC	100	/* usec */
Packit eace71
	/* options enabled by the user */
Packit eace71
	uint32_t rx_poll_usec;
Packit eace71
Packit eace71
	/*  Used to hold hardware specific data */
Packit eace71
	void *priv;
Packit eace71
Packit eace71
	/*  Used to hold the TX packets that are needed to be sent */
Packit eace71
	struct packet *tx_packet_queue;
Packit eace71
Packit eace71
	/* Mutex to protect the list of free packets */
Packit eace71
	pthread_mutex_t free_packet_queue_mutex;
Packit eace71
Packit eace71
	/*  Used to hold the free packets that are needed to be sent */
Packit eace71
	struct packet *free_packet_queue;
Packit eace71
Packit eace71
	/*  Points to the NIC library */
Packit eace71
	nic_lib_handle_t *nic_library;
Packit eace71
Packit eace71
	/*  Points to the PCI table entry */
Packit eace71
	struct pci_device_id *pci_id;
Packit eace71
Packit eace71
	/*  Used to process the interrupt */
Packit eace71
	int (*process_intr) (struct nic *nic);
Packit eace71
Packit eace71
	struct nic_ops *ops;
Packit eace71
Packit eace71
	/* NL processing parameters */
Packit eace71
	pthread_t nl_process_thread;
Packit eace71
	pthread_cond_t nl_process_cond;
Packit eace71
	pthread_cond_t nl_process_if_down_cond;
Packit eace71
	pthread_mutex_t nl_process_mutex;
Packit eace71
	int nl_process_if_down;
Packit eace71
	int nl_process_head;
Packit eace71
	int nl_process_tail;
Packit eace71
#define NIC_NL_PROCESS_MAX_RING_SIZE        128
Packit eace71
#define NIC_NL_PROCESS_LAST_ENTRY           (NIC_NL_PROCESS_MAX_RING_SIZE - 1)
Packit eace71
#define NIC_NL_PROCESS_NEXT_ENTRY(x) ((x + 1) & NIC_NL_PROCESS_MAX_RING_SIZE)
Packit eace71
	void *nl_process_ring[NIC_NL_PROCESS_MAX_RING_SIZE];
Packit eace71
Packit eace71
	/* The thread used to perform ping */
Packit eace71
	pthread_t ping_thread;
Packit eace71
	uint64_t transport_handle;
Packit eace71
} nic_t;
Packit eace71
Packit eace71
/******************************************************************************
Packit eace71
 * Function Prototypes
Packit eace71
 *****************************************************************************/
Packit eace71
int load_all_nic_libraries();
Packit eace71
Packit eace71
nic_t *nic_init();
Packit eace71
void nic_add(nic_t *nic);
Packit eace71
int nic_remove(nic_t *nic);
Packit eace71
Packit eace71
int nic_add_nic_iface(nic_t *nic, nic_interface_t *nic_iface);
Packit eace71
int nic_process_intr(nic_t *nic, int discard_check);
Packit eace71
Packit eace71
nic_interface_t *nic_iface_init();
Packit eace71
Packit eace71
typedef enum {
Packit eace71
	NIC_LIBRARY_EXSITS = 1,
Packit eace71
	NIC_LIBRARY_DOESNT_EXIST = 2,
Packit eace71
} NIC_LIBRARY_EXIST_T;
Packit eace71
Packit eace71
NIC_LIBRARY_EXIST_T does_nic_uio_name_exist(char *name,
Packit eace71
					    nic_lib_handle_t **handle);
Packit eace71
NIC_LIBRARY_EXIST_T does_nic_library_exist(char *name,
Packit eace71
					   nic_lib_handle_t **handle);
Packit eace71
Packit eace71
/*******************************************************************************
Packit eace71
 *  Packet management utility functions
Packit eace71
 ******************************************************************************/
Packit eace71
struct packet *get_next_tx_packet(nic_t *nic);
Packit eace71
struct packet *get_next_free_packet(nic_t *nic);
Packit eace71
void put_packet_in_tx_queue(struct packet *pkt, nic_t *nic);
Packit eace71
void put_packet_in_free_queue(struct packet *pkt, nic_t *nic);
Packit eace71
Packit eace71
int unload_all_nic_libraries();
Packit eace71
void nic_close(nic_t *nic, NIC_SHUTDOWN_T graceful, int clean);
Packit eace71
Packit eace71
/*  Use this function to fill in minor number and uio, and eth names */
Packit eace71
int nic_fill_name(nic_t *nic);
Packit eace71
Packit eace71
int enable_multicast(nic_t *nic);
Packit eace71
int disable_multicast(nic_t *nic);
Packit eace71
Packit eace71
void nic_set_all_nic_iface_mac_to_parent(nic_t *nic);
Packit eace71
int find_nic_lib_using_pci_id(uint32_t vendor, uint32_t device,
Packit eace71
			      uint32_t subvendor, uint32_t subdevice,
Packit eace71
			      nic_lib_handle_t **handle,
Packit eace71
			      struct pci_device_id **pci_entry);
Packit eace71
Packit eace71
void *nic_loop(void *arg);
Packit eace71
Packit eace71
int nic_packet_capture(struct nic *, struct packet *pkt);
Packit eace71
Packit eace71
int process_packets(nic_t *nic,
Packit eace71
		    struct timer *periodic_timer,
Packit eace71
		    struct timer *arp_timer, nic_interface_t *nic_iface);
Packit eace71
Packit eace71
void prepare_ustack(nic_t *nic,
Packit eace71
		    nic_interface_t *nic_iface,
Packit eace71
		    struct uip_stack *ustack, struct packet *pkt);
Packit eace71
Packit eace71
void prepare_ipv4_packet(nic_t *nic,
Packit eace71
			 nic_interface_t *nic_iface,
Packit eace71
			 struct uip_stack *ustack, struct packet *pkt);
Packit eace71
Packit eace71
void prepare_ipv6_packet(nic_t *nic,
Packit eace71
			 nic_interface_t *nic_iface,
Packit eace71
			 struct uip_stack *ustack, struct packet *pkt);
Packit eace71
Packit eace71
#endif /* __NIC_H__ */