Skip to content

Commit a1b486a

Browse files
committed
Merge branch 'bridge-mdb-entry-offload-flag'
Jiri Pirko says: ==================== bridge: mdb: flag offloaded mdb entries This patchset extends uapi to let the user know if an mdb entry is offloaded. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d66bd90 + 9e8430f commit a1b486a

File tree

4 files changed

+56
-38
lines changed

4 files changed

+56
-38
lines changed

include/uapi/linux/if_bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ struct br_mdb_entry {
183183
#define MDB_TEMPORARY 0
184184
#define MDB_PERMANENT 1
185185
__u8 state;
186+
#define MDB_FLAGS_OFFLOAD (1 << 0)
187+
__u8 flags;
186188
__u16 vid;
187189
struct {
188190
union {

net/bridge/br_mdb.c

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
4141
return -EMSGSIZE;
4242
}
4343

44+
static void __mdb_entry_fill_flags(struct br_mdb_entry *e, unsigned char flags)
45+
{
46+
e->state = flags & MDB_PG_FLAGS_PERMANENT;
47+
e->flags = 0;
48+
if (flags & MDB_PG_FLAGS_OFFLOAD)
49+
e->flags |= MDB_FLAGS_OFFLOAD;
50+
}
51+
4452
static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
4553
struct net_device *dev)
4654
{
@@ -85,8 +93,8 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
8593
struct br_mdb_entry e;
8694
memset(&e, 0, sizeof(e));
8795
e.ifindex = port->dev->ifindex;
88-
e.state = p->state;
8996
e.vid = p->addr.vid;
97+
__mdb_entry_fill_flags(&e, p->flags);
9098
if (p->addr.proto == htons(ETH_P_IP))
9199
e.addr.u.ip4 = p->addr.u.ip4;
92100
#if IS_ENABLED(CONFIG_IPV6)
@@ -209,7 +217,7 @@ static inline size_t rtnl_mdb_nlmsg_size(void)
209217
}
210218

211219
static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
212-
int type)
220+
int type, struct net_bridge_port_group *pg)
213221
{
214222
struct switchdev_obj_port_mdb mdb = {
215223
.obj = {
@@ -232,10 +240,13 @@ static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
232240
#endif
233241

234242
mdb.obj.orig_dev = port_dev;
235-
if (port_dev && type == RTM_NEWMDB)
236-
switchdev_port_obj_add(port_dev, &mdb.obj);
237-
else if (port_dev && type == RTM_DELMDB)
243+
if (port_dev && type == RTM_NEWMDB) {
244+
err = switchdev_port_obj_add(port_dev, &mdb.obj);
245+
if (!err && pg)
246+
pg->flags |= MDB_PG_FLAGS_OFFLOAD;
247+
} else if (port_dev && type == RTM_DELMDB) {
238248
switchdev_port_obj_del(port_dev, &mdb.obj);
249+
}
239250

240251
skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC);
241252
if (!skb)
@@ -253,21 +264,21 @@ static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
253264
rtnl_set_sk_err(net, RTNLGRP_MDB, err);
254265
}
255266

256-
void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
257-
struct br_ip *group, int type, u8 state)
267+
void br_mdb_notify(struct net_device *dev, struct net_bridge_port_group *pg,
268+
int type)
258269
{
259270
struct br_mdb_entry entry;
260271

261272
memset(&entry, 0, sizeof(entry));
262-
entry.ifindex = port->dev->ifindex;
263-
entry.addr.proto = group->proto;
264-
entry.addr.u.ip4 = group->u.ip4;
273+
entry.ifindex = pg->port->dev->ifindex;
274+
entry.addr.proto = pg->addr.proto;
275+
entry.addr.u.ip4 = pg->addr.u.ip4;
265276
#if IS_ENABLED(CONFIG_IPV6)
266-
entry.addr.u.ip6 = group->u.ip6;
277+
entry.addr.u.ip6 = pg->addr.u.ip6;
267278
#endif
268-
entry.state = state;
269-
entry.vid = group->vid;
270-
__br_mdb_notify(dev, &entry, type);
279+
entry.vid = pg->addr.vid;
280+
__mdb_entry_fill_flags(&entry, pg->flags);
281+
__br_mdb_notify(dev, &entry, type, pg);
271282
}
272283

