Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755356Ab0LOUOb (ORCPT ); Wed, 15 Dec 2010 15:14:31 -0500 Received: from mga14.intel.com ([143.182.124.37]:19635 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755094Ab0LOUOK (ORCPT ); Wed, 15 Dec 2010 15:14:10 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.59,350,1288594800"; d="scan'208";a="362217865" From: "Fenghua Yu" To: "David S. Miller" , "Eric Dumazet" , "John Fastabend" , "Xinan Tang" , "Junchang Wang" Cc: "netdev" , "linux-kernel" , Fenghua Yu , Junchang Wang , Xinan Tang Subject: [PATCH 2/3] net/packet/af_packet.c: implement multiqueue aware socket in af_apcket Date: Wed, 15 Dec 2010 12:02:05 -0800 Message-Id: <8c24157203309f2ccb56fd8cdbc8fc648ae46e26.1292405004.git.fenghua.yu@intel.com> X-Mailer: git-send-email 1.7.2 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4803 Lines: 180 From: Fenghua Yu This patch implements multiqueue aware socket interfaces in af_packet. The interfaces are: 1. ioctl(int sockfd, int SIOSTXQUEUEMAPPING, int *tx_queue); Set tx queue mapping for sockfd; 2. int ioctl(int sockfd, int SIOGTXQUEUEMAPPING, int *tx_queue): Get tx queue mapping for sockfd. If no queue mapping is set, error is returned. 3. ioctl(int sockfd, int SIOSRXQUEUEMAPPING, int *rx_queue); Set rx queue mapping for sockfd; 4. ioctl(int sockfd, int SIOGRXQUEUEMAPPING, int *rx_queue); Get rx queue mapping for sockfd. If no queue mapping is set, error is returned. 5. ioctl(int sockfd, int SIOGNUMTXQUEUE, int *num_tx_queue); Get number of tx queue which is configured on the NIC interface bound to sockfd. 6. ioctl(int sockfd, int SIOGNUMRXQUEUE, int *num_rx_queue); Get number of rx queue which is configured on the NIC interface bound to sockfd. Signed-off-by: Fenghua Yu Signed-off-by: Junchang Wang Signed-off-by: Xinan Tang --- net/packet/af_packet.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 109 insertions(+), 0 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8298e67..022900d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -659,6 +659,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct timeval tv; struct timespec ts; struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); + int rx_queue_mapping; if (skb->pkt_type == PACKET_LOOPBACK) goto drop; @@ -666,6 +667,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, sk = pt->af_packet_priv; po = pkt_sk(sk); + rx_queue_mapping = sk_rx_queue_get(sk); + if (rx_queue_mapping >= 0) + if (skb_get_queue_mapping(skb) != rx_queue_mapping + 1) + goto drop; + if (!net_eq(dev_net(dev), sock_net(sk))) goto drop; @@ -2219,6 +2225,83 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void return NOTIFY_DONE; } +static void set_queue_mapping(struct sock *sk, unsigned int cmd, __u16 queue) +{ + if (cmd == SIOSRXQUEUEMAPPING) + sk_rx_queue_set(sk, queue); + else + sk_tx_queue_set(sk, queue); +} + +static int get_num_queues(struct socket *sock, unsigned int cmd, + unsigned int *p) +{ + struct net_device *dev; + struct sock *sk = sock->sk; + + if (!pkt_sk(sk)->ifindex) + return -EPERM; + + dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex); + if (dev == NULL) + return -ENODEV; + + switch (cmd) { + case SIOGNUMRXQUEUE: + *p = dev->real_num_rx_queues; + break; + case SIOGNUMTXQUEUE: + *p = dev->real_num_tx_queues; + break; + default: + return -EFAULT; + } + return 0; +} + +static int set_sock_queue(struct socket *sock, unsigned int cmd, + char __user *uarg) +{ + __u16 queue; + struct sock *sk = sock->sk; + struct net_device *dev; + int num_queues; + + if (copy_from_user(&queue, uarg, sizeof(queue))) + return -EFAULT; + + if (!pkt_sk(sk)->ifindex) + return -EPERM; + + dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex); + if (dev == NULL) + return -ENODEV; + + num_queues = cmd == SIOSRXQUEUEMAPPING ? dev->real_num_rx_queues : + dev->real_num_tx_queues; + if (queue >= num_queues) + return -EINVAL; + + set_queue_mapping(sk, cmd, queue); + return 0; +} + +static int get_sock_queue(struct socket *sock, unsigned int cmd, int *p) +{ + struct sock *sk = sock->sk; + + switch (cmd) { + case SIOGTXQUEUEMAPPING: + *p = sk_tx_queue_get(sk); + break; + case SIOGRXQUEUEMAPPING: + *p = sk_rx_queue_get(sk); + break; + default: + return -EFAULT; + } + return 0; +} static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) @@ -2267,6 +2350,32 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, return inet_dgram_ops.ioctl(sock, cmd, arg); #endif + case SIOGNUMRXQUEUE: + case SIOGNUMTXQUEUE: + { + int err; + unsigned int num_queues; + err = get_num_queues(sock, cmd, &num_queues); + if (!err) + return put_user(num_queues, (int __user *)arg); + else + return err; + } + case SIOSRXQUEUEMAPPING: + case SIOSTXQUEUEMAPPING: + return set_sock_queue(sock, cmd, (char __user *)arg); + + case SIOGRXQUEUEMAPPING: + case SIOGTXQUEUEMAPPING: + { + int err; + int queue_mapping; + err = get_sock_queue(sock, cmd, &queue_mapping); + if (!err) + return put_user(queue_mapping, (int __user *)arg); + else + return err; + } default: return -ENOIOCTLCMD; } -- 1.6.0.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/