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? 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 > 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 <[email protected]> > --- > 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); > _______________________________________________ networkmanager-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/networkmanager-list