273284
static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
@@ -412,7 +423,8 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
412423
}
413424

414425
static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
415-
struct br_ip *group, unsigned char state)
426+
struct br_ip *group, unsigned char state,
427+
struct net_bridge_port_group **pg)
416428
{
417429
struct net_bridge_mdb_entry *mp;
418430
struct net_bridge_port_group *p;
@@ -443,14 +455,16 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
443455
if (unlikely(!p))
444456
return -ENOMEM;
445457
rcu_assign_pointer(*pp, p);
458+
*pg = p;
446459
if (state == MDB_TEMPORARY)
447460
mod_timer(&p->timer, now + br->multicast_membership_interval);
448461

449462
return 0;
450463
}
451464

452465
static int __br_mdb_add(struct net *net, struct net_bridge *br,
453-
struct br_mdb_entry *entry)
466+
struct br_mdb_entry *entry,
467+
struct net_bridge_port_group **pg)
454468
{
455469
struct br_ip ip;
456470
struct net_device *dev;
@@ -479,14 +493,15 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
479493
#endif
480494

481495
spin_lock_bh(&br->multicast_lock);
482-
ret = br_mdb_add_group(br, p, &ip, entry->state);
496+
ret = br_mdb_add_group(br, p, &ip, entry->state, pg);
483497
spin_unlock_bh(&br->multicast_lock);
484498
return ret;
485499
}
486500

487501
static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
488502
{
489503
struct net *net = sock_net(skb->sk);
504+
struct net_bridge_port_group *pg;
490505
struct net_bridge_vlan_group *vg;
491506
struct net_device *dev, *pdev;
492507
struct br_mdb_entry *entry;
@@ -516,15 +531,15 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
516531
if (br_vlan_enabled(br) && vg && entry->vid == 0) {
517532
list_for_each_entry(v, &vg->vlan_list, vlist) {
518533
entry->vid = v->vid;
519-
err = __br_mdb_add(net, br, entry);
534+
err = __br_mdb_add(net, br, entry, &pg);
520535
if (err)
521536
break;
522-
__br_mdb_notify(dev, entry, RTM_NEWMDB);
537+
__br_mdb_notify(dev, entry, RTM_NEWMDB, pg);
523538
}
524539
} else {
525-
err = __br_mdb_add(net, br, entry);
540+
err = __br_mdb_add(net, br, entry, &pg);
526541
if (!err)
527-
__br_mdb_notify(dev, entry, RTM_NEWMDB);
542+
__br_mdb_notify(dev, entry, RTM_NEWMDB, pg);
528543
}
529544

530545
return err;
@@ -568,7 +583,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
568583
if (p->port->state == BR_STATE_DISABLED)
569584
goto unlock;
570585

571-
entry->state = p->state;
586+
__mdb_entry_fill_flags(entry, p->flags);
572587
rcu_assign_pointer(*pp, p->next);
573588
hlist_del_init(&p->mglist);
574589
del_timer(&p->timer);
@@ -620,12 +635,12 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
620635
entry->vid = v->vid;
621636
err = __br_mdb_del(br, entry);
622637
if (!err)
623-
__br_mdb_notify(dev, entry, RTM_DELMDB);
638+
__br_mdb_notify(dev, entry, RTM_DELMDB, NULL);
624639
}
625640
} else {
626641
err = __br_mdb_del(br, entry);
627642
if (!err)
628-
__br_mdb_notify(dev, entry, RTM_DELMDB);
643+
__br_mdb_notify(dev, entry, RTM_DELMDB, NULL);
629644
}
630645

631646
return err;

net/bridge/br_multicast.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
283283
rcu_assign_pointer(*pp, p->next);
284284
hlist_del_init(&p->mglist);
285285
del_timer(&p->timer);
286-
br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
287-
p->state);
286+
br_mdb_notify(br->dev, p, RTM_DELMDB);
288287
call_rcu_bh(&p->rcu, br_multicast_free_pg);
289288

