74
74
(1ULL << VHOST_NET_F_VIRTIO_NET_HDR ) |
75
75
(1ULL << VIRTIO_NET_F_MRG_RXBUF ) |
76
76
(1ULL << VIRTIO_F_ACCESS_PLATFORM ) |
77
- (1ULL << VIRTIO_F_RING_RESET )
77
+ (1ULL << VIRTIO_F_RING_RESET ) |
78
+ (1ULL << VIRTIO_F_IN_ORDER )
78
79
};
79
80
80
81
enum {
@@ -450,16 +451,17 @@ static int vhost_net_enable_vq(struct vhost_net *n,
450
451
return vhost_poll_start (poll , sock -> file );
451
452
}
452
453
453
- static void vhost_net_signal_used (struct vhost_net_virtqueue * nvq )
454
+ static void vhost_net_signal_used (struct vhost_net_virtqueue * nvq ,
455
+ unsigned int count )
454
456
{
455
457
struct vhost_virtqueue * vq = & nvq -> vq ;
456
458
struct vhost_dev * dev = vq -> dev ;
457
459
458
460
if (!nvq -> done_idx )
459
461
return ;
460
462
461
- vhost_add_used_and_signal_n (dev , vq , vq -> heads , NULL ,
462
- nvq -> done_idx );
463
+ vhost_add_used_and_signal_n (dev , vq , vq -> heads ,
464
+ vq -> nheads , count );
463
465
nvq -> done_idx = 0 ;
464
466
}
465
467
@@ -468,13 +470,20 @@ static void vhost_tx_batch(struct vhost_net *net,
468
470
struct socket * sock ,
469
471
struct msghdr * msghdr )
470
472
{
473
+ struct vhost_virtqueue * vq = & nvq -> vq ;
474
+ bool in_order = vhost_has_feature (vq , VIRTIO_F_IN_ORDER );
471
475
struct tun_msg_ctl ctl = {
472
476
.type = TUN_MSG_PTR ,
473
477
.num = nvq -> batched_xdp ,
474
478
.ptr = nvq -> xdp ,
475
479
};
476
480
int i , err ;
477
481
482
+ if (in_order ) {
483
+ vq -> heads [0 ].len = 0 ;
484
+ vq -> nheads [0 ] = nvq -> done_idx ;
485
+ }
486
+
478
487
if (nvq -> batched_xdp == 0 )
479
488
goto signal_used ;
480
489
@@ -496,7 +505,7 @@ static void vhost_tx_batch(struct vhost_net *net,
496
505
}
497
506
498
507
signal_used :
499
- vhost_net_signal_used (nvq );
508
+ vhost_net_signal_used (nvq , in_order ? 1 : nvq -> done_idx );
500
509
nvq -> batched_xdp = 0 ;
501
510
}
502
511
@@ -758,6 +767,7 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock)
758
767
int sent_pkts = 0 ;
759
768
bool sock_can_batch = (sock -> sk -> sk_sndbuf == INT_MAX );
760
769
bool busyloop_intr ;
770
+ bool in_order = vhost_has_feature (vq , VIRTIO_F_IN_ORDER );
761
771
762
772
do {
763
773
busyloop_intr = false;
@@ -794,11 +804,13 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock)
794
804
break ;
795
805
}
796
806
797
- /* We can't build XDP buff, go for single
798
- * packet path but let's flush batched
799
- * packets.
800
- */
801
- vhost_tx_batch (net , nvq , sock , & msg );
807
+ if (nvq -> batched_xdp ) {
808
+ /* We can't build XDP buff, go for single
809
+ * packet path but let's flush batched
810
+ * packets.
811
+ */
812
+ vhost_tx_batch (net , nvq , sock , & msg );
813
+ }
802
814
msg .msg_control = NULL ;
803
815
} else {
804
816
if (tx_can_batch (vq , total_len ))
@@ -819,8 +831,12 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock)
819
831
pr_debug ("Truncated TX packet: len %d != %zd\n" ,
820
832
err , len );
821
833
done :
822
- vq -> heads [nvq -> done_idx ].id = cpu_to_vhost32 (vq , head );
823
- vq -> heads [nvq -> done_idx ].len = 0 ;
834
+ if (in_order ) {
835
+ vq -> heads [0 ].id = cpu_to_vhost32 (vq , head );
836
+ } else {
837
+ vq -> heads [nvq -> done_idx ].id = cpu_to_vhost32 (vq , head );
838
+ vq -> heads [nvq -> done_idx ].len = 0 ;
839
+ }
824
840
++ nvq -> done_idx ;
825
841
} while (likely (!vhost_exceeds_weight (vq , ++ sent_pkts , total_len )));
826
842
@@ -999,7 +1015,7 @@ static int peek_head_len(struct vhost_net_virtqueue *rvq, struct sock *sk)
999
1015
}
1000
1016
1001
1017
static int vhost_net_rx_peek_head_len (struct vhost_net * net , struct sock * sk ,
1002
- bool * busyloop_intr )
1018
+ bool * busyloop_intr , unsigned int count )
1003
1019
{
1004
1020
struct vhost_net_virtqueue * rnvq = & net -> vqs [VHOST_NET_VQ_RX ];
1005
1021
struct vhost_net_virtqueue * tnvq = & net -> vqs [VHOST_NET_VQ_TX ];
@@ -1009,7 +1025,7 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
1009
1025
1010
1026
if (!len && rvq -> busyloop_timeout ) {
1011
1027
/* Flush batched heads first */
1012
- vhost_net_signal_used (rnvq );
1028
+ vhost_net_signal_used (rnvq , count );
1013
1029
/* Both tx vq and rx socket were polled here */
1014
1030
vhost_net_busy_poll (net , rvq , tvq , busyloop_intr , true);
1015
1031
@@ -1021,22 +1037,25 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
1021
1037
1022
1038
/* This is a multi-buffer version of vhost_get_desc, that works if
1023
1039
* vq has read descriptors only.
1024
- * @vq - the relevant virtqueue
1040
+ * @nvq - the relevant vhost_net virtqueue
1025
1041
* @datalen - data length we'll be reading
1026
1042
* @iovcount - returned count of io vectors we fill
1027
1043
* @log - vhost log
1028
1044
* @log_num - log offset
1029
1045
* @quota - headcount quota, 1 for big buffer
1030
1046
* returns number of buffer heads allocated, negative on error
1031
1047
*/
1032
- static int get_rx_bufs (struct vhost_virtqueue * vq ,
1048
+ static int get_rx_bufs (struct vhost_net_virtqueue * nvq ,
1033
1049
struct vring_used_elem * heads ,
1050
+ u16 * nheads ,
1034
1051
int datalen ,
1035
1052
unsigned * iovcount ,
1036
1053
struct vhost_log * log ,
1037
1054
unsigned * log_num ,
1038
1055
unsigned int quota )
1039
1056
{
1057
+ struct vhost_virtqueue * vq = & nvq -> vq ;
1058
+ bool in_order = vhost_has_feature (vq , VIRTIO_F_IN_ORDER );
1040
1059
unsigned int out , in ;
1041
1060
int seg = 0 ;
1042
1061
int headcount = 0 ;
@@ -1073,14 +1092,16 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
1073
1092
nlogs += * log_num ;
1074
1093
log += * log_num ;
1075
1094
}
1076
- heads [headcount ].id = cpu_to_vhost32 (vq , d );
1077
1095
len = iov_length (vq -> iov + seg , in );
1078
- heads [headcount ].len = cpu_to_vhost32 (vq , len );
1079
- datalen -= len ;
1096
+ if (!in_order ) {
1097
+ heads [headcount ].id = cpu_to_vhost32 (vq , d );
1098
+ heads [headcount ].len = cpu_to_vhost32 (vq , len );
1099
+ }
1080
1100
++ headcount ;
1101
+ datalen -= len ;
1081
1102
seg += in ;
1082
1103
}
1083
- heads [ headcount - 1 ]. len = cpu_to_vhost32 ( vq , len + datalen );
1104
+
1084
1105
* iovcount = seg ;
1085
1106
if (unlikely (log ))
1086
1107
* log_num = nlogs ;
@@ -1090,6 +1111,15 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
1090
1111
r = UIO_MAXIOV + 1 ;
1091
1112
goto err ;
1092
1113
}
1114
+
1115
+ if (!in_order )
1116
+ heads [headcount - 1 ].len = cpu_to_vhost32 (vq , len + datalen );
1117
+ else {
1118
+ heads [0 ].len = cpu_to_vhost32 (vq , len + datalen );
1119
+ heads [0 ].id = cpu_to_vhost32 (vq , d );
1120
+ nheads [0 ] = headcount ;
1121
+ }
1122
+
1093
1123
return headcount ;
1094
1124
err :
1095
1125
vhost_discard_vq_desc (vq , headcount );
@@ -1102,6 +1132,8 @@ static void handle_rx(struct vhost_net *net)
1102
1132
{
1103
1133
struct vhost_net_virtqueue * nvq = & net -> vqs [VHOST_NET_VQ_RX ];
1104
1134
struct vhost_virtqueue * vq = & nvq -> vq ;
1135
+ bool in_order = vhost_has_feature (vq , VIRTIO_F_IN_ORDER );
1136
+ unsigned int count = 0 ;
1105
1137
unsigned in , log ;
1106
1138
struct vhost_log * vq_log ;
1107
1139
struct msghdr msg = {
@@ -1149,12 +1181,13 @@ static void handle_rx(struct vhost_net *net)
1149
1181
1150
1182
do {
1151
1183
sock_len = vhost_net_rx_peek_head_len (net , sock -> sk ,
1152
- & busyloop_intr );
1184
+ & busyloop_intr , count );
1153
1185
if (!sock_len )
1154
1186
break ;
1155
1187
sock_len += sock_hlen ;
1156
1188
vhost_len = sock_len + vhost_hlen ;
1157
- headcount = get_rx_bufs (vq , vq -> heads + nvq -> done_idx ,
1189
+ headcount = get_rx_bufs (nvq , vq -> heads + count ,
1190
+ vq -> nheads + count ,
1158
1191
vhost_len , & in , vq_log , & log ,
1159
1192
likely (mergeable ) ? UIO_MAXIOV : 1 );
1160
1193
/* On error, stop handling until the next kick. */
@@ -1230,8 +1263,11 @@ static void handle_rx(struct vhost_net *net)
1230
1263
goto out ;
1231
1264
}
1232
1265
nvq -> done_idx += headcount ;
1233
- if (nvq -> done_idx > VHOST_NET_BATCH )
1234
- vhost_net_signal_used (nvq );
1266
+ count += in_order ? 1 : headcount ;
1267
+ if (nvq -> done_idx > VHOST_NET_BATCH ) {
1268
+ vhost_net_signal_used (nvq , count );
1269
+ count = 0 ;
1270
+ }
1235
1271
if (unlikely (vq_log ))
1236
1272
vhost_log_write (vq , vq_log , log , vhost_len ,
1237
1273
vq -> iov , in );
@@ -1243,7 +1279,7 @@ static void handle_rx(struct vhost_net *net)
1243
1279
else if (!sock_len )
1244
1280
vhost_net_enable_vq (net , vq );
1245
1281
out :
1246
- vhost_net_signal_used (nvq );
1282
+ vhost_net_signal_used (nvq , count );
1247
1283
mutex_unlock (& vq -> mutex );
1248
1284
}
1249
1285
0 commit comments