Re: [Bridge] [PATCH net-next v3 05/15] net: bridge: mcast: factor out port group del

2020-09-06 Thread Jakub Kicinski
On Mon, 7 Sep 2020 00:29:10 +0300 Nikolay Aleksandrov wrote:
> >> @@ -1641,16 +1647,7 @@ br_multicast_leave_group(struct net_bridge *br,
> >>if (p->flags & MDB_PG_FLAGS_PERMANENT)
> >>break;
> >>   
> >> -  rcu_assign_pointer(*pp, p->next);
> >> -  hlist_del_init(>mglist);
> >> -  del_timer(>timer);
> >> -  kfree_rcu(p, rcu);
> >> -  br_mdb_notify(br->dev, port, group, RTM_DELMDB,
> >> -p->flags | MDB_PG_FLAGS_FAST_LEAVE);  
> > 
> > And here we'll loose MDB_PG_FLAGS_FAST_LEAVE potentially?
> 
> Good catch, we will lose the fast leave indeed.
> This is a 1 line change to set the flag before notifying. Would you prefer
> me to send a v4 or a follow up for it?

I think it's cleaner if you send a v4. But not rush, I was planning to
apply this tomorrow morning PST, anyway.


Re: [Bridge] [PATCH net-next v3 05/15] net: bridge: mcast: factor out port group del

2020-09-06 Thread Nikolay Aleksandrov

On 9/7/20 12:29 AM, Nikolay Aleksandrov wrote:

On 9/6/20 11:56 PM, Jakub Kicinski wrote:

On Sat,  5 Sep 2020 11:24:00 +0300 Nikolay Aleksandrov wrote:

@@ -843,24 +843,11 @@ static int __br_mdb_del(struct net_bridge *br, struct 
br_mdb_entry *entry)
  if (!p->port || p->port->dev->ifindex != entry->ifindex)
  continue;
-    if (!hlist_empty(>src_list)) {
-    err = -EINVAL;
-    goto unlock;
-    }
-
  if (p->port->state == BR_STATE_DISABLED)
  goto unlock;
-    __mdb_entry_fill_flags(entry, p->flags);


Just from staring at the code it's unclear why the list_empty() check
and this __mdb_entry_fill_flags() are removed as well.



The hlist_empty check is added by patch 01 temporarily for correctness.
Otherwise I'd have to edit all open-coded pg del places and add src delete
code and then remove it here.



Obviously if I do a v4, I'll just move this patch before adding the hlist_empty
in the first place. :-)


__mdb_entry_fill_flags() are called by __mdb_fill_info() which is the only
function used to fill an mdb both for dumping and notifications after patch 08.


-    rcu_assign_pointer(*pp, p->next);
-    hlist_del_init(>mglist);
-    del_timer(>timer);
-    kfree_rcu(p, rcu);
+    br_multicast_del_pg(mp, p, pp);
  err = 0;
-
-    if (!mp->ports && !mp->host_joined &&
-    netif_running(br->dev))
-    mod_timer(>timer, jiffies);
  break;




+void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+ struct net_bridge_port_group *pg,
+ struct net_bridge_port_group __rcu **pp)
+{
+    struct net_bridge *br = pg->port->br;
+    struct net_bridge_group_src *ent;
+    struct hlist_node *tmp;
+
+    rcu_assign_pointer(*pp, pg->next);
+    hlist_del_init(>mglist);
+    del_timer(>timer);
+    hlist_for_each_entry_safe(ent, tmp, >src_list, node)
+    br_multicast_del_group_src(ent);
+    br_mdb_notify(br->dev, pg->port, >addr, RTM_DELMDB, pg->flags);
+    kfree_rcu(pg, rcu);
+
+    if (!mp->ports && !mp->host_joined && netif_running(br->dev))
+    mod_timer(>timer, jiffies);
+}



