Re: [PATCH 6/6] VLAN: create NMDeviceVLAN and activate it



On 11/16/2011 02:10 PM, Dan Williams wrote:
On Fri, 2011-10-21 at 09:52 +0800, Weiping Pan wrote:
When NetworkManager receives the message that a VLAN device is created in kernel,
it should create corresponding NMDeviceVLAN object, and then activate it.
Instead of creating a new VLAN setting and passing it into
nm_device_vlan_new(), can't we just pass the interface name in?
Ok.
The second issue is that this code would automatically detect VLAN
interfaces created outside NM; that's not extremely useful because the
tool that created the interface probably wants to set it up too, and if
it doesn't, then it should probably just be telling NM to set it up
instead of creating the VLAN interface and then telling NM to configure
it.  So we need to figure out what to do here so we don't step on
anyones toes and we interoperate in a way people expect.

At the moment my thought is to make NM ignore any VLAN interfaces it
doesn't create - the simplest choice and the clearest from an
interoperability standpoint.

If we recognize externally created VLAN interfaces, chances are that
we'll overwrite whatever the thing that created it did.  I'm not sure
there's a point to creating a VLAN and then telling NM to configure it,
so why not just have NM create the VLAN and configure it.  Taking over
existing configured devices is pretty tricky in most cases, and we only
support it for wired interfaces right now (and not for wired interfaces
that use 802.1x) because when taking over management of an interface we
need to take over *all* of it, including DHCP leases,
802.1x/wpa_supplicnat, PPP control, etc.  And we don't do all of that
yet...

Dan

I thought NetworkManager should control all interfaces of a host,
no matter how they are created, then we can monitor states and traffics of all interfaces.

Ok, let me ignore external created vlan interfaces at present,
we can handle them in the future.

thanks
Weiping Pan
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);





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