diff mbox series

[2/3] bridge: allow adding vlans to a bridge

Message ID 20200712165020.249741-3-john@phrozen.org
State Under Review
Delegated to: John Crispin
Headers show
Series netifd: add bridge/vlan support | expand

Commit Message

John Crispin July 12, 2020, 4:50 p.m. UTC
Add a rtnl helper for adding vlans to a bridge interface.

Signed-off-by: John Crispin <john@phrozen.org>
---
 system-linux.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 system.h       |  1 +
 2 files changed, 49 insertions(+)
diff mbox series

Patch

diff --git a/system-linux.c b/system-linux.c
index 97b38e7..130d057 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -854,6 +854,54 @@  int system_bridge_delif(struct device *bridge, struct device *dev)
 	return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
 }
 
+int system_bridge_vlan(const char *iface, int pvid, int vid, int tagged,
+		       int self, int add)
+{
+	struct ifinfomsg ifi = { .ifi_family = PF_BRIDGE, };
+	struct bridge_vlan_info vinfo = { .vid = vid, };
+	unsigned short flags = 0;
+	struct nlattr *afspec;
+	struct nl_msg *nlm;
+	int ret = 0;
+
+	ifi.ifi_index = if_nametoindex(iface);
+	if (!ifi.ifi_index)
+		return -1;
+
+	nlm = nlmsg_alloc_simple(add ? RTM_SETLINK : RTM_DELLINK, NLM_F_REQUEST);
+	if (!nlm)
+		return -1;
+
+	nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
+
+	if (self)
+		flags |= BRIDGE_FLAGS_SELF;
+
+	if (pvid)
+		vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
+
+	if (!tagged)
+		vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
+
+	afspec = nla_nest_start(nlm, IFLA_AF_SPEC);
+	if (!afspec) {
+		ret = -ENOMEM;
+		goto failure;
+	}
+
+	if (flags)
+		nla_put_u16(nlm, IFLA_BRIDGE_FLAGS, flags);
+
+	nla_put(nlm, IFLA_BRIDGE_VLAN_INFO, sizeof(vinfo), &vinfo);
+	nla_nest_end(nlm, afspec);
+
+	return system_rtnl_call(nlm);
+
+failure:
+	nlmsg_free(nlm);
+	return ret;
+}
+
 int system_if_resolve(struct device *dev)
 {
 	struct ifreq ifr;
diff --git a/system.h b/system.h
index 258b1af..6a7f738 100644
--- a/system.h
+++ b/system.h
@@ -196,6 +196,7 @@  int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg);
 int system_bridge_delbr(struct device *bridge);
 int system_bridge_addif(struct device *bridge, struct device *dev);
 int system_bridge_delif(struct device *bridge, struct device *dev);
+int system_bridge_vlan(const char *iface, int pvid, int vid, int tagged, int self, int add);
 
 int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg);
 int system_macvlan_del(struct device *macvlan);