History

net: bridge: vlan: add rtnetlink group and notify support

Add a new rtnetlink group for bridge vlan notifications - RTNLGRP_BRVLAN and add support for sending vlan notifications (both single and ranges). No functional changes intended, the notification support will be used by later patches.

Nikolay Aleksandrov committed 6 years ago

Commit cf5bddb1 parent 0ab55873 files · +92 −0Browse files

Unified · Split

3 files
  1. include/uapi/linux/rtnetlink.h +2 −0
  2. net/bridge/br_private.h +11 −0
  3. net/bridge/br_vlan.c +79 −0
include/uapi/linux/rtnetlink.h+2−0
@@ -730,6 +730,8 @@ enum rtnetlink_groups { · 729 unmodified lines
730#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R730#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
731 RTNLGRP_NEXTHOP,731 RTNLGRP_NEXTHOP,
732#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP732#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
733 RTNLGRP_BRVLAN,
734#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
733 __RTNLGRP_MAX735 __RTNLGRP_MAX
734};736};
735#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)737#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
net/bridge/br_private.h+11−0
@@ -960,6 +960,10 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, · 959 unmodified lines
960 void *ptr);960 void *ptr);
961void br_vlan_rtnl_init(void);961void br_vlan_rtnl_init(void);
962void br_vlan_rtnl_uninit(void);962void br_vlan_rtnl_uninit(void);
963void br_vlan_notify(const struct net_bridge *br,
964 const struct net_bridge_port *p,
965 u16 vid, u16 vid_range,
966 int cmd);
963 967
964static inline struct net_bridge_vlan_group *br_vlan_group(968static inline struct net_bridge_vlan_group *br_vlan_group(
965 const struct net_bridge *br)969 const struct net_bridge *br)
@@ -1166,6 +1170,13 @@ static inline void br_vlan_rtnl_init(void) · 200 unmodified lines
1166static inline void br_vlan_rtnl_uninit(void)1170static inline void br_vlan_rtnl_uninit(void)
1167{1171{
1168}1172}
1173
1174static inline void br_vlan_notify(const struct net_bridge *br,
1175 const struct net_bridge_port *p,
1176 u16 vid, u16 vid_range,
1177 int cmd)
1178{
1179}
1169#endif1180#endif
1170 1181
1171struct nf_br_ops {1182struct nf_br_ops {
net/bridge/br_vlan.c+79−0
@@ -1540,6 +1540,85 @@ out_err: · 1539 unmodified lines
1540 return false;1540 return false;
1541}1541}
1542 1542
1543static size_t rtnl_vlan_nlmsg_size(void)
1544{
1545 return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
1546 + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */
1547 + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */
1548 + nla_total_size(sizeof(struct bridge_vlan_info)); /* BRIDGE_VLANDB_ENTRY_INFO */
1549}
1550
1551void br_vlan_notify(const struct net_bridge *br,
1552 const struct net_bridge_port *p,
1553 u16 vid, u16 vid_range,
1554 int cmd)
1555{
1556 struct net_bridge_vlan_group *vg;
1557 struct net_bridge_vlan *v;
1558 struct br_vlan_msg *bvm;
1559 struct nlmsghdr *nlh;
1560 struct sk_buff *skb;
1561 int err = -ENOBUFS;
1562 struct net *net;
1563 u16 flags = 0;
1564 int ifindex;
1565
1566 /* right now notifications are done only with rtnl held */
1567 ASSERT_RTNL();
1568
1569 if (p) {
1570 ifindex = p->dev->ifindex;
1571 vg = nbp_vlan_group(p);
1572 net = dev_net(p->dev);
1573 } else {
1574 ifindex = br->dev->ifindex;
1575 vg = br_vlan_group(br);
1576 net = dev_net(br->dev);
1577 }
1578
1579 skb = nlmsg_new(rtnl_vlan_nlmsg_size(), GFP_KERNEL);
1580 if (!skb)
1581 goto out_err;
1582
1583 err = -EMSGSIZE;
1584 nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*bvm), 0);
1585 if (!nlh)
1586 goto out_err;
1587 bvm = nlmsg_data(nlh);
1588 memset(bvm, 0, sizeof(*bvm));
1589 bvm->family = AF_BRIDGE;
1590 bvm->ifindex = ifindex;
1591
1592 switch (cmd) {
1593 case RTM_NEWVLAN:
1594 /* need to find the vlan due to flags/options */
1595 v = br_vlan_find(vg, vid);
1596 if (!v || !br_vlan_should_use(v))
1597 goto out_kfree;
1598
1599 flags = v->flags;
1600 if (br_get_pvid(vg) == v->vid)
1601 flags |= BRIDGE_VLAN_INFO_PVID;
1602 break;
1603 case RTM_DELVLAN:
1604 break;
1605 default:
1606 goto out_kfree;
1607 }
1608
1609 if (!br_vlan_fill_vids(skb, vid, vid_range, flags))
1610 goto out_err;
1611
1612 nlmsg_end(skb, nlh);
1613 rtnl_notify(skb, net, 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL);
1614 return;
1615
1616out_err:
1617 rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err);
1618out_kfree:
1619 kfree_skb(skb);
1620}
1621
1543/* check if v_curr can enter a range ending in range_end */1622/* check if v_curr can enter a range ending in range_end */
1544static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,1623static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
1545 const struct net_bridge_vlan *range_end)1624 const struct net_bridge_vlan *range_end)