summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/hyperv/netvsc/hv_net_vsc.h
blob: f7e7d00a903f1625043f2c16aec594d467c75be9 (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
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
/*-
 * Copyright (c) 2009-2012 Microsoft Corp.
 * Copyright (c) 2010-2012 Citrix Inc.
 * Copyright (c) 2012 NetApp Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * HyperV vmbus (virtual machine bus) network VSC (virtual services client)
 * header file
 *
 * (Updated from unencumbered NvspProtocol.h)
 */

#ifndef __HV_NET_VSC_H__
#define __HV_NET_VSC_H__

#include <sys/types.h>
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/sx.h>

#include <dev/hyperv/include/hyperv.h>


#define NVSP_INVALID_PROTOCOL_VERSION           (0xFFFFFFFF)

#define NVSP_PROTOCOL_VERSION_1                 2
#define NVSP_PROTOCOL_VERSION_2                 0x30002
#define NVSP_MIN_PROTOCOL_VERSION               (NVSP_PROTOCOL_VERSION_1)
#define NVSP_MAX_PROTOCOL_VERSION               (NVSP_PROTOCOL_VERSION_2)

#define NVSP_PROTOCOL_VERSION_CURRENT           NVSP_PROTOCOL_VERSION_2

#define NVSP_OPERATIONAL_STATUS_OK              (0x00000000)
#define NVSP_OPERATIONAL_STATUS_DEGRADED        (0x00000001)
#define NVSP_OPERATIONAL_STATUS_NONRECOVERABLE  (0x00000002)
#define NVSP_OPERATIONAL_STATUS_NO_CONTACT      (0x00000003)
#define NVSP_OPERATIONAL_STATUS_LOST_COMMUNICATION (0x00000004)

/*
 * Maximun number of transfer pages (packets) the VSP will use on a receive
 */
#define NVSP_MAX_PACKETS_PER_RECEIVE            375


typedef enum nvsp_msg_type_ {
	nvsp_msg_type_none                      = 0,

	/*
	 * Init Messages
	 */
	nvsp_msg_type_init                      = 1,
	nvsp_msg_type_init_complete             = 2,

	nvsp_version_msg_start                  = 100,

	/*
	 * Version 1 Messages
	 */
	nvsp_msg_1_type_send_ndis_vers          = nvsp_version_msg_start,

	nvsp_msg_1_type_send_rx_buf,
	nvsp_msg_1_type_send_rx_buf_complete,
	nvsp_msg_1_type_revoke_rx_buf,

	nvsp_msg_1_type_send_send_buf,
	nvsp_msg_1_type_send_send_buf_complete,
	nvsp_msg_1_type_revoke_send_buf,

	nvsp_msg_1_type_send_rndis_pkt,
	nvsp_msg_1_type_send_rndis_pkt_complete,
    
	/*
	 * Version 2 Messages
	 */
	nvsp_msg_2_type_send_chimney_delegated_buf,
	nvsp_msg_2_type_send_chimney_delegated_buf_complete,
	nvsp_msg_2_type_revoke_chimney_delegated_buf,

	nvsp_msg_2_type_resume_chimney_rx_indication,

	nvsp_msg_2_type_terminate_chimney,
	nvsp_msg_2_type_terminate_chimney_complete,

	nvsp_msg_2_type_indicate_chimney_event,

	nvsp_msg_2_type_send_chimney_packet,
	nvsp_msg_2_type_send_chimney_packet_complete,

	nvsp_msg_2_type_post_chimney_rx_request,
	nvsp_msg_2_type_post_chimney_rx_request_complete,

	nvsp_msg_2_type_alloc_rx_buf,
	nvsp_msg_2_type_alloc_rx_buf_complete,

	nvsp_msg_2_type_free_rx_buf,

	nvsp_msg_2_send_vmq_rndis_pkt,
	nvsp_msg_2_send_vmq_rndis_pkt_complete,

	nvsp_msg_2_type_send_ndis_config,

	nvsp_msg_2_type_alloc_chimney_handle,
	nvsp_msg_2_type_alloc_chimney_handle_complete,
} nvsp_msg_type;

typedef enum nvsp_status_ {
	nvsp_status_none = 0,
	nvsp_status_success,
	nvsp_status_failure,
	/* Deprecated */
	nvsp_status_prot_vers_range_too_new,
	/* Deprecated */
	nvsp_status_prot_vers_range_too_old,
	nvsp_status_invalid_rndis_pkt,
	nvsp_status_busy,
	nvsp_status_max,
} nvsp_status;

typedef struct nvsp_msg_hdr_ {
	uint32_t                                msg_type;
} __packed nvsp_msg_hdr;

/*
 * Init Messages
 */

/*
 * This message is used by the VSC to initialize the channel
 * after the channels has been opened. This message should 
 * never include anything other then versioning (i.e. this
 * message will be the same for ever).
 *
 * Forever is a long time.  The values have been redefined
 * in Win7 to indicate major and minor protocol version
 * number.
 */
typedef struct nvsp_msg_init_ {
	union {
		struct {
			uint16_t                minor_protocol_version;
			uint16_t                major_protocol_version;
		} s;
		/* Formerly min_protocol_version */
		uint32_t                        protocol_version;
	} p1;
	/* Formerly max_protocol_version */
	uint32_t                                protocol_version_2;
} __packed nvsp_msg_init;

/*
 * This message is used by the VSP to complete the initialization
 * of the channel. This message should never include anything other 
 * then versioning (i.e. this message will be the same forever).
 */
typedef struct nvsp_msg_init_complete_ {
	/* Deprecated */
	uint32_t                                negotiated_prot_vers;
	uint32_t                                max_mdl_chain_len;
	uint32_t                                status;
} __packed nvsp_msg_init_complete;

typedef union nvsp_msg_init_uber_ {
	nvsp_msg_init                           init;
	nvsp_msg_init_complete                  init_compl;
} __packed nvsp_msg_init_uber;

/*
 * Version 1 Messages
 */

/*
 * This message is used by the VSC to send the NDIS version
 * to the VSP.  The VSP can use this information when handling
 * OIDs sent by the VSC.
 */
typedef struct nvsp_1_msg_send_ndis_version_ {
	uint32_t                                ndis_major_vers;
	/* Deprecated */
	uint32_t                                ndis_minor_vers;
} __packed nvsp_1_msg_send_ndis_version;

/*
 * This message is used by the VSC to send a receive buffer
 * to the VSP. The VSP can then use the receive buffer to
 * send data to the VSC.
 */
typedef struct nvsp_1_msg_send_rx_buf_ {
	uint32_t                                gpadl_handle;
	uint16_t                                id;
} __packed nvsp_1_msg_send_rx_buf;

typedef struct nvsp_1_rx_buf_section_ {
	uint32_t                                offset;
	uint32_t                                sub_allocation_size;
	uint32_t                                num_sub_allocations;
	uint32_t                                end_offset;
} __packed nvsp_1_rx_buf_section;

/*
 * This message is used by the VSP to acknowledge a receive 
 * buffer send by the VSC.  This message must be sent by the 
 * VSP before the VSP uses the receive buffer.
 */
typedef struct nvsp_1_msg_send_rx_buf_complete_ {
	uint32_t                                status;
	uint32_t                                num_sections;

	/*
	 * The receive buffer is split into two parts, a large
	 * suballocation section and a small suballocation
	 * section. These sections are then suballocated by a 
	 * certain size.
	 *
	 * For example, the following break up of the receive
	 * buffer has 6 large suballocations and 10 small
	 * suballocations.
	 *
	 * |            Large Section          |  |   Small Section   |
	 * ------------------------------------------------------------
	 * |     |     |     |     |     |     |  | | | | | | | | | | |
	 * |                                      |  
	 * LargeOffset                            SmallOffset
	 */
	nvsp_1_rx_buf_section                   sections[1];

} __packed nvsp_1_msg_send_rx_buf_complete;

/*
 * This message is sent by the VSC to revoke the receive buffer.
 * After the VSP completes this transaction, the VSP should never
 * use the receive buffer again.
 */
typedef struct nvsp_1_msg_revoke_rx_buf_ {
	uint16_t                                id;
} __packed nvsp_1_msg_revoke_rx_buf;

/*
 * This message is used by the VSC to send a send buffer
 * to the VSP. The VSC can then use the send buffer to
 * send data to the VSP.
 */
typedef struct nvsp_1_msg_send_send_buf_ {
	uint32_t                                gpadl_handle;
	uint16_t                                id;
} __packed nvsp_1_msg_send_send_buf;

/*
 * This message is used by the VSP to acknowledge a send 
 * buffer sent by the VSC. This message must be sent by the 
 * VSP before the VSP uses the sent buffer.
 */
typedef struct nvsp_1_msg_send_send_buf_complete_ {
	uint32_t                                status;

	/*
	 * The VSC gets to choose the size of the send buffer and
	 * the VSP gets to choose the sections size of the buffer.
	 * This was done to enable dynamic reconfigurations when
	 * the cost of GPA-direct buffers decreases.
	 */
	uint32_t                                section_size;
} __packed nvsp_1_msg_send_send_buf_complete;

/*
 * This message is sent by the VSC to revoke the send buffer.
 * After the VSP completes this transaction, the vsp should never
 * use the send buffer again.
 */
typedef struct nvsp_1_msg_revoke_send_buf_ {
	uint16_t                                id;
} __packed nvsp_1_msg_revoke_send_buf;

/*
 * This message is used by both the VSP and the VSC to send
 * an RNDIS message to the opposite channel endpoint.
 */
typedef struct nvsp_1_msg_send_rndis_pkt_ {
	/*
	 * This field is specified by RNIDS.  They assume there's
	 * two different channels of communication. However, 
	 * the Network VSP only has one.  Therefore, the channel
	 * travels with the RNDIS packet.
	 */
	uint32_t                                chan_type;

	/*
	 * This field is used to send part or all of the data
	 * through a send buffer. This values specifies an 
	 * index into the send buffer.  If the index is 
	 * 0xFFFFFFFF, then the send buffer is not being used
	 * and all of the data was sent through other VMBus
	 * mechanisms.
	 */
	uint32_t                                send_buf_section_idx;
	uint32_t                                send_buf_section_size;
} __packed nvsp_1_msg_send_rndis_pkt;

/*
 * This message is used by both the VSP and the VSC to complete
 * a RNDIS message to the opposite channel endpoint.  At this
 * point, the initiator of this message cannot use any resources
 * associated with the original RNDIS packet.
 */
typedef struct nvsp_1_msg_send_rndis_pkt_complete_ {
	uint32_t                                status;
} __packed nvsp_1_msg_send_rndis_pkt_complete;


/*
 * Version 2 Messages
 */

/*
 * This message is used by the VSC to send the NDIS version
 * to the VSP.  The VSP can use this information when handling
 * OIDs sent by the VSC.
 */
typedef struct nvsp_2_netvsc_capabilities_ {
	union {
		uint64_t                        as_uint64;
		struct {
			uint64_t                vmq           : 1;
			uint64_t                chimney       : 1;
			uint64_t                sriov         : 1;
			uint64_t                ieee8021q     : 1;
			uint64_t                correlationid : 1;
			uint64_t                teaming       : 1;
		} u2;
	} u1;
} __packed nvsp_2_netvsc_capabilities;

typedef struct nvsp_2_msg_send_ndis_config_ {
	uint32_t                                mtu;
	uint32_t                                reserved;
	nvsp_2_netvsc_capabilities              capabilities;
} __packed nvsp_2_msg_send_ndis_config;

/*
 * NvspMessage2TypeSendChimneyDelegatedBuffer
 */
typedef struct nvsp_2_msg_send_chimney_buf_
{
	/*
	 * On WIN7 beta, delegated_obj_max_size is defined as a uint32_t
	 * Since WIN7 RC, it was split into two uint16_t.  To have the same
	 * struct layout, delegated_obj_max_size shall be the first field.
	 */
	uint16_t                                delegated_obj_max_size;

	/*
	 * The revision # of chimney protocol used between NVSC and NVSP.
	 *
	 * This revision is NOT related to the chimney revision between
	 * NDIS protocol and miniport drivers.
	 */
	uint16_t                                revision;

	uint32_t                                gpadl_handle;
} __packed nvsp_2_msg_send_chimney_buf;


/* Unsupported chimney revision 0 (only present in WIN7 beta) */
#define NVSP_CHIMNEY_REVISION_0                 0

/* WIN7 Beta Chimney QFE */
#define NVSP_CHIMNEY_REVISION_1                 1

/* The chimney revision since WIN7 RC */
#define NVSP_CHIMNEY_REVISION_2                 2


/*
 * NvspMessage2TypeSendChimneyDelegatedBufferComplete
 */
typedef struct nvsp_2_msg_send_chimney_buf_complete_ {
	uint32_t                                status;

	/*
	 * Maximum number outstanding sends and pre-posted receives.
	 *
	 * NVSC should not post more than SendQuota/ReceiveQuota packets.
	 * Otherwise, it can block the non-chimney path for an indefinite
	 * amount of time.
	 * (since chimney sends/receives are affected by the remote peer).
	 *
	 * Note: NVSP enforces the quota restrictions on a per-VMBCHANNEL
	 * basis.  It doesn't enforce the restriction separately for chimney
	 * send/receive.  If NVSC doesn't voluntarily enforce "SendQuota",
	 * it may kill its own network connectivity.
	 */
	uint32_t                                send_quota;
	uint32_t                                rx_quota;
} __packed nvsp_2_msg_send_chimney_buf_complete;

/*
 * NvspMessage2TypeRevokeChimneyDelegatedBuffer
 */
typedef struct nvsp_2_msg_revoke_chimney_buf_ {
	uint32_t                                gpadl_handle;
} __packed nvsp_2_msg_revoke_chimney_buf;


#define NVSP_CHIMNEY_OBJECT_TYPE_NEIGHBOR       0
#define NVSP_CHIMNEY_OBJECT_TYPE_PATH4          1
#define NVSP_CHIMNEY_OBJECT_TYPE_PATH6          2
#define NVSP_CHIMNEY_OBJECT_TYPE_TCP            3

/*
 * NvspMessage2TypeAllocateChimneyHandle
 */
typedef struct nvsp_2_msg_alloc_chimney_handle_ {
	uint64_t                                vsc_context;
	uint32_t                                object_type;
} __packed nvsp_2_msg_alloc_chimney_handle;

/*
 * NvspMessage2TypeAllocateChimneyHandleComplete
 */
typedef struct nvsp_2_msg_alloc_chimney_handle_complete_ {
	uint32_t                                vsp_handle;
} __packed nvsp_2_msg_alloc_chimney_handle_complete;


/*
 * NvspMessage2TypeResumeChimneyRXIndication
 */
typedef struct nvsp_2_msg_resume_chimney_rx_indication {
	/*
	 * Handle identifying the offloaded connection
	 */
	uint32_t                                vsp_tcp_handle;
} __packed nvsp_2_msg_resume_chimney_rx_indication;


#define NVSP_2_MSG_TERMINATE_CHIMNEY_FLAGS_FIRST_STAGE      (0x01u)
#define NVSP_2_MSG_TERMINATE_CHIMNEY_FLAGS_RESERVED         (~(0x01u))

/*
 * NvspMessage2TypeTerminateChimney
 */
typedef struct nvsp_2_msg_terminate_chimney_ {
	/*
	* Handle identifying the offloaded object
	*/
	uint32_t                                vsp_handle;

	/*
	 * Terminate Offload Flags
	 *     Bit 0:
	 *         When set to 0, terminate the offload at the destination NIC
	 *     Bit 1-31:  Reserved, shall be zero
	 */
	uint32_t                                flags;

	union {
		/*
		 * This field is valid only when bit 0 of flags is clear.
		 * It specifies the index into the premapped delegated
		 * object buffer.  The buffer was sent through the
		 * NvspMessage2TypeSendChimneyDelegatedBuffer
		 * message at initialization time.
		 *
		 * NVSP will write the delegated state into the delegated
		 * buffer upon upload completion.
		 */
		uint32_t                        index;

		/*
		 * This field is valid only when bit 0 of flags is set.
		 *
		 * The seqence number of the most recently accepted RX
		 * indication when VSC sets its TCP context into
		 * "terminating" state.
		 *
		 * This allows NVSP to determines if there are any in-flight
		 * RX indications for which the acceptance state is still
		 * undefined.
		 */
		uint64_t                        last_accepted_rx_seq_no;
	} f0;
} __packed nvsp_2_msg_terminate_chimney;


#define NVSP_TERMINATE_CHIMNEY_COMPLETE_FLAG_DATA_CORRUPTED     0x0000001u

/*
 * NvspMessage2TypeTerminateChimneyComplete
 */
typedef struct nvsp_2_msg_terminate_chimney_complete_ {
	uint64_t                                vsc_context;
	uint32_t                                flags;
} __packed nvsp_2_msg_terminate_chimney_complete;

/*
 * NvspMessage2TypeIndicateChimneyEvent
 */
typedef struct nvsp_2_msg_indicate_chimney_event_ {
	/*
	 * When VscTcpContext is 0, event_type is an NDIS_STATUS event code
	 * Otherwise, EventType is an TCP connection event (defined in
	 * NdisTcpOffloadEventHandler chimney DDK document).
	 */
	uint32_t                                event_type;

	/*
	 * When VscTcpContext is 0, EventType is an NDIS_STATUS event code
	 * Otherwise, EventType is an TCP connection event specific information
	 * (defined in NdisTcpOffloadEventHandler chimney DDK document).
	 */
	uint32_t                                event_specific_info;

	/*
	 * If not 0, the event is per-TCP connection event.  This field
	 * contains the VSC's TCP context.
	 * If 0, the event indication is global.
	 */
	uint64_t                                vsc_tcp_context;
} __packed nvsp_2_msg_indicate_chimney_event;


#define NVSP_1_CHIMNEY_SEND_INVALID_OOB_INDEX       0xffffu
#define NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX   0xffffu

/*
 * NvspMessage2TypeSendChimneyPacket
 */
typedef struct nvsp_2_msg_send_chimney_pkt_ {
    /*
     * Identify the TCP connection for which this chimney send is
     */
    uint32_t                                    vsp_tcp_handle;

    /*
     * This field is used to send part or all of the data
     * through a send buffer. This values specifies an
     * index into the send buffer. If the index is
     * 0xFFFF, then the send buffer is not being used
     * and all of the data was sent through other VMBus
     * mechanisms.
     */
    uint16_t                                    send_buf_section_index;
    uint16_t                                    send_buf_section_size;

    /*
     * OOB Data Index
     * This an index to the OOB data buffer. If the index is 0xFFFFFFFF,
     * then there is no OOB data.
     *
     * This field shall be always 0xFFFFFFFF for now. It is reserved for
     * the future.
     */
    uint16_t                                    oob_data_index;

    /*
     * DisconnectFlags = 0
     *      Normal chimney send. See MiniportTcpOffloadSend for details.
     *
     * DisconnectFlags = TCP_DISCONNECT_GRACEFUL_CLOSE (0x01)
     *      Graceful disconnect. See MiniportTcpOffloadDisconnect for details.
     *
     * DisconnectFlags = TCP_DISCONNECT_ABORTIVE_CLOSE (0x02)
     *      Abortive disconnect. See MiniportTcpOffloadDisconnect for details.
     */
    uint16_t                                    disconnect_flags;

    uint32_t                                    seq_no;
} __packed nvsp_2_msg_send_chimney_pkt;

/*
 * NvspMessage2TypeSendChimneyPacketComplete
 */
typedef struct nvsp_2_msg_send_chimney_pkt_complete_ {
    /*
     * The NDIS_STATUS for the chimney send
     */
    uint32_t                                    status;

    /*
     * Number of bytes that have been sent to the peer (and ACKed by the peer).
     */
    uint32_t                                    bytes_transferred;
} __packed nvsp_2_msg_send_chimney_pkt_complete;


#define NVSP_1_CHIMNEY_RECV_FLAG_NO_PUSH        0x0001u
#define NVSP_1_CHIMNEY_RECV_INVALID_OOB_INDEX   0xffffu

/*
 * NvspMessage2TypePostChimneyRecvRequest
 */
typedef struct nvsp_2_msg_post_chimney_rx_request_ {
	/*
	 * Identify the TCP connection which this chimney receive request
	 * is for.
	 */
	uint32_t                                vsp_tcp_handle;

	/*
	 * OOB Data Index
	 * This an index to the OOB data buffer. If the index is 0xFFFFFFFF,
	 * then there is no OOB data.
	 *
	 * This field shall be always 0xFFFFFFFF for now. It is reserved for
	 * the future.
	 */
	uint32_t                                oob_data_index;

	/*
	 * Bit 0
	 *      When it is set, this is a "no-push" receive.
	 *      When it is clear, this is a "push" receive.
	 *
	 * Bit 1-15:  Reserved and shall be zero
	 */
	uint16_t                                flags;

	/*
	 * For debugging and diagnoses purpose.
	 * The SeqNo is per TCP connection and starts from 0.
	 */
	uint32_t                                seq_no;
} __packed nvsp_2_msg_post_chimney_rx_request;

/*
 * NvspMessage2TypePostChimneyRecvRequestComplete
 */
typedef struct nvsp_2_msg_post_chimney_rx_request_complete_ {
	/*
	 * The NDIS_STATUS for the chimney send
	 */
	uint32_t                                status;

	/*
	 * Number of bytes that have been sent to the peer (and ACKed by
	 * the peer).
	 */
	uint32_t                                bytes_xferred;
} __packed nvsp_2_msg_post_chimney_rx_request_complete;

/*
 * NvspMessage2TypeAllocateReceiveBuffer
 */
typedef struct nvsp_2_msg_alloc_rx_buf_ {
	/*
	 * Allocation ID to match the allocation request and response
	 */
	uint32_t                                allocation_id;

	/*
	 * Length of the VM shared memory receive buffer that needs to
	 * be allocated
	 */
	uint32_t                                length;
} __packed nvsp_2_msg_alloc_rx_buf;

/*
 * NvspMessage2TypeAllocateReceiveBufferComplete
 */
typedef struct nvsp_2_msg_alloc_rx_buf_complete_ {
	/*
	 * The NDIS_STATUS code for buffer allocation
	 */
	uint32_t                                status;

	/*
	 * Allocation ID from NVSP_2_MESSAGE_ALLOCATE_RECEIVE_BUFFER
	 */
	uint32_t                                allocation_id;

	/*
	 * GPADL handle for the allocated receive buffer
	 */
	uint32_t                                gpadl_handle;

	/*
	 * Receive buffer ID that is further used in
	 * NvspMessage2SendVmqRndisPacket
	 */
	uint64_t                                rx_buf_id;
} __packed nvsp_2_msg_alloc_rx_buf_complete;

/*
 * NvspMessage2TypeFreeReceiveBuffer
 */
typedef struct nvsp_2_msg_free_rx_buf_ {
	/*
	 * Receive buffer ID previous returned in
	 * NvspMessage2TypeAllocateReceiveBufferComplete message
	 */
	uint64_t                                rx_buf_id;
} __packed nvsp_2_msg_free_rx_buf;

/*
 * This structure is used in defining the buffers in
 * NVSP_2_MESSAGE_SEND_VMQ_RNDIS_PACKET structure
 */
typedef struct nvsp_xfer_page_range_ {
	/*
	 * Specifies the ID of the receive buffer that has the buffer. This
	 * ID can be the general receive buffer ID specified in
	 * NvspMessage1TypeSendReceiveBuffer or it can be the shared memory
	 * receive buffer ID allocated by the VSC and specified in
	 * NvspMessage2TypeAllocateReceiveBufferComplete message
	 */
	uint64_t                                xfer_page_set_id;

	/*
	 * Number of bytes
	 */
	uint32_t                                byte_count;

	/*
	 * Offset in bytes from the beginning of the buffer
	 */
	uint32_t                                byte_offset;
} __packed nvsp_xfer_page_range;

/*
 * NvspMessage2SendVmqRndisPacket
 */
typedef struct nvsp_2_msg_send_vmq_rndis_pkt_ {
	/*
	 * This field is specified by RNIDS. They assume there's
	 * two different channels of communication. However,
	 * the Network VSP only has one. Therefore, the channel
	 * travels with the RNDIS packet. It must be RMC_DATA
	 */
	uint32_t                                channel_type;

	/*
	 * Only the Range element corresponding to the RNDIS header of
	 * the first RNDIS message in the multiple RNDIS messages sent
	 * in one NVSP message.  Information about the data portions as well
	 * as the subsequent RNDIS messages in the same NVSP message are
	 * embedded in the RNDIS header itself
	 */
	nvsp_xfer_page_range                    range;
} __packed nvsp_2_msg_send_vmq_rndis_pkt;

/*
 * This message is used by the VSC to complete
 * a RNDIS VMQ message to the VSP.  At this point,
 * the initiator of this message can use any resources
 * associated with the original RNDIS VMQ packet.
 */
typedef struct nvsp_2_msg_send_vmq_rndis_pkt_complete_
{
	uint32_t                                status;
} __packed nvsp_2_msg_send_vmq_rndis_pkt_complete;


typedef union nvsp_1_msg_uber_ {
	nvsp_1_msg_send_ndis_version            send_ndis_vers;

	nvsp_1_msg_send_rx_buf                  send_rx_buf;
	nvsp_1_msg_send_rx_buf_complete         send_rx_buf_complete;
	nvsp_1_msg_revoke_rx_buf                revoke_rx_buf;

	nvsp_1_msg_send_send_buf                send_send_buf;
	nvsp_1_msg_send_send_buf_complete       send_send_buf_complete;
	nvsp_1_msg_revoke_send_buf              revoke_send_buf;

	nvsp_1_msg_send_rndis_pkt               send_rndis_pkt;
	nvsp_1_msg_send_rndis_pkt_complete      send_rndis_pkt_complete;
} __packed nvsp_1_msg_uber;


typedef union nvsp_2_msg_uber_ {
	nvsp_2_msg_send_ndis_config             send_ndis_config;

	nvsp_2_msg_send_chimney_buf             send_chimney_buf;
	nvsp_2_msg_send_chimney_buf_complete    send_chimney_buf_complete;
	nvsp_2_msg_revoke_chimney_buf           revoke_chimney_buf;

	nvsp_2_msg_resume_chimney_rx_indication resume_chimney_rx_indication;
	nvsp_2_msg_terminate_chimney            terminate_chimney;
	nvsp_2_msg_terminate_chimney_complete   terminate_chimney_complete;
	nvsp_2_msg_indicate_chimney_event       indicate_chimney_event;

	nvsp_2_msg_send_chimney_pkt             send_chimney_packet;
	nvsp_2_msg_send_chimney_pkt_complete    send_chimney_packet_complete;
	nvsp_2_msg_post_chimney_rx_request      post_chimney_rx_request;
	nvsp_2_msg_post_chimney_rx_request_complete
	                                       post_chimney_rx_request_complete;

	nvsp_2_msg_alloc_rx_buf                 alloc_rx_buffer;
	nvsp_2_msg_alloc_rx_buf_complete        alloc_rx_buffer_complete;
	nvsp_2_msg_free_rx_buf                  free_rx_buffer;

	nvsp_2_msg_send_vmq_rndis_pkt           send_vmq_rndis_pkt;
	nvsp_2_msg_send_vmq_rndis_pkt_complete  send_vmq_rndis_pkt_complete;
	nvsp_2_msg_alloc_chimney_handle         alloc_chimney_handle;
	nvsp_2_msg_alloc_chimney_handle_complete alloc_chimney_handle_complete;
} __packed nvsp_2_msg_uber;


typedef union nvsp_all_msgs_ {
	nvsp_msg_init_uber                      init_msgs;
	nvsp_1_msg_uber                         vers_1_msgs;
	nvsp_2_msg_uber                         vers_2_msgs;
} __packed nvsp_all_msgs;

/*
 * ALL Messages
 */
typedef struct nvsp_msg_ {
	nvsp_msg_hdr                            hdr; 
	nvsp_all_msgs                           msgs;
} __packed nvsp_msg;


/*
 * The following arguably belongs in a separate header file
 */

/*
 * Defines
 */

#define NETVSC_SEND_BUFFER_SIZE			(64*1024)   /* 64K */
#define NETVSC_SEND_BUFFER_ID			0xface


#define NETVSC_RECEIVE_BUFFER_SIZE		(1024*1024) /* 1MB */

#define NETVSC_RECEIVE_BUFFER_ID		0xcafe

#define NETVSC_RECEIVE_SG_COUNT			1

/* Preallocated receive packets */
#define NETVSC_RECEIVE_PACKETLIST_COUNT		256

/*
 * Maximum MTU we permit to be configured for a netvsc interface.
 * When the code was developed, a max MTU of 12232 was tested and
 * proven to work.  9K is a reasonable maximum for an Ethernet.
 */
#define NETVSC_MAX_CONFIGURABLE_MTU		(9 * 1024)

/*
 * Data types
 */

/*
 * Per netvsc channel-specific
 */
typedef struct netvsc_dev_ {
	struct hv_device			*dev;
	int					num_outstanding_sends;

	/* List of free preallocated NETVSC_PACKET to represent RX packet */
	STAILQ_HEAD(PQ, netvsc_packet_)		myrx_packet_list;
	struct mtx				rx_pkt_list_lock;

	/* Send buffer allocated by us but manages by NetVSP */
	void					*send_buf;
	uint32_t				send_buf_size;
	uint32_t				send_buf_gpadl_handle;
	uint32_t				send_section_size;

	/* Receive buffer allocated by us but managed by NetVSP */
	void					*rx_buf;
	uint32_t				rx_buf_size;
	uint32_t				rx_buf_gpadl_handle;
	uint32_t				rx_section_count;
	nvsp_1_rx_buf_section			*rx_sections;

	/* Used for NetVSP initialization protocol */
	struct sema				channel_init_sema;
	nvsp_msg				channel_init_packet;

	nvsp_msg				revoke_packet;
	/*uint8_t				hw_mac_addr[HW_MACADDR_LEN];*/

	/* Holds rndis device info */
	void					*extension;

	hv_bool_uint8_t				destroy;
	/* Negotiated NVSP version */
	uint32_t				nvsp_version;
} netvsc_dev;


typedef void (*pfn_on_send_rx_completion)(void *);

#define NETVSC_DEVICE_RING_BUFFER_SIZE   (64 * PAGE_SIZE)
#define NETVSC_PACKET_MAXPAGE            16


typedef struct xfer_page_packet_ {
	/*
	 * This needs to be here because the network RX code casts
	 * an instantiation of this structure to a netvsc_packet.
	 */
	STAILQ_ENTRY(netvsc_packet_) mylist_entry;

	uint32_t count;
} xfer_page_packet;

typedef struct netvsc_packet_ {
	/*
	 * List used when enqueued on &net_dev->rx_packet_list,
	 * and when enqueued within the netvsc code
	 */
	STAILQ_ENTRY(netvsc_packet_) mylist_entry;
	struct hv_device           *device;
	hv_bool_uint8_t            is_data_pkt;      /* One byte */
	uint16_t		   vlan_tci;
	xfer_page_packet           *xfer_page_pkt;

	/* Completion */
	union {
		struct {
			uint64_t   rx_completion_tid;
			void	   *rx_completion_context;
			/* This is no longer used */
			pfn_on_send_rx_completion   on_rx_completion;
		} rx;
		struct {
			uint64_t    send_completion_tid;
			void	    *send_completion_context;
			/* Still used in netvsc and filter code */
			pfn_on_send_rx_completion   on_send_completion;
		} send;
	} compl;

	void		*extension;
	uint32_t	tot_data_buf_len;
	uint32_t	page_buf_count;
	hv_vmbus_page_buffer	page_buffers[NETVSC_PACKET_MAXPAGE];
} netvsc_packet;

typedef struct {
	uint8_t		mac_addr[6];  /* Assumption unsigned long */
	hv_bool_uint8_t	link_state;
} netvsc_device_info;

/*
 * Device-specific softc structure
 */
typedef struct hn_softc {
	struct ifnet    *hn_ifp;
	struct arpcom   arpcom;
	device_t        hn_dev;
	uint8_t         hn_unit;
	int             hn_carrier;
	int             hn_if_flags;
	struct mtx      hn_lock;
	int             hn_initdone;
	struct hv_device  *hn_dev_obj;
	netvsc_dev  	*net_dev;
} hn_softc_t;


/*
 * Externs
 */
extern int hv_promisc_mode;

extern void netvsc_linkstatus_callback(struct hv_device *device_obj,
				       uint32_t status);
extern int  netvsc_recv(struct hv_device *device_obj, netvsc_packet *packet);
extern void netvsc_xmit_completion(void *context);

extern void hv_nv_on_receive_completion(void *context);
extern netvsc_dev *hv_nv_on_device_add(struct hv_device *device, void *additional_info);
extern int  hv_nv_on_device_remove(struct hv_device *device,
				   boolean_t destroy_channel);
extern int  hv_nv_on_send(struct hv_device *device, netvsc_packet *pkt);

#endif  /* __HV_NET_VSC_H__ */

OpenPOWER on IntegriCloud