@@ -1641,16 +1647,7 @@ br_multicast_leave_group(struct net_bridge *br,
  if (p->flags & MDB_PG_FLAGS_PERMANENT)
  break;
-    rcu_assign_pointer(*pp, p->next);
-    hlist_del_init(>mglist);
-    del_timer(>timer);
-    kfree_rcu(p, rcu);
-    br_mdb_notify(br->dev, port, group, RTM_DELMDB,
-  p->flags | MDB_PG_FLAGS_FAST_LEAVE);


And here we'll loose MDB_PG_FLAGS_FAST_LEAVE potentially?



Good catch, we will lose the fast leave indeed.
This is a 1 line change to set the flag before notifying. Would you prefer
me to send a v4 or a follow up for it?

Thanks,
  Nik


-    if (!mp->ports && !mp->host_joined &&
-    netif_running(br->dev))
-    mod_timer(>timer, jiffies);
+    br_multicast_del_pg(mp, p, pp);






Re: [Bridge] [PATCH net-next v3 05/15] net: bridge: mcast: factor out port group del

2020-09-06 Thread Nikolay Aleksandrov

On 9/6/20 11:56 PM, Jakub Kicinski wrote:

On Sat,  5 Sep 2020 11:24:00 +0300 Nikolay Aleksandrov wrote:

@@ -843,24 +843,11 @@ static int __br_mdb_del(struct net_bridge *br, struct 
br_mdb_entry *entry)
if (!p->port || p->port->dev->ifindex != entry->ifindex)
continue;
  
-		if (!hlist_empty(>src_list)) {

-   err = -EINVAL;
-   goto unlock;
-   }
-
if (p->port->state == BR_STATE_DISABLED)
goto unlock;
  
-		__mdb_entry_fill_flags(entry, p->flags);


Just from staring at the code it's unclear why the list_empty() check
and this __mdb_entry_fill_flags() are removed as well.



The hlist_empty check is added by patch 01 temporarily for correctness.
Otherwise I'd have to edit all open-coded pg del places and add src delete
code and then remove it here.

__mdb_entry_fill_flags() are called by __mdb_fill_info() which is the only
function used to fill an mdb both for dumping and notifications after patch 08.


-   rcu_assign_pointer(*pp, p->next);
-   hlist_del_init(>mglist);
-   del_timer(>timer);
-   kfree_rcu(p, rcu);
+   br_multicast_del_pg(mp, p, pp);
err = 0;
-
-   if (!mp->ports && !mp->host_joined &&
-   netif_running(br->dev))
-   mod_timer(>timer, jiffies);
break;




+void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+struct net_bridge_port_group *pg,
+struct net_bridge_port_group __rcu **pp)
+{
+   struct net_bridge *br = pg->port->br;
+   struct net_bridge_group_src *ent;
+   struct hlist_node *tmp;
+
+   rcu_assign_pointer(*pp, pg->next);
+   hlist_del_init(>mglist);
+   del_timer(>timer);
+   hlist_for_each_entry_safe(ent, tmp, >src_list, node)
+   br_multicast_del_group_src(ent);
+   br_mdb_notify(br->dev, pg->port, >addr, RTM_DELMDB, pg->flags);
+   kfree_rcu(pg, rcu);
+
+   if (!mp->ports && !mp->host_joined && netif_running(br->dev))
+   mod_timer(>timer, jiffies);
+}



