[PATCH 6/6] VLAN: create NMDeviceVLAN and activate it
- From: Weiping Pan <wpan redhat com>
- To: networkmanager-list gnome org
- Subject: [PATCH 6/6] VLAN: create NMDeviceVLAN and activate it
- Date: Fri, 21 Oct 2011 09:52:55 +0800
When NetworkManager receives the message that a VLAN device is created in kernel,
it should create corresponding NMDeviceVLAN object, and then activate it.
Before activating a VLAN device, we should make sure that the underlying
physical ethernet device is up.
For example, before activating eth0.100, we should make sure that eth0 is up.
NetworkManager calls g_udev_client_query_by_subsystem() to get the device
list, and then activates each devices on that device list.
And luckily I found that the physical ethernet device is prior to VLAN device
on that device list, so there is nothing to do to make sure the activating
sequence between a VLAN device and its underlying physical ethernet device.
Signed-off-by: Weiping Pan <wpan redhat com>
---
src/nm-system.c | 31 ++++++++++++++
src/nm-system.h | 1 +
src/nm-udev-manager.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 136 insertions(+), 1 deletions(-)
diff --git a/src/nm-system.c b/src/nm-system.c
index 8696000..62d0961 100644
--- a/src/nm-system.c
+++ b/src/nm-system.c
@@ -1436,3 +1436,34 @@ free_cache:
nl_cache_free(cache);
return FALSE;
}
+
+/**
+ * nm_system_get_link_type:
+ * @name: name of link
+ *
+ * Lookup virtual link type. The returned string is allocated and needs
+ * to be freed after usage.
+ *
+ * Returns: Name of virtual link type or NULL if not a virtual link.
+ **/
+char *
+nm_system_get_link_type(const char *name)
+{
+ struct rtnl_link *result;
+ struct nl_sock *nlh;
+ char *type;
+
+ nlh = nm_netlink_get_default_handle ();
+ if (!nlh)
+ return NULL;
+
+ if (rtnl_link_get_kernel (nlh, 0, name, &result) < 0)
+ return NULL;
+
+ if ((type = rtnl_link_get_type (result)))
+ type = g_strdup(type);
+
+ rtnl_link_put (result);
+
+ return type;
+}
diff --git a/src/nm-system.h b/src/nm-system.h
index 93f942c..2f0e65c 100644
--- a/src/nm-system.h
+++ b/src/nm-system.h
@@ -92,4 +92,5 @@ gboolean nm_system_iface_set_mac (int ifindex, const struct eth
gboolean nm_system_add_vlan_device(NMSettingVLAN *setting);
gboolean nm_system_del_vlan_device(NMSettingVLAN *setting);
+char * nm_system_get_link_type (const char *name);
#endif
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c
index e8c6b82..3634423 100644
--- a/src/nm-udev-manager.c
+++ b/src/nm-udev-manager.c
@@ -42,6 +42,12 @@
#include "nm-device-wimax.h"
#endif
+#include "nm-system.h"
+#include "nm-device-vlan.h"
+#include "nm-setting-vlan.h"
+#include "nm-netlink-monitor.h"
+#include <netlink/route/link/vlan.h>
+
typedef struct {
GUdevClient *client;
@@ -388,6 +394,90 @@ is_wimax (const char *driver)
return g_strcmp0 (driver, "i2400m_usb") == 0;
}
+static gboolean
+is_vlan (const char *name)
+{
+ gboolean ret = FALSE;
+ struct rtnl_link *search_link = NULL;
+ struct nl_sock *nlh = NULL;
+ struct nl_cache *cache = NULL;
+
+ nlh = nm_netlink_get_default_handle();
+ if (!nlh)
+ return FALSE;
+
+ if (rtnl_link_alloc_cache(nlh, &cache) < 0)
+ return FALSE;
+
+ if (!cache)
+ return FALSE;
+
+ search_link = rtnl_link_get_by_name(cache, name);
+ if (!search_link)
+ goto free_cache;
+
+ if (rtnl_link_is_vlan(search_link))
+ ret = TRUE;
+
+ rtnl_link_put(search_link);
+
+ return ret;
+
+free_cache:
+ nl_cache_free(cache);
+ return FALSE;
+}
+
+static NMSettingVLAN *
+create_nm_settingvlan_from_gudev_device (GUdevDevice *device)
+{
+ struct rtnl_link *search_link = NULL;
+ struct nl_sock *nlh = NULL;
+ struct nl_cache *cache = NULL;
+
+ const char *interface_name;
+ int vlan_id;
+ int vlan_flags;
+
+ NMSettingVLAN * s_vlan = NULL;
+
+ interface_name = g_udev_device_get_name (device);
+ g_assert (interface_name);
+ nlh = nm_netlink_get_default_handle();
+ if (!nlh)
+ return FALSE;
+
+ if (rtnl_link_alloc_cache(nlh, &cache) < 0)
+ return FALSE;
+
+ if (!cache)
+ return FALSE;
+
+ search_link = rtnl_link_get_by_name(cache, interface_name);
+ if (!search_link)
+ goto free_cache;
+
+ if (rtnl_link_is_vlan(search_link)) {
+ vlan_id = rtnl_link_vlan_get_id(search_link);
+ vlan_flags = rtnl_link_vlan_get_flags(search_link);
+ // TODO
+ // ingress and egress priority mapping
+ }
+
+ rtnl_link_put(search_link);
+
+ s_vlan = NM_SETTING_VLAN(nm_setting_vlan_new());
+ g_object_set(s_vlan, NM_SETTING_VLAN_INTERFACE_NAME, interface_name, NULL);
+ g_object_set(s_vlan, NM_SETTING_VLAN_VLAN_ID, vlan_id, NULL);
+ g_object_set(s_vlan, NM_SETTING_VLAN_VLAN_FLAGS, vlan_flags, NULL);
+
+ return s_vlan;
+
+free_cache:
+ nl_cache_free(cache);
+ return NULL;
+}
+
static GObject *
device_creator (NMUdevManager *manager,
GUdevDevice *udev_device,
@@ -430,7 +520,15 @@ device_creator (NMUdevManager *manager,
}
if (!driver) {
- if (g_str_has_prefix (ifname, "easytether")) {
+ char *type = NULL;
+
+ type = nm_system_get_link_type (ifname);
+ if (type) {
+ if (g_strcmp0 (type, "vlan") == 0)
+ driver = "8021q";
+
+ g_free(type);
+ } else if (g_str_has_prefix (ifname, "easytether")) {
driver = "easytether";
} else {
nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path);
@@ -452,6 +550,11 @@ device_creator (NMUdevManager *manager,
#if WITH_WIMAX
device = (GObject *) nm_device_wimax_new (path, ifname, driver);
#endif
+ } else if (is_vlan(ifname)) {
+ NMSettingVLAN *s_vlan = NULL;
+ s_vlan = (NMSettingVLAN *)create_nm_settingvlan_from_gudev_device(udev_device);
+ device = (GObject *) nm_device_vlan_new(s_vlan);
+ g_object_unref(s_vlan);
} else
device = (GObject *) nm_device_ethernet_new (path, ifname, driver);
--
1.7.4.4
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]