Hello Scott, Thank you for the diff and comments. Please see my comments inline.
> -----Original Message----- > From: Scott Feldman [mailto:sfel...@gmail.com] > Sent: Tuesday, August 18, 2015 12:48 PM > To: Premkumar Jonnala > Cc: netdev@vger.kernel.org > Subject: Re: [PATCH] bridge: Enable configuration of ageing interval for > bridges > and switch devices. > > > > On Fri, 14 Aug 2015, Premkumar Jonnala wrote: > > > Bridge devices have ageing interval used to age out MAC addresses > > from FDB. This ageing interval was not configuratble. > > > > Enable netlink based configuration of ageing interval for bridges and > > switch devices. The ageing interval changes the timer used to purge > > inactive FDB entries in bridges. The ageing interval config is > > propagated to switch devices, so that platform or hardware based > > ageing works according to configuration. > > > > Signed-off-by: Premkumar Jonnala <pjonn...@broadcom.com> > > Hi Premkumar, > > I agree with Roopa that we should use existing IFLA_BR_AGEING_TIME. What is the motivation for using 'ip link' command to configure bridge attributes? IMHO, bridge command is better suited for that. > > I hope you don't mind if share a patch for setting bridge-level attributes > down to the switch hardware ports. It uses the switchdev_port_attr_set() > call on the bridge interface itself when any IFLA_BR_xxx attribute is set > via netlink. switchdev_port_attr_set() will do a recursive walk of all > lower devs from the bridge, stopping at each to set the attribute. I > added one small tweak to switchdev_port_attr_set() to allow skipping over > ports that return -EOPNOTSUPP. The advantage to using > switchdev_port_attr_set() is it automatically knows how to find the leaf > ports in a stacked driver setup, and it uses the prepare/commit > transaction model to make sure all ports can support new attr setting > before committing setting to hardware. > > I gave an example using rocker to set IFLA_BR_AGEING_TIME. It's stubbed > out, but you get the idea. Other IFLA_BR_xxx attrs can be added to this > model. > > Does this look like something that would work? If so, would you mind > running with this patch and maybe even extending it for other IFLA_BR_xxx > attrs? Sure, let me go with this patch. Couple of comments inline. > > Again, I hope I'm not stepping on toes here by rewriting your patch, but > it was the best way to communicate the idea of how to use the switchdev > frame work for these bridge attrs. > > -scott > > > > > diff --git a/drivers/net/ethernet/rocker/rocker.c > b/drivers/net/ethernet/rocker/rocker.c > index 0cc9e8f..830f8e6 100644 > --- a/drivers/net/ethernet/rocker/rocker.c > +++ b/drivers/net/ethernet/rocker/rocker.c > @@ -4680,6 +4680,24 @@ static int rocker_port_brport_flags_set(struct > rocker_port *rocker_port, > return err; > } > > +static int rocker_port_bridge_set(struct rocker_port *rocker_port, > + enum switchdev_trans trans, > + struct switchdev_attr_bridge *bridge) > +{ > + switch (bridge->attr) { > + case IFLA_BR_AGEING_TIME: > + { > + u32 ageing_time = bridge->val; > + /* XXX push ageing_time down to device */ > + } > + break; > + default: > + return -EOPNOTSUPP; > + } > + > + return 0; > +} > + > static int rocker_port_attr_set(struct net_device *dev, > struct switchdev_attr *attr) > { > @@ -4707,6 +4725,10 @@ static int rocker_port_attr_set(struct net_device > *dev, > err = rocker_port_brport_flags_set(rocker_port, attr->trans, > attr->u.brport_flags); > break; > + case SWITCHDEV_ATTR_BRIDGE: > + err = rocker_port_bridge_set(rocker_port, attr->trans, > + &attr->u.bridge); > + break; > default: > err = -EOPNOTSUPP; > break; > diff --git a/include/net/switchdev.h b/include/net/switchdev.h > index 319baab..22a6dbe 100644 > --- a/include/net/switchdev.h > +++ b/include/net/switchdev.h > @@ -15,6 +15,7 @@ > #include <linux/notifier.h> > > #define SWITCHDEV_F_NO_RECURSE BIT(0) > +#define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) > > enum switchdev_trans { > SWITCHDEV_TRANS_NONE, > @@ -28,6 +29,7 @@ enum switchdev_attr_id { > SWITCHDEV_ATTR_PORT_PARENT_ID, > SWITCHDEV_ATTR_PORT_STP_STATE, > SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS, > + SWITCHDEV_ATTR_BRIDGE, > }; > > struct switchdev_attr { > @@ -38,6 +40,10 @@ struct switchdev_attr { > struct netdev_phys_item_id ppid; /* PORT_PARENT_ID > */ > u8 stp_state; /* PORT_STP_STATE > */ > unsigned long brport_flags; /* > PORT_BRIDGE_FLAGS */ > + struct switchdev_attr_bridge { /* BRIDGE */ > + enum ifla_br attr; > + u32 val; > + } bridge; > } u; > }; > > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h > index ff659f0..0630053 100644 > --- a/include/uapi/linux/if_link.h > +++ b/include/uapi/linux/if_link.h > @@ -222,7 +222,7 @@ enum in6_addr_gen_mode { > > /* Bridge section */ > > -enum { > +enum ifla_br { > IFLA_BR_UNSPEC, > IFLA_BR_FORWARD_DELAY, > IFLA_BR_HELLO_TIME, > diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c > index 0f2408f..01401ea 100644 > --- a/net/bridge/br_netlink.c > +++ b/net/bridge/br_netlink.c > @@ -759,9 +759,9 @@ static int br_changelink(struct net_device *brdev, struct > nlattr *tb[], > } > > if (data[IFLA_BR_AGEING_TIME]) { > - u32 ageing_time = nla_get_u32(data[IFLA_BR_AGEING_TIME]); Should we do some range checking here to ensure that the value is within a certain range. IEEE 802.1d recommends that the ageing time be between 10 sec and 1 million seconds. > - > - br->ageing_time = clock_t_to_jiffies(ageing_time); > + err = br_set_ageing_time(br, > nla_get_u32(data[IFLA_BR_AGEING_TIME])); > + if (err) > + return err; > } > > if (data[IFLA_BR_STP_STATE]) { > diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h > index 3d95647..9807a6f 100644 > --- a/net/bridge/br_private.h > +++ b/net/bridge/br_private.h > @@ -807,6 +807,7 @@ void __br_set_forward_delay(struct net_bridge *br, > unsigned long t); > int br_set_forward_delay(struct net_bridge *br, unsigned long x); > int br_set_hello_time(struct net_bridge *br, unsigned long x); > int br_set_max_age(struct net_bridge *br, unsigned long x); > +int br_set_ageing_time(struct net_bridge *br, u32 ageing_time); > > > /* br_stp_if.c */ > diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c > index ed74ffa..5de27bc 100644 > --- a/net/bridge/br_stp.c > +++ b/net/bridge/br_stp.c > @@ -566,6 +566,25 @@ int br_set_max_age(struct net_bridge *br, unsigned > long val) > > } > > +int br_set_ageing_time(struct net_bridge *br, u32 ageing_time) > +{ > + struct switchdev_attr attr = { > + .id = SWITCHDEV_ATTR_BRIDGE, > + .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, > + .u.bridge.attr = IFLA_BR_AGEING_TIME, > + .u.bridge.val = ageing_time, > + }; > + int err; > + > + err = switchdev_port_attr_set(br->dev, &attr); > + if (err) > + return err; > + > + br->ageing_time = clock_t_to_jiffies(ageing_time); Should we restart the timer here the new time takes effect? > + > + return 0; > +} > + > void __br_set_forward_delay(struct net_bridge *br, unsigned long t) > { > br->bridge_forward_delay = t; > diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c > index 16c1c43..b990301 100644 > --- a/net/switchdev/switchdev.c > +++ b/net/switchdev/switchdev.c > @@ -73,7 +73,7 @@ static int __switchdev_port_attr_set(struct net_device > *dev, > return ops->switchdev_port_attr_set(dev, attr); > > if (attr->flags & SWITCHDEV_F_NO_RECURSE) > - return err; > + goto done; > > /* Switch device port(s) may be stacked under > * bond/team/vlan dev, so recurse down to set attr on > @@ -82,10 +82,17 @@ static int __switchdev_port_attr_set(struct net_device > *dev, > > netdev_for_each_lower_dev(dev, lower_dev, iter) { > err = __switchdev_port_attr_set(lower_dev, attr); > + if (err == -EOPNOTSUPP && > + attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP) > + continue; > if (err) > break; > } > > +done: > + if (err == -EOPNOTSUPP && attr->flags & > SWITCHDEV_F_SKIP_EOPNOTSUPP) > + err = 0; > + > return err; > } -Prem -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html