@@ -1641,16 +1647,7 @@ br_multicast_leave_group(struct net_bridge *br,
if (p->flags & MDB_PG_FLAGS_PERMANENT)
break;
  
-			rcu_assign_pointer(*pp, p->next);

-   hlist_del_init(>mglist);
-   del_timer(>timer);
-   kfree_rcu(p, rcu);
-   br_mdb_notify(br->dev, port, group, RTM_DELMDB,
- p->flags | MDB_PG_FLAGS_FAST_LEAVE);


And here we'll loose MDB_PG_FLAGS_FAST_LEAVE potentially?



Good catch, we will lose the fast leave indeed.
This is a 1 line change to set the flag before notifying. Would you prefer
me to send a v4 or a follow up for it?

Thanks,
 Nik


-   if (!mp->ports && !mp->host_joined &&
-   netif_running(br->dev))
-   mod_timer(>timer, jiffies);
+   br_multicast_del_pg(mp, p, pp);




Re: [Bridge] [PATCH net-next v3 05/15] net: bridge: mcast: factor out port group del

2020-09-06 Thread Jakub Kicinski
On Sat,  5 Sep 2020 11:24:00 +0300 Nikolay Aleksandrov wrote:
> @@ -843,24 +843,11 @@ static int __br_mdb_del(struct net_bridge *br, struct 
> br_mdb_entry *entry)
>   if (!p->port || p->port->dev->ifindex != entry->ifindex)
>   continue;
>  
> - if (!hlist_empty(>src_list)) {
> - err = -EINVAL;
> - goto unlock;
> - }
> -
>   if (p->port->state == BR_STATE_DISABLED)
>   goto unlock;
>  
> - __mdb_entry_fill_flags(entry, p->flags);

Just from staring at the code it's unclear why the list_empty() check
and this __mdb_entry_fill_flags() are removed as well.

> - rcu_assign_pointer(*pp, p->next);
> - hlist_del_init(>mglist);
> - del_timer(>timer);
> - kfree_rcu(p, rcu);
> + br_multicast_del_pg(mp, p, pp);
>   err = 0;
> -
> - if (!mp->ports && !mp->host_joined &&
> - netif_running(br->dev))
> - mod_timer(>timer, jiffies);
>   break;


> +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
> +  struct net_bridge_port_group *pg,
> +  struct net_bridge_port_group __rcu **pp)
> +{
> + struct net_bridge *br = pg->port->br;
> + struct net_bridge_group_src *ent;
> + struct hlist_node *tmp;
> +
> + rcu_assign_pointer(*pp, pg->next);
> + hlist_del_init(>mglist);
> + del_timer(>timer);
> + hlist_for_each_entry_safe(ent, tmp, >src_list, node)
> + br_multicast_del_group_src(ent);
> + br_mdb_notify(br->dev, pg->port, >addr, RTM_DELMDB, pg->flags);
> + kfree_rcu(pg, rcu);
> +
> + if (!mp->ports && !mp->host_joined && netif_running(br->dev))
> + mod_timer(>timer, jiffies);
> +}

> @@ -1641,16 +1647,7 @@ br_multicast_leave_group(struct net_bridge *br,
>   if (p->flags & MDB_PG_FLAGS_PERMANENT)
>   break;
>  
> - rcu_assign_pointer(*pp, p->next);
> - hlist_del_init(>mglist);
> - del_timer(>timer);
> - kfree_rcu(p, rcu);
> - br_mdb_notify(br->dev, port, group, RTM_DELMDB,
> -   p->flags | MDB_PG_FLAGS_FAST_LEAVE);

And here we'll loose MDB_PG_FLAGS_FAST_LEAVE potentially?

> - if (!mp->ports && !mp->host_joined &&
> - netif_running(br->dev))
> - mod_timer(>timer, jiffies);
> + br_multicast_del_pg(mp, p, pp);


[Bridge] [PATCH net-next v3 05/15] net: bridge: mcast: factor out port group del

2020-09-05 Thread Nikolay Aleksandrov
In order to avoid future errors and reduce code duplication we should
factor out the port group del sequence. This allows us to have one
function which takes care of all details when removing a port group.

Signed-off-by: Nikolay Aleksandrov 
---
 net/bridge/br_mdb.c   | 15 +-
 net/bridge/br_multicast.c | 59 +++
 net/bridge/br_private.h   |  3 ++
 3 files changed, 32 insertions(+), 45 deletions(-)

diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 76fce1dac4a5..9dc12ce61018 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -843,24 +843,11 @@ static int __br_mdb_del(struct net_bridge *br, struct 
br_mdb_entry *entry)
if (!p->port || p->port->dev->ifindex != entry->ifindex)
continue;
 
-   if (!hlist_empty(>src_list)) {
-   err = -EINVAL;
-   goto unlock;
-   }
-
if (p->port->state == BR_STATE_DISABLED)
goto unlock;
 
-   __mdb_entry_fill_flags(entry, p->flags);
-   rcu_assign_pointer(*pp, p->next);
-   hlist_del_init(>mglist);
-   del_timer(>timer);
-   kfree_rcu(p, rcu);
+   br_multicast_del_pg(mp, p, pp);
err = 0;
-
-   if (!mp->ports && !mp->host_joined &&
-   netif_running(br->dev))
-   mod_timer(>timer, jiffies);
break;
}
 
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 4fdc1a7ba627..72b32398e279 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -173,14 +173,32 @@ static void br_multicast_del_group_src(struct 
net_bridge_group_src *src)
queue_work(system_long_wq, >src_gc_work);
 }
 
