[PATCH 3/5] vlan: create/delete kernel vlan device



We make use of libnl (>=3.2.1) to create/delete kernel vlan device,
and it can set vlan id, vlan flags and ingress/egress priority mapping.

V2:
1 use existing nm_netlink_iface_to_index()

Signed-off-by: Weiping Pan <wpan redhat com>
---
 src/nm-system.c |  156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/nm-system.h |    5 ++-
 2 files changed, 160 insertions(+), 1 deletions(-)

diff --git a/src/nm-system.c b/src/nm-system.c
index 709a08b..8f9ddc8 100644
--- a/src/nm-system.c
+++ b/src/nm-system.c
@@ -59,6 +59,7 @@
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/link.h>
+#include <netlink/route/link/vlan.h>
 
 #ifdef HAVE_LIBNL3
 #include <netlink/route/link/bonding.h>
@@ -1453,3 +1454,158 @@ nm_system_get_link_type (const char *name)
 	return type;
 }
 
+static void ingress_priority_iterator(gpointer data, gpointer user_data)
+{
+	struct rtnl_link *new_link = (struct rtnl_link *)user_data;
+	vlan_priority_map *item = (vlan_priority_map *)data;
+
+	g_return_if_fail (item != NULL);
+	g_return_if_fail (new_link!= NULL);
+
+	if ((item->from < 0) || (item->from > 7))
+		return;
+	rtnl_link_vlan_set_ingress_map(new_link, item->from, item->to);
+}
+
+static void egress_priority_iterator(gpointer data, gpointer user_data)
+{
+	struct rtnl_link *new_link = (struct rtnl_link *)user_data;
+	vlan_priority_map *item = (vlan_priority_map *)data;
+
+	g_return_if_fail (item != NULL);
+	g_return_if_fail (new_link!= NULL);
+
+	if ((item->to < 0) || (item->to > 7))
+		return;
+
+	rtnl_link_vlan_set_egress_map(new_link, item->from, item->to);
+}
+
+/**
+ * nm_system_add_vlan_device:
+ * @setting: NMSettingVlan
+ *
+ * Add a VLAN device specified in setting.
+ *
+ * Returns: %TRUE on success, or %FALSE
+ */
+gboolean
+nm_system_add_vlan_device(NMSettingVlan *setting)
+{
+	int ret = 0;
+	int if_index = 0;
+	struct rtnl_link *new_link = NULL;
+	struct nl_sock *nlh = NULL;
+	const GSList *list = NULL;
+
+	const char *interface_name = NULL;
+	const char *vlan_slave = NULL;
+	guint32 vlan_id = 0;
+	guint32 vlan_flags = 0;
+
+	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+
+	vlan_slave = nm_setting_vlan_get_slave(setting);
+	g_return_val_if_fail (vlan_slave != NULL, FALSE);
+
+	vlan_id = nm_setting_vlan_get_id(setting);
+	g_return_val_if_fail (vlan_id != 0, FALSE);
+	g_return_val_if_fail (vlan_id < 4096, FALSE);
+
+	nlh = nm_netlink_get_default_handle();
+	g_return_val_if_fail (nlh != NULL, FALSE);
+
+	interface_name = nm_setting_vlan_get_interface_name(setting);
+	g_return_val_if_fail (interface_name != NULL, FALSE);
+
+	if_index = nm_netlink_iface_to_index(interface_name);
+	g_return_val_if_fail (if_index > 0, FALSE);
+
+	new_link = rtnl_link_alloc();
+	g_return_val_if_fail (new_link != NULL, FALSE);
+
+	ret = rtnl_link_set_type(new_link, "vlan");
+	if (ret < 0)
+		goto free_new_link;
+
+	rtnl_link_set_link(new_link, if_index);
+	rtnl_link_set_name(new_link, interface_name);
+	rtnl_link_vlan_set_id(new_link, vlan_id);
+
+	vlan_flags = nm_setting_vlan_get_flags(setting);
+	if (vlan_flags)
+		rtnl_link_vlan_set_flags(new_link, vlan_flags);
+
+	list = nm_setting_vlan_get_ingress_priority_map(setting);
+	if (list != NULL)
+		g_slist_foreach((GSList *)list, (GFunc)ingress_priority_iterator, (gpointer)new_link);
+
+	list = nm_setting_vlan_get_egress_priority_map(setting);
+	if (list != NULL)
+		g_slist_foreach((GSList *)list, (GFunc)egress_priority_iterator, (gpointer)new_link);
+
+	ret = rtnl_link_add(nlh, new_link, NLM_F_CREATE);
+	if (ret < 0)
+		goto free_new_link;
+
+	rtnl_link_put(new_link);
+
+	return TRUE;
+
+free_new_link:
+	rtnl_link_put(new_link);
+
+	return FALSE;
+}
+
+/**
+ * nm_system_del_vlan_device:
+ * @setting: NMSettingVlan
+ *
+ * Delete a VLAN device specified in setting.
+ *
+ * Returns: %TRUE on success, or %FALSE
+ */
+gboolean
+nm_system_del_vlan_device(NMSettingVlan *setting)
+{
+	int ret = 0;
+	struct nl_sock *nlh = NULL;
+	struct nl_cache *cache = NULL;
+	struct rtnl_link *new_link = NULL;
+	const char *interface_name = NULL;
+
+	interface_name = nm_setting_vlan_get_interface_name(setting);
+	if (!interface_name)
+		return FALSE;
+
+	nlh = nm_netlink_get_default_handle();
+	if (!nlh)
+		return FALSE;
+
+	ret = rtnl_link_alloc_cache(nlh, &cache);
+	if (ret < 0)
+		return FALSE;
+
+	if (!cache)
+		return FALSE;
+
+	new_link = rtnl_link_get_by_name(cache, interface_name);
+	if (!new_link)
+		goto free_cache;
+
+	ret = rtnl_link_delete(nlh, new_link);
+	if (ret < 0)
+		goto free_new_link;
+
+	rtnl_link_put(new_link);
+
+	return TRUE;
+
+free_new_link:
+	rtnl_link_put(new_link);
+
+free_cache:
+	nl_cache_free(cache);
+	return FALSE;
+}
diff --git a/src/nm-system.h b/src/nm-system.h
index 339dfa7..5527b7d 100644
--- a/src/nm-system.h
+++ b/src/nm-system.h
@@ -31,6 +31,7 @@
 #include "nm-device.h"
 #include "nm-ip4-config.h"
 #include "nm-setting-bond.h"
+#include "nm-setting-vlan.h"
 
 /* Prototypes for system/distribution dependent functions,
  * implemented in the backend files in backends/ directory
@@ -90,11 +91,13 @@ gboolean        nm_system_iface_is_up                   (int ifindex);
 gboolean		nm_system_iface_set_mtu                 (int ifindex, guint32 mtu);
 
 gboolean		nm_system_iface_set_mac                 (int ifindex, const struct ether_addr *mac);
-
 gboolean		nm_system_add_bonding_master	(NMSettingBond *setting);
 gboolean		nm_system_iface_enslave		(NMDevice *slave, NMDevice *master);
 gboolean		nm_system_iface_release		(NMDevice *slave, NMDevice *master);
 
 char *			nm_system_get_link_type		(const char *name);
 
+gboolean		nm_system_add_vlan_device(NMSettingVlan *setting);
+gboolean		nm_system_del_vlan_device(NMSettingVlan *setting);
+
 #endif
-- 
1.7.4.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]