diff mbox

[net-next,v2,1/1] bring netlink interface to par with brctl show macs

Message ID 1401023755-8174-1-git-send-email-jhs@emojatatu.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Jamal Hadi Salim May 25, 2014, 1:15 p.m. UTC
From: Jamal Hadi Salim <jhs@mojatatu.com>

This patch allows something equivalent to
"brctl showmacs <bridge device>" with iproute2
syntax "bridge fdb show br <bridge device>"
Filtering by bridge is done in the kernel.
The current setup doesnt scale when you have many bridges each
with large fdbs (preliminary fix with the kernel patch).

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
 net/core/rtnetlink.c |   49 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 15 deletions(-)

Comments

Ben Hutchings May 26, 2014, 2:35 a.m. UTC | #1
On Sun, 2014-05-25 at 09:15 -0400, Jamal Hadi Salim wrote:
> From: Jamal Hadi Salim <jhs@mojatatu.com>
> 
> This patch allows something equivalent to
> "brctl showmacs <bridge device>" with iproute2
> syntax "bridge fdb show br <bridge device>"
> Filtering by bridge is done in the kernel.
> The current setup doesnt scale when you have many bridges each
> with large fdbs (preliminary fix with the kernel patch).
> 
> Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
> ---
>  net/core/rtnetlink.c |   49 ++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 34 insertions(+), 15 deletions(-)
> 
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index f31268d..1ad4828 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -2509,26 +2509,45 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
>  {
>  	int idx = 0;
>  	struct net *net = sock_net(skb->sk);
> +	const struct net_device_ops *ops;
>  	struct net_device *dev;
> +	struct ndmsg *ndm;
>  
> -	rcu_read_lock();
> -	for_each_netdev_rcu(net, dev) {
> -		if (dev->priv_flags & IFF_BRIDGE_PORT) {
> -			struct net_device *br_dev;
> -			const struct net_device_ops *ops;
> -
> -			br_dev = netdev_master_upper_dev_get(dev);
> -			ops = br_dev->netdev_ops;
> -			if (ops->ndo_fdb_dump)
> -				idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
> +	ndm = nlmsg_data(cb->nlh);
> +	if (ndm->ndm_ifindex) {
> +		dev = __dev_get_by_index(net, ndm->ndm_ifindex);
> +		if (dev == NULL) {
> +			pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n");

You left another debug message here.

> +			return -ENODEV;
>  		}
>  
> -		if (dev->netdev_ops->ndo_fdb_dump)
> -			idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
> -		else
> -			idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
> +		ops = dev->netdev_ops;
> +		if (ops->ndo_fdb_dump) {
> +			idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
> +		} else {
> +			pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n",
> +				dev->name);

And here.

> +			return -EINVAL;
> +		}
[...]

Why does this only call the device's own ndo_fdb_dump and not a
bridge-port's bridge's ndo_fdb_dump or ndo_dflt_fdb_dump?

Ben.
Jamal Hadi Salim May 26, 2014, 11:05 a.m. UTC | #2
On 05/25/14 22:35, Ben Hutchings wrote:
> On Sun, 2014-05-25 at 09:15 -0400, Jamal Hadi Salim wrote:

>> +		if (dev == NULL) {
>> +			pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n");
>
> You left another debug message here.
>
>> +			return -ENODEV;
>>   		}

>> +			pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n",
>> +				dev->name);
>
> And here.

Those two just adhere to the coding style used in the rest of the fdb
code. I could remove them and send subsequent patches to remove
equivalent debugs in the rest of the code. To me they seem useful
although i have seen very strong views against them in the past.

>> +			return -EINVAL;
>> +		}
> [...]
>
> Why does this only call the device's own ndo_fdb_dump and not a
> bridge-port's bridge's ndo_fdb_dump or ndo_dflt_fdb_dump?

The target is a specific bridge not a bridge port. Having
said that, it is (probably) possible there are physical or virtual
bridge ports whose master is the targeted bridge that are sheltering
fdb entries we want to dump that are not in the bridge's fdb.
Macvlans or vmdq maybe? What did you have in mind?

cheers,
jamal



> Ben.
>

--
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
David Miller May 30, 2014, 5:08 a.m. UTC | #3
From: Jamal Hadi Salim <jhs@mojatatu.com>
Date: Mon, 26 May 2014 07:05:01 -0400

> On 05/25/14 22:35, Ben Hutchings wrote:
>> On Sun, 2014-05-25 at 09:15 -0400, Jamal Hadi Salim wrote:
> 
>>> +		if (dev == NULL) {
>>> + pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n");
>>
>> You left another debug message here.
>>
>>> +			return -ENODEV;
>>>   		}
> 
>>> +			pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n",
>>> +				dev->name);
>>
>> And here.
> 
> Those two just adhere to the coding style used in the rest of the fdb
> code. I could remove them and send subsequent patches to remove
> equivalent debugs in the rest of the code. To me they seem useful
> although i have seen very strong views against them in the past.

I think we have to get rid of these, because they are essentially
user triggerable.
--
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 mbox

Patch

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f31268d..1ad4828 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2509,26 +2509,45 @@  static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	int idx = 0;
 	struct net *net = sock_net(skb->sk);
+	const struct net_device_ops *ops;
 	struct net_device *dev;
+	struct ndmsg *ndm;
 
-	rcu_read_lock();
-	for_each_netdev_rcu(net, dev) {
-		if (dev->priv_flags & IFF_BRIDGE_PORT) {
-			struct net_device *br_dev;
-			const struct net_device_ops *ops;
-
-			br_dev = netdev_master_upper_dev_get(dev);
-			ops = br_dev->netdev_ops;
-			if (ops->ndo_fdb_dump)
-				idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
+	ndm = nlmsg_data(cb->nlh);
+	if (ndm->ndm_ifindex) {
+		dev = __dev_get_by_index(net, ndm->ndm_ifindex);
+		if (dev == NULL) {
+			pr_info("PF_BRIDGE: RTM_GETNEIGH with unknown ifindex\n");
+			return -ENODEV;
 		}
 
-		if (dev->netdev_ops->ndo_fdb_dump)
-			idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
-		else
-			idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+		ops = dev->netdev_ops;
+		if (ops->ndo_fdb_dump) {
+			idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
+		} else {
+			pr_info("PF_BRIDGE: RTM_GETNEIGH %s no dumper\n",
+				dev->name);
+			return -EINVAL;
+		}
+	} else {
+		rcu_read_lock();
+		for_each_netdev_rcu(net, dev) {
+			if (dev->priv_flags & IFF_BRIDGE_PORT) {
+				struct net_device *br_dev;
+				br_dev = netdev_master_upper_dev_get(dev);
+				ops = br_dev->netdev_ops;
+				if (ops->ndo_fdb_dump)
+					idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
+			}
+
+			if (dev->netdev_ops->ndo_fdb_dump)
+				idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev,
+								    idx);
+			else
+				idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+		}
+		rcu_read_unlock();
 	}
-	rcu_read_unlock();
 
 	cb->args[0] = idx;
 	return skb->len;