Re: [PATCH 3/6] VLAN: create/delete kernel vlan device
- From: Dan Williams <dcbw redhat com>
- To: Weiping Pan <wpan redhat com>
- Cc: networkmanager-list gnome org
- Subject: Re: [PATCH 3/6] VLAN: create/delete kernel vlan device
- Date: Tue, 15 Nov 2011 23:43:28 -0600
On Fri, 2011-10-21 at 09:52 +0800, Weiping Pan wrote:
> 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;
We've got:
/* Generic utility functions */
int nm_netlink_iface_to_index (const char *iface);
char * nm_netlink_index_to_iface (int idx);
struct rtnl_link *nm_netlink_index_to_rtnl_link (int idx);
struct nl_sock * nm_netlink_get_default_handle (void);
in nm-netlink-monitor.c that we can use here to grab links and do
name<->index lookups. The one thing that's missing would be
nm_netlink_iface_to_rtnl_link() which we should add, and then you don't
have to go through 10 lines to get links and lookups.
> + 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);
Yeah, best to parse these when reading them in. Note that when that's
being done in ifcfg-rh/reader.c for the next revision, you can use
g_strsplit_set (<string>, ",") and it'll give you a NULL terminated
char** (which you can free with g_strfreev() when you're done with it),
ie something like this:
char **split, **iter;
iter = split = g_strsplit_set (string, ",");
if (!split)
return;
while (iter && *iter) {
<do something with *iter>
}
g_strfreev (split);
Dan
> + 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]