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
730730 #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
731731 RTNLGRP_NEXTHOP,
732732 #define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
733+ RTNLGRP_BRVLAN,
734+#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
733735 __RTNLGRP_MAX
734736 };
735737 #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
960960 void *ptr);
961961 void br_vlan_rtnl_init(void);
962962 void br_vlan_rtnl_uninit(void);
963+void br_vlan_notify(const struct net_bridge *br,
964+ const struct net_bridge_port *p,
965+ u16 vid, u16 vid_range,
966+ int cmd);
963967
964968 static inline struct net_bridge_vlan_group *br_vlan_group(
965969 const struct net_bridge *br)
@@ -1166,6 +1170,13 @@ static inline void br_vlan_rtnl_init(void) · 200 unmodified lines
11661170 static inline void br_vlan_rtnl_uninit(void)
11671171 {
11681172 }
1173+
1174+static 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+}
11691180 #endif
11701181
11711182 struct nf_br_ops {
net/bridge/br_vlan.c+79−0
@@ -1540,6 +1540,85 @@ out_err: · 1539 unmodified lines
15401540 return false;
15411541 }
15421542
1543+static 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+
1551+void 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+
1616+out_err:
1617+ rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err);
1618+out_kfree:
1619+ kfree_skb(skb);
1620+}
1621+
15431622 /* check if v_curr can enter a range ending in range_end */
15441623 static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
15451624 const struct net_bridge_vlan *range_end)