-static void br_multicast_del_pg(struct net_bridge *br,
-   struct net_bridge_port_group *pg)
+void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
+struct net_bridge_port_group *pg,
+struct net_bridge_port_group __rcu **pp)
+{
+   struct net_bridge *br = pg->port->br;
+   struct net_bridge_group_src *ent;
+   struct hlist_node *tmp;
+
+   rcu_assign_pointer(*pp, pg->next);
+   hlist_del_init(>mglist);
+   del_timer(>timer);
+   hlist_for_each_entry_safe(ent, tmp, >src_list, node)
+   br_multicast_del_group_src(ent);
+   br_mdb_notify(br->dev, pg->port, >addr, RTM_DELMDB, pg->flags);
+   kfree_rcu(pg, rcu);
+
+   if (!mp->ports && !mp->host_joined && netif_running(br->dev))
+   mod_timer(>timer, jiffies);
+}
+
+static void br_multicast_find_del_pg(struct net_bridge *br,
+struct net_bridge_port_group *pg)
 {
struct net_bridge_mdb_entry *mp;
struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp;
-   struct net_bridge_group_src *ent;
-   struct hlist_node *tmp;
 
mp = br_mdb_ip_get(br, >addr);
if (WARN_ON(!mp))
@@ -192,19 +210,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
if (p != pg)
continue;
 
-   rcu_assign_pointer(*pp, p->next);
-   hlist_del_init(>mglist);
-   del_timer(>timer);
-   hlist_for_each_entry_safe(ent, tmp, >src_list, node)
-   br_multicast_del_group_src(ent);
-   br_mdb_notify(br->dev, p->port, >addr, RTM_DELMDB,
- p->flags);
-   kfree_rcu(p, rcu);
-
-   if (!mp->ports && !mp->host_joined &&
-   netif_running(br->dev))
-   mod_timer(>timer, jiffies);
-
+   br_multicast_del_pg(mp, pg, pp);
return;
}
 
@@ -221,7 +227,7 @@ static void br_multicast_port_group_expired(struct 
timer_list *t)
hlist_unhashed(>mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT)
goto out;
 
-   br_multicast_del_pg(br, pg);
+   br_multicast_find_del_pg(br, pg);
 
 out:
spin_unlock(>multicast_lock);
@@ -615,7 +621,7 @@ static void br_multicast_group_src_expired(struct 
timer_list *t)
br_multicast_del_group_src(src);
if (!hlist_empty(>src_list))
goto out;
-   br_multicast_del_pg(br, pg);
+   br_multicast_find_del_pg(br, pg);
}
 out:
spin_unlock(>multicast_lock);
@@ -1086,7 +1092,7 @@ void br_multicast_del_port(struct net_bridge_port *port)
/* Take care of the remaining groups, only perm ones should be left */
spin_lock_bh(>multicast_lock);
hlist_for_each_entry_safe(pg, n, >mglist, mglist)
-   br_multicast_del_pg(br, pg);
+   br_multicast_find_del_pg(br, pg);
spin_unlock_bh(>multicast_lock);