290289
if (!mp->ports && !mp->mglist &&
@@ -304,7 +303,7 @@ static void br_multicast_port_group_expired(unsigned long data)
304303

305304
spin_lock(&br->multicast_lock);
306305
if (!netif_running(br->dev) || timer_pending(&pg->timer) ||
307-
hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT)
306+
hlist_unhashed(&pg->mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT)
308307
goto out;
309308

310309
br_multicast_del_pg(br, pg);
@@ -649,7 +648,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
649648
struct net_bridge_port *port,
650649
struct br_ip *group,
651650
struct net_bridge_port_group __rcu *next,
652-
unsigned char state)
651+
unsigned char flags)
653652
{
654653
struct net_bridge_port_group *p;
655654

@@ -659,7 +658,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
659658

660659
p->addr = *group;
661660
p->port = port;
662-
p->state = state;
661+
p->flags = flags;
663662
rcu_assign_pointer(p->next, next);
664663
hlist_add_head(&p->mglist, &port->mglist);
665664
setup_timer(&p->timer, br_multicast_port_group_expired,
@@ -702,11 +701,11 @@ static int br_multicast_add_group(struct net_bridge *br,
702701
break;
703702
}
704703

705-
p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY);
704+
p = br_multicast_new_port_group(port, group, *pp, 0);
706705
if (unlikely(!p))
707706
goto err;
708707
rcu_assign_pointer(*pp, p);
709-
br_mdb_notify(br->dev, port, group, RTM_NEWMDB, MDB_TEMPORARY);
708+
br_mdb_notify(br->dev, p, RTM_NEWMDB);
710709

711710
found:
712711
mod_timer(&p->timer, now + br->multicast_membership_interval);
@@ -975,7 +974,7 @@ void br_multicast_disable_port(struct net_bridge_port *port)
975974

976975
spin_lock(&br->multicast_lock);
977976
hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
978-
if (pg->state == MDB_TEMPORARY)
977+
if (!(pg->flags & MDB_PG_FLAGS_PERMANENT))
979978
br_multicast_del_pg(br, pg);
980979

981980
if (!hlist_unhashed(&port->rlist)) {
@@ -1453,8 +1452,7 @@ br_multicast_leave_group(struct net_bridge *br,
14531452
hlist_del_init(&p->mglist);
14541453
del_timer(&p->timer);
14551454
call_rcu_bh(&p->rcu, br_multicast_free_pg);
1456-
br_mdb_notify(br->dev, port, group, RTM_DELMDB,
1457-
p->state);
1455+
br_mdb_notify(br->dev, p, RTM_DELMDB);
14581456

14591457
if (!mp->ports && !mp->mglist &&
14601458
netif_running(br->dev))

net/bridge/br_private.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,17 @@ struct net_bridge_fdb_entry
150150
struct rcu_head rcu;
151151
};
152152

153+
#define MDB_PG_FLAGS_PERMANENT BIT(0)
154+
#define MDB_PG_FLAGS_OFFLOAD BIT(1)
155+
153156
struct net_bridge_port_group {
154157
struct net_bridge_port *port;
155158
struct net_bridge_port_group __rcu *next;
156159
struct hlist_node mglist;
157160
struct rcu_head rcu;
158161
struct timer_list timer;
159162
struct br_ip addr;
160-
unsigned char state;
163+
unsigned char flags;
161164
};
162165

163166
struct net_bridge_mdb_entry
@@ -554,11 +557,11 @@ void br_multicast_free_pg(struct rcu_head *head);
554557
struct net_bridge_port_group *
555558
br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
556559
struct net_bridge_port_group __rcu *next,
557-
unsigned char state);
560+
unsigned char flags);
558561
void br_mdb_init(void);
559562
void br_mdb_uninit(void);
560-
void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
561-
struct br_ip *group, int type, u8 state);
563+
void br_mdb_notify(struct net_device *dev, struct net_bridge_port_group *pg,
564+
int type);
562565
void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
563566
int type);
564567

0 commit comments

Comments
 (0)