21
21
#include <net/rtnetlink.h>
22
22
#include <net/sock.h>
23
23
#include <linux/virtio_net.h>
24
+ #include <linux/skb_array.h>
24
25
25
26
/*
26
27
* A macvtap queue is the central object of this driver, it connects
@@ -43,6 +44,7 @@ struct macvtap_queue {
43
44
u16 queue_index ;
44
45
bool enabled ;
45
46
struct list_head next ;
47
+ struct skb_array skb_array ;
46
48
};
47
49
48
50
#define MACVTAP_FEATURES (IFF_VNET_HDR | IFF_MULTI_QUEUE)
@@ -273,6 +275,7 @@ static void macvtap_put_queue(struct macvtap_queue *q)
273
275
rtnl_unlock ();
274
276
275
277
synchronize_rcu ();
278
+ skb_array_cleanup (& q -> skb_array );
276
279
sock_put (& q -> sk );
277
280
}
278
281
@@ -366,7 +369,7 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
366
369
if (!q )
367
370
return RX_HANDLER_PASS ;
368
371
369
- if (skb_queue_len (& q -> sk . sk_receive_queue ) >= dev -> tx_queue_len )
372
+ if (__skb_array_full (& q -> skb_array ) )
370
373
goto drop ;
371
374
372
375
skb_push (skb , ETH_HLEN );
@@ -384,7 +387,8 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
384
387
goto drop ;
385
388
386
389
if (!segs ) {
387
- skb_queue_tail (& q -> sk .sk_receive_queue , skb );
390
+ if (skb_array_produce (& q -> skb_array , skb ))
391
+ goto drop ;
388
392
goto wake_up ;
389
393
}
390
394
@@ -393,7 +397,11 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
393
397
struct sk_buff * nskb = segs -> next ;
394
398
395
399
segs -> next = NULL ;
396
- skb_queue_tail (& q -> sk .sk_receive_queue , segs );
400
+ if (skb_array_produce (& q -> skb_array , segs )) {
401
+ kfree_skb (segs );
402
+ kfree_skb_list (nskb );
403
+ break ;
404
+ }
397
405
segs = nskb ;
398
406
}
399
407
} else {
@@ -406,7 +414,8 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
406
414
!(features & NETIF_F_CSUM_MASK ) &&
407
415
skb_checksum_help (skb ))
408
416
goto drop ;
409
- skb_queue_tail (& q -> sk .sk_receive_queue , skb );
417
+ if (skb_array_produce (& q -> skb_array , skb ))
418
+ goto drop ;
410
419
}
411
420
412
421
wake_up :
@@ -523,7 +532,11 @@ static void macvtap_sock_write_space(struct sock *sk)
523
532
524
533
static void macvtap_sock_destruct (struct sock * sk )
525
534
{
526
- skb_queue_purge (& sk -> sk_receive_queue );
535
+ struct macvtap_queue * q = container_of (sk , struct macvtap_queue , sk );
536
+ struct sk_buff * skb ;
537
+
538
+ while ((skb = skb_array_consume (& q -> skb_array )) != NULL )
539
+ kfree (skb );
527
540
}
528
541
529
542
static int macvtap_open (struct inode * inode , struct file * file )
@@ -536,13 +549,13 @@ static int macvtap_open(struct inode *inode, struct file *file)
536
549
rtnl_lock ();
537
550
dev = dev_get_by_macvtap_minor (iminor (inode ));
538
551
if (!dev )
539
- goto out ;
552
+ goto err ;
540
553
541
554
err = - ENOMEM ;
542
555
q = (struct macvtap_queue * )sk_alloc (net , AF_UNSPEC , GFP_KERNEL ,
543
556
& macvtap_proto , 0 );
544
557
if (!q )
545
- goto out ;
558
+ goto err ;
546
559
547
560
RCU_INIT_POINTER (q -> sock .wq , & q -> wq );
548
561
init_waitqueue_head (& q -> wq .wait );
@@ -566,11 +579,24 @@ static int macvtap_open(struct inode *inode, struct file *file)
566
579
if ((dev -> features & NETIF_F_HIGHDMA ) && (dev -> features & NETIF_F_SG ))
567
580
sock_set_flag (& q -> sk , SOCK_ZEROCOPY );
568
581
582
+ err = - ENOMEM ;
583
+ if (skb_array_init (& q -> skb_array , dev -> tx_queue_len , GFP_KERNEL ))
584
+ goto err_array ;
585
+
569
586
err = macvtap_set_queue (dev , file , q );
570
587
if (err )
571
- sock_put ( & q -> sk ) ;
588
+ goto err_queue ;
572
589
573
- out :
590
+ dev_put (dev );
591
+
592
+ rtnl_unlock ();
593
+ return err ;
594
+
595
+ err_queue :
596
+ skb_array_cleanup (& q -> skb_array );
597
+ err_array :
598
+ sock_put (& q -> sk );
599
+ err :
574
600
if (dev )
575
601
dev_put (dev );
576
602
@@ -596,7 +622,7 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait)
596
622
mask = 0 ;
597
623
poll_wait (file , & q -> wq .wait , wait );
598
624
599
- if (!skb_queue_empty (& q -> sk . sk_receive_queue ))
625
+ if (!skb_array_empty (& q -> skb_array ))
600
626
mask |= POLLIN | POLLRDNORM ;
601
627
602
628
if (sock_writeable (& q -> sk ) ||
@@ -856,7 +882,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q,
856
882
TASK_INTERRUPTIBLE );
857
883
858
884
/* Read frames from the queue */
859
- skb = skb_dequeue (& q -> sk . sk_receive_queue );
885
+ skb = skb_array_consume (& q -> skb_array );
860
886
if (skb )
861
887
break ;
862
888
if (noblock ) {
@@ -1180,10 +1206,18 @@ static int macvtap_recvmsg(struct socket *sock, struct msghdr *m,
1180
1206
return ret ;
1181
1207
}
1182
1208
1209
+ static int macvtap_peek_len (struct socket * sock )
1210
+ {
1211
+ struct macvtap_queue * q = container_of (sock , struct macvtap_queue ,
1212
+ sock );
1213
+ return skb_array_peek_len (& q -> skb_array );
1214
+ }
1215
+
1183
1216
/* Ops structure to mimic raw sockets with tun */
1184
1217
static const struct proto_ops macvtap_socket_ops = {
1185
1218
.sendmsg = macvtap_sendmsg ,
1186
1219
.recvmsg = macvtap_recvmsg ,
1220
+ .peek_len = macvtap_peek_len ,
1187
1221
};
1188
1222
1189
1223
/* Get an underlying socket object from tun file. Returns error unless file is
@@ -1202,6 +1236,28 @@ struct socket *macvtap_get_socket(struct file *file)
1202
1236
}
1203
1237
EXPORT_SYMBOL_GPL (macvtap_get_socket );
1204
1238
1239
+ static int macvtap_queue_resize (struct macvlan_dev * vlan )
1240
+ {
1241
+ struct net_device * dev = vlan -> dev ;
1242
+ struct macvtap_queue * q ;
1243
+ struct skb_array * * arrays ;
1244
+ int n = vlan -> numqueues ;
1245
+ int ret , i = 0 ;
1246
+
1247
+ arrays = kmalloc (sizeof * arrays * n , GFP_KERNEL );
1248
+ if (!arrays )
1249
+ return - ENOMEM ;
1250
+
1251
+ list_for_each_entry (q , & vlan -> queue_list , next )
1252
+ arrays [i ++ ] = & q -> skb_array ;
1253
+
1254
+ ret = skb_array_resize_multiple (arrays , n ,
1255
+ dev -> tx_queue_len , GFP_KERNEL );
1256
+
1257
+ kfree (arrays );
1258
+ return ret ;
1259
+ }
1260
+
1205
1261
static int macvtap_device_event (struct notifier_block * unused ,
1206
1262
unsigned long event , void * ptr )
1207
1263
{
@@ -1249,6 +1305,10 @@ static int macvtap_device_event(struct notifier_block *unused,
1249
1305
device_destroy (& macvtap_class , devt );
1250
1306
macvtap_free_minor (vlan );
1251
1307
break ;
1308
+ case NETDEV_CHANGE_TX_QUEUE_LEN :
1309
+ if (macvtap_queue_resize (vlan ))
1310
+ return NOTIFY_BAD ;
1311
+ break ;
1252
1312
}
1253
1313
1254
1314
return NOTIFY_DONE ;
0 commit comments