summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4v/sys/vnet_gen.h
blob: 2e5623a33e08ff292295a34fddb153f6c9f7db39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _VNET_GEN_H
#define	_VNET_GEN_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/vgen_stats.h>

#define	VGEN_SUCCESS		(0)	/* successful return */
#define	VGEN_FAILURE		(-1)	/* unsuccessful return */

#define	VGEN_NUM_VER		1	/* max # of vgen versions */

#define	VGEN_LOCAL	1	/* local ldc end-point */
#define	VGEN_PEER	2	/* peer ldc end-point */

/* vgen_t flags */
#define	VGEN_STOPPED		0x0
#define	VGEN_STARTED		0x1

#define	KMEM_FREE(_p)		kmem_free((_p), sizeof (*(_p)))

#define	VGEN_INIT_MCTAB_SIZE	16	/* initial size of multicast table */

#define	READ_ENTER(x)	rw_enter(x, RW_READER)
#define	WRITE_ENTER(x)	rw_enter(x, RW_WRITER)
#define	RW_EXIT(x)	rw_exit(x)

/* channel flags */
#define	CHANNEL_ATTACHED	0x1
#define	CHANNEL_STARTED		0x2

/* transmit return values */
#define	VGEN_TX_SUCCESS		0	/* transmit success */
#define	VGEN_TX_FAILURE		1	/* transmit failure */
#define	VGEN_TX_NORESOURCES	2	/* out of tbufs/txds */

/* private descriptor flags */
#define	VGEN_PRIV_DESC_FREE	0x0	/* desc is available */
#define	VGEN_PRIV_DESC_BUSY	0x1	/* desc in use */

#define	LDC_TO_VNET(ldcp)  ((ldcp)->portp->vgenp->vnetp)
#define	LDC_TO_VGEN(ldcp)  ((ldcp)->portp->vgenp)

/* receive thread flags */
#define	VGEN_WTHR_DATARCVD 		0x01 /* data received */
#define	VGEN_WTHR_STOP 			0x02 /* stop worker thr request */
#define	VGEN_WTHR_PROCESSING		0x04 /* worker thr awake & processing */

#define	VGEN_LDC_MTU		64	/* ldc pkt transfer mtu */
#define	VGEN_LDC_UP_DELAY	100	/* usec delay between ldc_up retries */
#define	VGEN_LDC_CLOSE_DELAY	100	/* usec delay between ldc_cl retries */
#define	VGEN_LDC_UNINIT_DELAY	100	/* usec delay between uninit retries */
#define	VGEN_TXWD_INTERVAL	1000	/* tx watchdog freq in msec */
#define	VGEN_TXWD_TIMEOUT	1000	/* tx watchdog timeout in msec */

#define	VGEN_NUM_VMPOOLS	3	/* number of vio mblk pools */

#define	VGEN_DBLK_SZ_128	128	/* data buffer size 128 bytes */
#define	VGEN_DBLK_SZ_256	256	/* data buffer size 256 bytes */
#define	VGEN_DBLK_SZ_2048	2048	/* data buffer size 2K bytes */
#define	VGEN_NRBUFS		512	/* number of receive bufs */

#define	VGEN_TXDBLK_SZ		2048	/* Tx data buffer size */

#define	VGEN_NUM_DESCRIPTORS_MIN	128	/* min # of descriptors */

/*
 * Number of rcv buffers in RxDringData mode
 */
#define	VGEN_RXDRING_NRBUFS	(vnet_num_descriptors * vgen_nrbufs_factor)

