[PATCH 3/6] VLAN: create/delete kernel vlan device
- From: Weiping Pan <wpan redhat com>
- To: networkmanager-list gnome org
- Subject: [PATCH 3/6] VLAN: create/delete kernel vlan device
- Date: Fri, 21 Oct 2011 09:52:52 +0800
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.
Signed-off-by: Weiping Pan <wpan redhat com>
---
src/nm-system.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/nm-system.h | 3 +
2 files changed, 237 insertions(+), 0 deletions(-)
diff --git a/src/nm-system.c b/src/nm-system.c
index 62ab8b9..8696000 100644
--- a/src/nm-system.c
+++ b/src/nm-system.c
@@ -56,6 +56,7 @@
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
+#include <netlink/route/link/vlan.h>
static void nm_system_device_set_priority (int ifindex,
NMIP4Config *config,
@@ -1202,3 +1203,236 @@ nm_system_device_set_priority (int ifindex,
rtnl_route_put (found);
}
}
+
+static void priority_parser(GHashTable *table, char *str, const char *delim, char *subdelim)
+{
+ char *str1, *str2, *token, *key = NULL, *value = NULL;
+ char *saveptr1, *saveptr2;
+ int j;
+
+ if (!table)
+ return;
+
+ for (j = 1, str1 = str; ; j++, str1 = NULL) {
+ int i;
+ token = strtok_r(str1, delim, &saveptr1);
+ if (token == NULL)
+ break;
+
+ i = 0;
+ for (str2 = token; ; str2 = NULL) {
+ if (i == 0) {
+ key = strtok_r(str2, subdelim, &saveptr2);
+ if (key == NULL)
+ break;
+ i++;
+ } else if (i == 1) {
+ value = strtok_r(str2, subdelim, &saveptr2);
+ if (value == NULL)
+ break;
+ i = 0;
+ g_hash_table_insert(table, key, value);
+ }
+ }
+ }
+
+}
+
+static void ingress_priority_iterator(gpointer key, gpointer value ,gpointer user_data)
+{
+ struct rtnl_link *new_link = (struct rtnl_link *)user_data;
+ int from;
+ uint32_t to;
+
+ errno = 0;
+ from = strtol((char *)key, NULL, 10);
+ if (errno == ERANGE)
+ return;
+
+ errno = 0;
+ to = strtol((char *)value, NULL, 10);
+ if (errno == ERANGE)
+ return;
+ if ((from < 0) || (from > 7))
+ return;
+ rtnl_link_vlan_set_ingress_map(new_link, from, to);
+}
+
+static void egress_priority_iterator(gpointer key, gpointer value ,gpointer user_data)
+{
+ struct rtnl_link *new_link = (struct rtnl_link *)user_data;
+ uint32_t from;
+ int to;
+
+ errno = 0;
+ from = strtol((char *)key, NULL, 10);
+ if (errno == ERANGE)
+ return;
+
+ errno = 0;
+ to = strtol((char *)value, NULL, 10);
+ if (errno == ERANGE)
+ return;
+ if ((to < 0) || (to > 7))
+ return;
+ rtnl_link_vlan_set_egress_map(new_link, from, 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 *orig_link = NULL, *new_link = NULL;
+ struct nl_sock *nlh = NULL;
+ struct nl_cache *cache = NULL;
+
+ const char *interface_name = NULL;
+ const char *vlan_slave = NULL;
+ guint32 vlan_id = 0;
+ guint32 vlan_flags = 0;
+
+ const char *delim = ",";
+ char *subdelim = ":";
+ GHashTable *table;
+
+ vlan_slave = nm_setting_vlan_get_vlan_slave(setting);
+ if (!vlan_slave)
+ return FALSE;
+
+ vlan_id = nm_setting_vlan_get_vlan_id(setting);
+ if (vlan_id == 0)
+ 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;
+
+ orig_link = rtnl_link_get_by_name(cache, vlan_slave);
+ if (!orig_link)
+ goto free_cache;
+
+ if_index = rtnl_link_get_ifindex(orig_link);
+ if (if_index <= 0)
+ goto free_orig_link;
+
+ new_link = rtnl_link_alloc();
+ if (!new_link)
+ goto free_orig_link;
+
+ 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_vlan_set_id(new_link, vlan_id);
+
+ interface_name = nm_setting_vlan_get_interface_name(setting);
+ if (interface_name)
+ rtnl_link_set_name(new_link, interface_name);
+
+ vlan_flags = nm_setting_vlan_get_vlan_flags(setting);
+ if (vlan_flags)
+ rtnl_link_vlan_set_flags(new_link, vlan_flags);
+
+ table = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!table)
+ goto free_new_link;
+
+ priority_parser(table, (char *)nm_setting_vlan_get_vlan_priority_ingress_map(setting), delim, subdelim);
+ g_hash_table_foreach(table, (GHFunc)ingress_priority_iterator, (gpointer)new_link);
+ g_hash_table_destroy(table);
+
+ table = g_hash_table_new(g_str_hash, g_str_equal);
+ if (!table)
+ goto free_new_link;
+ priority_parser(table, (char *)nm_setting_vlan_get_vlan_priority_egress_map(setting), delim, subdelim);
+ g_hash_table_foreach(table, (GHFunc)egress_priority_iterator, (gpointer)new_link);
+ g_hash_table_destroy(table);
+
+ ret = rtnl_link_add(nlh, new_link, NLM_F_CREATE);
+ if (ret < 0)
+ goto free_new_link;
+
+ rtnl_link_put(orig_link);
+ rtnl_link_put(new_link);
+
+ return TRUE;
+
+free_new_link:
+ rtnl_link_put(new_link);
+
+free_orig_link:
+ rtnl_link_put(orig_link);
+
+free_cache:
+ nl_cache_free(cache);
+ 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 ae4e7d9..93f942c 100644
--- a/src/nm-system.h
+++ b/src/nm-system.h
@@ -30,6 +30,7 @@
#include <glib.h>
#include "nm-device.h"
#include "nm-ip4-config.h"
+#include "nm-setting-vlan.h"
/* Prototypes for system/distribution dependent functions,
* implemented in the backend files in backends/ directory
@@ -88,5 +89,7 @@ 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_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]