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