static struct ether_addr etherbroadcastaddr = {
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
/*
 * MIB II broadcast/multicast packets
 */
#define	IS_BROADCAST(ehp) \
		(ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0)
#define	IS_MULTICAST(ehp) \
		((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)

/*
 * The handshake process consists of 5 phases defined below, with VH_PHASE0
 * being the pre-handshake phase and VH_DONE is the phase to indicate
 * successful completion of all phases. Each phase may have one to several
 * handshake states which are required to complete successfully to move to the
 * next phase. See functions vgen_handshake() and vgen_handshake_done() for
 * more details.
 */
/* Handshake phases */
enum {	VH_PHASE0, VH_PHASE1, VH_PHASE2, VH_PHASE3, VH_PHASE4, VH_DONE = 0x80 };

/* Handshake states */
enum {

	VER_INFO_SENT	=	0x1,
	VER_ACK_RCVD	=	0x2,
	VER_INFO_RCVD	=	0x4,
	VER_ACK_SENT	=	0x8,
	VER_NEGOTIATED	=	(VER_ACK_RCVD | VER_ACK_SENT),

	ATTR_INFO_SENT	=	0x10,
	ATTR_ACK_RCVD	=	0x20,
	ATTR_INFO_RCVD	=	0x40,
	ATTR_ACK_SENT	=	0x80,
	ATTR_INFO_EXCHANGED	=	(ATTR_ACK_RCVD | ATTR_ACK_SENT),

	DRING_INFO_SENT	=	0x100,
	DRING_ACK_RCVD	=	0x200,
	DRING_INFO_RCVD	=	0x400,
	DRING_ACK_SENT	=	0x800,
	DRING_INFO_EXCHANGED	=	(DRING_ACK_RCVD | DRING_ACK_SENT),

	RDX_INFO_SENT	=	0x1000,
	RDX_ACK_RCVD	=	0x2000,
	RDX_INFO_RCVD	=	0x4000,
	RDX_ACK_SENT	=	0x8000,
	RDX_EXCHANGED	=	(RDX_ACK_RCVD | RDX_ACK_SENT)

};

/* reset flags */
typedef enum {
	VGEN_FLAG_EVT_RESET = 0x1,	/* channel reset event */
	VGEN_FLAG_NEED_LDCRESET = 0x2,	/* need channel reset */
	VGEN_FLAG_UNINIT = 0x4		/* channel tear down */
} vgen_reset_flags_t;

/* caller information needed in some code paths */
typedef enum {
	VGEN_LDC_CB = 0x1,	/* ldc callback handler */
	VGEN_MSG_THR = 0x2,	/* vio message worker thread */
	VGEN_OTHER = 0x4	/* other threads - tx etc */
} vgen_caller_t;

/* get the address of next tbuf */
#define	NEXTTBUF(ldcp, tbufp)	(((tbufp) + 1) == (ldcp)->tbufendp    \
		? (ldcp)->tbufp : ((tbufp) + 1))

/* increment recv index */
#define	INCR_RXI(i, ldcp)	\
		((i) = (((i) + 1) & ((ldcp)->num_rxds - 1)))

/* decrement recv index */
#define	DECR_RXI(i, ldcp)	\
		((i) = (((i) - 1) & ((ldcp)->num_rxds - 1)))

/* increment tx index */
#define	INCR_TXI(i, ldcp)	\
		((i) = (((i) + 1) & ((ldcp)->num_txds - 1)))

/* decrement tx index */
#define	DECR_TXI(i, ldcp)	\
		((i) = (((i) - 1) & ((ldcp)->num_txds - 1)))

/* bounds check rx index */
#define	CHECK_RXI(i, ldcp)	\
		(((i) >= 0) && ((i) < (ldcp)->num_rxds))

/* bounds check tx index */
#define	CHECK_TXI(i, ldcp)	\
		(((i) >= 0) && ((i) < (ldcp)->num_txds))

#ifdef DEBUG

/* Error injection codes */
#define	VGEN_ERR_HVER		0x1	/* handshake version */
#define	VGEN_ERR_HTIMEOUT	0x2	/* handshake timeout */
#define	VGEN_ERR_HSID		0x4	/* handshake session id */
#define	VGEN_ERR_HSTATE		0x8	/* handshake state */
#define	VGEN_ERR_TXTIMEOUT	0x10	/* tx timeout */
#define	VGEN_ERR_RXLOST		0x20	/* rx lost pkts */

#endif
/* private descriptor */
typedef struct vgen_priv_desc {
	uint64_t		flags;		/* flag bits */
	vnet_public_desc_t	*descp;		/* associated public desc */
	ldc_mem_handle_t	memhandle;	/* mem handle for data */
	caddr_t			datap;		/* prealloc'd tx data buffer */
	uint64_t		datalen;	/* total actual datalen */
	uint64_t		ncookies;	/* num ldc_mem_cookies */
	ldc_mem_cookie_t	memcookie[MAX_COOKIES];	/* data cookies */
} vgen_private_desc_t;

/*
 * Handshake parameters (per vio_mailbox.h) of each ldc end point, used
 * during handshake negotiation.
 */
typedef struct vgen_handshake_params {
	/* version specific params */
	uint16_t	ver_major;		/* major version number */
	uint16_t	ver_minor;		/* minor version number */
	uint8_t		dev_class;		/* device class */

	/* attributes specific params */
	uint64_t		mtu;		/* max transfer unit size */
	uint64_t		addr;		/* address of the device */
	uint8_t			addr_type;	/* type of address */
	uint8_t			xfer_mode;	/* SHM or PKT */
	uint16_t		ack_freq;	/* dring data ack freq */
	uint32_t		physlink_update; /* physlink updates */
	uint8_t			dring_mode;	/* Descriptor ring mode */

	/* descriptor ring params */
	uint32_t		num_desc;	/* # of descriptors in ring */
	uint32_t		desc_size;	/* size of descriptor */
	ldc_mem_cookie_t	dring_cookie;	/* desc ring cookie */
	uint32_t		dring_ncookies;	/* # of dring cookies */
	uint64_t		dring_ident;	/* ident=0 for INFO msg */
	boolean_t		dring_ready;	/* dring ready flag */
} vgen_hparams_t;

/* version info */
typedef struct vgen_ver {
	uint16_t	ver_major;		/* major version number */
	uint16_t	ver_minor;		/* minor version number */
} vgen_ver_t;

/*
 * vnet-protocol-version dependent function prototypes.
 */
typedef int	(*vgen_ldctx_t) (void *, mblk_t *);
typedef void	(*vgen_ldcrx_pktdata_t) (void *, void *, uint32_t);
typedef int	(*vgen_ldcrx_dringdata_t) (void *, void *);

/*
 * LDC end point abstraction in vnet. This structure holds all the information
 * that is required to configure and use the Channel for data transfers with
 * the peer LDC end point (vnet or vswitch), using VIO Protocol.
 */
typedef struct vgen_ldc {

	struct vgen_port	*portp;		/* associated port */

	/*
	 * Locks:
	 * locking hierarchy when more than one lock is held concurrently:
	 * cblock > rxlock > txlock > tclock.
	 */
	kmutex_t		cblock;		/* sync callback processing */
	kmutex_t		txlock;		/* protect txd alloc */
	kmutex_t		tclock;		/* tx reclaim lock */
	kmutex_t		wrlock;		/* sync transmits */
	kmutex_t		rxlock;		/* sync reception */
	kmutex_t		pollq_lock;	/* sync polling and rxworker */

	/*
	 * Channel and Handshake Info
	 */
	uint64_t		ldc_id;		/* channel number */
	uint64_t		ldc_handle;	/* channel handle */
	ldc_status_t		ldc_status;	/* channel status */
	vgen_ver_t		vgen_versions[VGEN_NUM_VER]; /* versions */
	int			hphase;		/* handshake phase */
	int			hstate;		/* handshake state bits */
	link_state_t		link_state;	/* channel link state */
#ifdef	VNET_IOC_DEBUG
	boolean_t		link_down_forced; /* forced link down */
#endif
	uint32_t		local_sid;	/* local session id */
	uint32_t		peer_sid;	/* session id of peer */
	vgen_hparams_t		local_hparams;	/* local handshake params */
	vgen_hparams_t		peer_hparams;	/* peer's handshake params */
	timeout_id_t		htid;		/* handshake wd timeout id */
	timeout_id_t		cancel_htid;	/* cancel handshake watchdog */
	uint8_t			dring_mtype;	/* dring mem map type */
	uint64_t		*ldcmsg;	/* msg buffer for ldc_read() */
	uint64_t		msglen;		/* size of ldcmsg */
	uint32_t		flags;		/* flags */
	uint_t			reset_in_progress; /* channel being reset */
	uint32_t		hretries;	/* handshake retry count */
	uint32_t		ldc_reset_count; /* # of channel resets */

	/*
	 * Transmit Specific Fields
	 */
	/* TX-Common (Used in both TxDring and RxDringData modes) */
	uint32_t		num_txds;	   /* # of descriptors */
	uint32_t		tx_dring_ncookies; /* # of dring cookies */
	ldc_dring_handle_t	tx_dring_handle;   /* dring handle */
	ldc_mem_cookie_t	tx_dring_cookie;   /* dring cookie */
	uint32_t		next_txi;	   /* free descriptor index */
	caddr_t			tx_datap;	   /* tx data area */
	size_t			tx_data_sz;	   /* size of data area */
	size_t			tx_dblk_sz;	   /* size of data blk */
	timeout_id_t		wd_tid;		   /* watchdog timeout id */
	boolean_t		tx_blocked;	   /* flow controlled */
	clock_t			tx_blocked_lbolt;  /* flow controlled time */
	boolean_t		resched_peer;	   /* restart peer needed */
	uint32_t		resched_peer_txi;  /* index to resched peer */
	vgen_ldctx_t		tx;		   /* transmit function */
	vgen_ldctx_t		tx_dringdata;	   /* dring transmit function */

	/* TX-TxDring mode */
	vnet_public_desc_t	*txdp;		/* exported dring */
	vgen_private_desc_t	*tbufp;		/* dring associated resources */
	vgen_private_desc_t	*tbufendp;	/* tbuf ring end */
	vgen_private_desc_t	*next_tbufp;	/* free tbuf */
	vgen_private_desc_t	*cur_tbufp;	/* reclaim tbuf */
	uint32_t		cur_txi;	/* reclaim descrptor index */
	uint64_t		next_txseq;	/* msg seqnum */
	clock_t			reclaim_lbolt;	/* time of last reclaim */

	/* TX-RxDringData mode */
	uint32_t		tx_data_ncookies; /* # of data cookies */
	ldc_mem_handle_t	tx_data_handle;	  /* mapped data handle */
	ldc_mem_cookie_t	*tx_data_cookie;  /* mapped data cookies */
	vnet_rx_dringdata_desc_t *mtxdp;	  /* mapped dring */
	uint32_t		dringdata_msgid;  /* msg id */

	/*
	 * Receive Specific Fields
	 */
	/* RX-Common (Used in both TxDring and RxDringData modes) */
	uint32_t		num_rxds;	   /* # of descriptors */
	uint32_t		rx_dring_ncookies; /* # of dring cookies */
	ldc_dring_handle_t	rx_dring_handle;   /* dring handle */
	ldc_mem_cookie_t	rx_dring_cookie;   /* dring cookie */
	uint32_t		next_rxi;	   /* free descriptor index */
	vgen_ldcrx_dringdata_t	rx_dringdata;	   /* dring rcv function */
	vgen_ldcrx_pktdata_t	rx_pktdata;	   /* raw data rcv function */
	boolean_t		polling_on;	   /* polling enabled ? */

	/* RX-TxDring mode */
	vnet_public_desc_t	*mrxdp;		 /* mapped dring */
	uint64_t		next_rxseq;	 /* msg seqnum */
	vio_multi_pool_t	vmp;		 /* mblk pools */
	uint32_t		max_rxpool_size; /* max size of rxpool in use */
	mblk_t			*pollq_headp;	 /* head of pkts in pollq */
	mblk_t			*pollq_tailp;	 /* tail of pkts in pollq */
	kthread_t		*msg_thread;	 /* message thread */
	uint32_t		msg_thr_flags;	 /* message thread flags */
	kmutex_t		msg_thr_lock;	 /* lock for message thread */
	kcondvar_t		msg_thr_cv;	 /* cond.var for msg thread */

	/* RX-RxDringData mode */
	uint32_t		num_rbufs;	  /* # of data bufs */
	uint32_t		rx_data_ncookies; /* # of data cookies */
	ldc_mem_handle_t	rx_data_handle;	  /* exported data handle */
	ldc_mem_cookie_t	*rx_data_cookie;  /* exported data cookies */
	vnet_rx_dringdata_desc_t *rxdp;		  /* exported dring */
	vio_mblk_pool_t		*rx_vmp;	  /* mblk pool */
	vio_mblk_t		**rxdp_to_vmp;	  /* descr to buf map tbl */
	caddr_t			rx_datap;	  /* mapped rx data area */
	size_t			rx_data_sz;	  /* size of mapped rx data */
	size_t			rx_dblk_sz;	  /* size of each rx data blk */
	mblk_t			*rx_pri_head;	  /* priority pkts head */
	mblk_t			*rx_pri_tail;	  /* priority pkts tail */

	/* Channel Statistics */
	vgen_stats_t		stats;		/* channel statistics */
	kstat_t			*ksp;		/* channel kstats */
} vgen_ldc_t;

/* port information  structure */
typedef struct vgen_port {
	struct vgen_port	*nextp;		/* next port in the list */
	struct vgen		*vgenp;		/* associated vgen_t */
	int			port_num;	/* port number */
	boolean_t		is_vsw_port;	/* connected to vswitch ? */
	int			num_ldcs;	/* # of channels in this port */
	uint64_t		*ldc_ids;	/* channel ids */
	vgen_ldc_t		*ldcp;		/* list of ldcs for this port */
	ether_addr_t		macaddr;	/* mac address of peer */
	uint16_t		pvid;		/* port vlan id (untagged) */
	uint16_t		*vids;		/* vlan ids (tagged) */
	uint16_t		nvids;		/* # of vids */
	mod_hash_t		*vlan_hashp;	/* vlan hash table */
	uint32_t		vlan_nchains;	/* # of vlan hash chains */
	uint32_t		use_vsw_port;	/* Use vsw_port or not */
	uint32_t		flags;		/* status of this port */
	vio_net_callbacks_t	vcb;		/* vnet callbacks */
	vio_net_handle_t	vhp;		/* handle from vnet */
	kmutex_t		lock;		/* synchornize ops */
} vgen_port_t;

/* port list structure */
typedef struct vgen_portlist {
	vgen_port_t	*headp;		/* head of ports */
	vgen_port_t	*tailp;		/* tail */
	krwlock_t	rwlock;		/* sync access to the port list */
} vgen_portlist_t;

/* vgen instance information  */
typedef struct vgen {
	vnet_t			*vnetp;		/* associated vnet instance */
	int			instance;	/* vnet instance */
	dev_info_t		*vnetdip;	/* dip of vnet */
	uint64_t		regprop;	/* "reg" property */
	ether_addr_t		macaddr;	/* mac addr of vnet */
	kmutex_t		lock;		/* synchornize ops */
	int			flags;		/* flags */
	vgen_portlist_t		vgenports;	/* Port List */
	mdeg_node_spec_t	*mdeg_parentp;
	mdeg_handle_t		mdeg_dev_hdl;	/* mdeg cb handle for device */
	mdeg_handle_t		mdeg_port_hdl;	/* mdeg cb handle for port */
	vgen_port_t		*vsw_portp;	/* port connected to vsw */
	struct ether_addr	*mctab;		/* multicast addr table */
	uint32_t		mcsize;		/* allocated size of mctab */
	uint32_t		mccount;	/* # of valid addrs in mctab */
	ddi_taskq_t		*rxp_taskq;	/* VIO rx pool taskq */
	uint32_t		pri_num_types;	/* # of priority eth types */
	uint16_t		*pri_types;	/* priority eth types */
	vio_mblk_pool_t		*pri_tx_vmp;	/* tx priority mblk pool */
	uint32_t		max_frame_size;	/* max frame size supported */

	uint32_t		vsw_port_refcnt; /* refcnt for vsw_port */
	boolean_t		pls_negotiated;	/* phys link state update ? */
	link_state_t		phys_link_state; /* physical link state */
} vgen_t;

#ifdef __cplusplus
}
#endif

#endif	/* _VNET_GEN_H */