From patchwork Wed Nov 9 07:56:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roopa Prabhu X-Patchwork-Id: 124461 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48AFA1007D4 for ; Wed, 9 Nov 2011 10:59:51 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933420Ab1KHX7o (ORCPT ); Tue, 8 Nov 2011 18:59:44 -0500 Received: from mtv-iport-2.cisco.com ([173.36.130.13]:44905 "EHLO mtv-iport-2.cisco.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932781Ab1KHX7l (ORCPT ); Tue, 8 Nov 2011 18:59:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cisco.com; i=roprabhu@cisco.com; l=5893; q=dns/txt; s=iport; t=1320796781; x=1322006381; h=subject:to:from:cc:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cA1jL22mGHtb/9gBpV5rtBjihtM2tk6oLFhq9LUZ+lk=; b=JlWDjdDUqHzlAH36lV4xpVpqZ07ti7X3vRgLMsd94fvDN1IWw5Ae1wVM wxsJW6YVXVZ5eoY7kxERTTO87IWqptF0z4iw6JltrVkUE2nN9uzBwZAsi kDBpcpwabj2k/hZPcWk8QefBuJPT1sTf7PG8xJ0oeuSYQLltH6CMSdyYX o=; X-IronPort-AV: E=Sophos;i="4.69,479,1315180800"; d="scan'208";a="13073604" Received: from mtv-core-3.cisco.com ([171.68.58.8]) by mtv-iport-2.cisco.com with ESMTP; 08 Nov 2011 23:59:41 +0000 Received: from rhel6.1 (savbu-dhcp-10-193-164-236.cisco.com [10.193.164.236]) by mtv-core-3.cisco.com (8.14.3/8.14.3) with ESMTP id pA8NxeV7003069; Tue, 8 Nov 2011 23:59:40 GMT Subject: [net-next-2.6 PATCH 6/6 v4] macvlan: Add support to get MAC/VLAN filter netdev ops To: netdev@vger.kernel.org, davem@davemloft.net From: Roopa Prabhu Cc: chrisw@redhat.com, sri@us.ibm.com, dragos.tatulea@gmail.com, kvm@vger.kernel.org, arnd@arndb.de, mst@redhat.com, gregory.v.rose@intel.com, mchan@broadcom.com, dwang2@cisco.com, shemminger@vyatta.com, eric.dumazet@gmail.com, kaber@trash.net, benve@cisco.com Date: Tue, 08 Nov 2011 23:56:06 -0800 Message-ID: <20111109075606.13549.97196.stgit@rhel6.1> In-Reply-To: <20111109075449.13549.58135.stgit@rhel6.1> References: <20111109075449.13549.58135.stgit@rhel6.1> User-Agent: StGit/0.15 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Roopa Prabhu This patch adds support to get MAC and VLAN filter netdev ops on a macvlan interface. It adds support for get_rx_filter_addr_size, get_rx_filter_vlan_size, fill_rx_filter_addr and fill_rx_filter_vlan netdev ops Signed-off-by: Roopa Prabhu Signed-off-by: Christian Benvenuti Signed-off-by: David Wang --- drivers/net/macvlan.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 158 insertions(+), 0 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index c2dea97..8a5320b 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -623,6 +623,55 @@ static int macvlan_set_rx_filter_vlan(struct net_device *dev, int vf, return 0; } +static size_t macvlan_get_rx_filter_vlan_size(const struct net_device *dev, + int vf) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + + if (vf != SELF_VF) + return -EINVAL; + + switch (vlan->mode) { + case MACVLAN_MODE_PASSTHRU: + if (ops->ndo_get_rx_filter_vlan_size) + return ops->ndo_get_rx_filter_vlan_size(dev, vf); + /* IFLA_RX_FILTER_VLAN_BITMAP */ + return nla_total_size(VLAN_BITMAP_SIZE); + default: + return 0; + } +} + +static int macvlan_get_rx_filter_vlan(const struct net_device *dev, int vf, + struct sk_buff *skb) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + + if (vf != SELF_VF) + return -EINVAL; + + switch (vlan->mode) { + case MACVLAN_MODE_PASSTHRU: + if (ops->ndo_get_rx_filter_vlan) + return ops->ndo_get_rx_filter_vlan(dev, vf, skb); + + NLA_PUT(skb, IFLA_RX_FILTER_VLAN_BITMAP, VLAN_BITMAP_SIZE, + vlan->vlan_filter); + break; + default: + return -ENODATA; /* No data to Fill */ + } + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int macvlan_addr_in_hw_list(struct netdev_hw_addr_list *list, u8 *addr, int addrlen) { @@ -802,6 +851,111 @@ static int macvlan_set_rx_filter_addr(struct net_device *dev, int vf, return 0; } +static size_t macvlan_get_rx_filter_addr_passthru_size( + const struct net_device *dev, int vf) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + size_t size; + + if (ops->ndo_get_rx_filter_addr_size) + return ops->ndo_get_rx_filter_addr_size(dev, vf); + + /* IFLA_RX_FILTER_ADDR_FLAGS */ + size = nla_total_size(sizeof(u32)); + + if (netdev_uc_count(dev)) + /* IFLA_RX_FILTER_ADDR_UC_LIST */ + size += nla_total_size(netdev_uc_count(dev) * + ETH_ALEN * sizeof(struct nlattr)); + + if (netdev_mc_count(dev)) + /* IFLA_RX_FILTER_ADDR_MC_LIST */ + size += nla_total_size(netdev_mc_count(dev) * + ETH_ALEN * sizeof(struct nlattr)); + + return size; +} + +static size_t macvlan_get_rx_filter_addr_size(const struct net_device *dev, + int vf) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + if (vf != SELF_VF) + return -EINVAL; + + switch (vlan->mode) { + case MACVLAN_MODE_PASSTHRU: + return macvlan_get_rx_filter_addr_passthru_size(dev, vf); + default: + return 0; + } +} + +static int macvlan_get_rx_filter_addr_passthru(const struct net_device *dev, + int vf, struct sk_buff *skb) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + struct nlattr *uninitialized_var(uc_list), *mc_list; + struct netdev_hw_addr *ha; + + if (ops->ndo_get_rx_filter_addr) + return ops->ndo_get_rx_filter_addr(dev, vf, skb); + + NLA_PUT_U32(skb, IFLA_RX_FILTER_ADDR_FLAGS, + dev->flags & RX_FILTER_FLAGS); + + if (netdev_uc_count(dev)) { + uc_list = nla_nest_start(skb, IFLA_RX_FILTER_ADDR_UC_LIST); + if (uc_list == NULL) + goto nla_put_failure; + + netdev_for_each_uc_addr(ha, dev) { + NLA_PUT(skb, IFLA_ADDR_LIST_ENTRY, ETH_ALEN, ha->addr); + } + nla_nest_end(skb, uc_list); + } + + if (netdev_mc_count(dev)) { + mc_list = nla_nest_start(skb, IFLA_RX_FILTER_ADDR_MC_LIST); + if (mc_list == NULL) + goto nla_uc_list_cancel; + + netdev_for_each_mc_addr(ha, dev) { + NLA_PUT(skb, IFLA_ADDR_LIST_ENTRY, ETH_ALEN, ha->addr); + } + nla_nest_end(skb, mc_list); + } + + return 0; + +nla_uc_list_cancel: + if (netdev_uc_count(dev)) + nla_nest_cancel(skb, uc_list); +nla_put_failure: + return -EMSGSIZE; +} + +static int macvlan_get_rx_filter_addr(const struct net_device *dev, int vf, + struct sk_buff *skb) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + if (vf != SELF_VF) + return -EINVAL; + + switch (vlan->mode) { + case MACVLAN_MODE_PASSTHRU: + return macvlan_get_rx_filter_addr_passthru(dev, vf, skb); + default: + return -ENODATA; /* No data to Fill */ + } +} + static void macvlan_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { @@ -838,7 +992,11 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid, .ndo_set_rx_filter_addr = macvlan_set_rx_filter_addr, + .ndo_get_rx_filter_addr_size = macvlan_get_rx_filter_addr_size, + .ndo_get_rx_filter_addr = macvlan_get_rx_filter_addr, .ndo_set_rx_filter_vlan = macvlan_set_rx_filter_vlan, + .ndo_get_rx_filter_vlan_size = macvlan_get_rx_filter_vlan_size, + .ndo_get_rx_filter_vlan = macvlan_get_rx_filter_vlan, }; void macvlan_common_setup(struct net_device *dev)