Commit 0c3efb17 authored by Dan Williams's avatar Dan Williams
Browse files

vlan: rework VLAN interface creation/deletion

First make it build on libnl1/2.  Second, the VLAN
virtual interface name might not always be given in the
NMConnection (if the master is a UUID and thus the name
is determined automatically) so just take the interface
name instead.  And make sure we verify it's a VLAN
interface before deleting it.

Lastly, construct the VLAN interface name if it's not
given in the NMConnection.  This means we need to know
the master interface name when creating the connection,
which we always will since you can't create the VLAN
interface without it's master being present.  That also
means we need to return the name to the caller so it
can be used to create the NMDevice for the VLAN interface
after we've created it in the kernel.
parent ab43b7b4
......@@ -243,6 +243,55 @@ rtnl_link_bond_release_ifindex (struct nl_sock *h, int slave_ifidx)
/* Bonding only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_vlan_set_id (struct rtnl_link *l, int id)
{
/* VLAN only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_vlan_set_flags (struct rtnl_link *l, unsigned int flags)
{
/* VLAN only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_vlan_set_ingress_map (struct rtnl_link *l, int from, uint32_t to)
{
/* VLAN only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_vlan_set_egress_map (struct rtnl_link *l, int from, uint32_t to)
{
/* VLAN only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_set_type (struct rtnl_link *l, const char *type)
{
/* Operation only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_add (struct nl_sock *sk, struct rtnl_link *l, int flags)
{
/* Operation only in libnl3 */
return -NLE_OPNOTSUPP;
}
static inline int
rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *l)
{
/* Operation only in libnl3 */
return -NLE_OPNOTSUPP;
}
#endif /* HAVE_LIBNL1 || HAVE_LIBNL2 */
#endif /* NM_NETLINK_COMPAT_H */
......@@ -59,10 +59,10 @@
#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>
#include <netlink/route/link/vlan.h>
#endif
static void nm_system_device_set_priority (int ifindex,
......@@ -1529,130 +1529,114 @@ out:
return res;
}
static void ingress_priority_iterator (gpointer data, gpointer user_data)
{
struct rtnl_link *new_link = user_data;
vlan_priority_map *item = 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 = user_data;
vlan_priority_map *item = 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
* nm_system_add_vlan_iface:
* @connection: the #NMConnection that describes the VLAN interface
* @iface: the interface name of the new VLAN interface
* @master_ifindex: the interface index of the new VLAN interface's master
* interface
*
* Add a VLAN device specified in @setting.
* Add a VLAN device named @iface and specified in @connection.
*
* Returns: %TRUE on success, or %FALSE
* Returns: %TRUE on success, %FALSE on failure
*/
gboolean
nm_system_add_vlan_device (NMSettingVlan *setting)
nm_system_add_vlan_iface (NMConnection *connection,
const char *iface,
int master_ifindex)
{
int ret = 0;
int if_index = 0;
NMSettingVlan *s_vlan;
int ret = -1;
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;
guint32 num, i, from, to;
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);
g_return_val_if_fail (master_ifindex >= 0, 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);
s_vlan = nm_connection_get_setting_vlan (connection);
g_return_val_if_fail (s_vlan, FALSE);
vlan_id = nm_setting_vlan_get_id (s_vlan);
if_index = nm_netlink_iface_to_index (vlan_slave);
g_return_val_if_fail (if_index > 0, FALSE);
if (!iface) {
iface = nm_connection_get_virtual_iface_name (connection);
g_return_val_if_fail (iface != NULL, FALSE);
}
new_link = rtnl_link_alloc ();
g_return_val_if_fail (new_link != NULL, FALSE);
if (!new_link) {
g_warn_if_fail (new_link != NULL);
goto out;
}
ret = rtnl_link_set_type (new_link, "vlan");
if (ret < 0)
goto free_new_link;
goto out;
rtnl_link_set_link (new_link, if_index);
rtnl_link_set_name (new_link, interface_name);
rtnl_link_set_link (new_link, master_ifindex);
rtnl_link_set_name (new_link, iface);
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, new_link);
vlan_flags = nm_setting_vlan_get_flags (s_vlan);
if (vlan_flags) {
guint kernel_flags = 0;
list = nm_setting_vlan_get_egress_priority_map (setting);
if (list != NULL)
g_slist_foreach((GSList *)list, (GFunc)egress_priority_iterator, new_link);
if (vlan_flags & NM_VLAN_FLAG_REORDER_HEADERS)
kernel_flags |= VLAN_FLAG_REORDER_HDR;
if (vlan_flags & NM_VLAN_FLAG_GVRP)
kernel_flags |= VLAN_FLAG_GVRP;
if (vlan_flags & NM_VLAN_FLAG_LOOSE_BINDING)
kernel_flags |= VLAN_FLAG_LOOSE_BINDING;
ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE);
if (ret < 0)
goto free_new_link;
rtnl_link_vlan_set_flags (new_link, kernel_flags);
}
rtnl_link_put (new_link);
num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP);
for (i = 0; i < num; i++) {
if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to))
rtnl_link_vlan_set_ingress_map (new_link, (int) from, (int) to);
}
return TRUE;
num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP);
for (i = 0; i < num; i++) {
if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to))
rtnl_link_vlan_set_egress_map (new_link, (int) from, (int) to);
}
free_new_link:
rtnl_link_put (new_link);
ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE);
return FALSE;
out:
if (new_link)
rtnl_link_put (new_link);
return (ret == 0);
}
/**
* nm_system_del_vlan_device:
* @setting: NMSettingVlan
* nm_system_del_vlan_iface:
* @iface: the interface name
*
* Delete a VLAN device specified in @setting.
* Delete a VLAN interface specified by @iface.
*
* Returns: %TRUE on success, or %FALSE
*/
gboolean
nm_system_del_vlan_device (NMSettingVlan *setting)
nm_system_del_vlan_iface (const char *iface)
{
int ret = 0;
struct nl_sock *nlh = NULL;
struct nl_cache *cache = NULL;
struct rtnl_link *new_link = NULL;
const char *interface_name = NULL;
int itype;
g_return_val_if_fail (iface != NULL, FALSE);
interface_name = nm_setting_vlan_get_interface_name (setting);
g_return_val_if_fail (interface_name != NULL, FALSE);
itype = nm_system_get_iface_type (-1, iface);
g_return_val_if_fail (itype == NM_IFACE_TYPE_VLAN, FALSE);
nlh = nm_netlink_get_default_handle ();
g_return_val_if_fail (nlh != NULL, FALSE);
......@@ -1661,22 +1645,12 @@ nm_system_del_vlan_device (NMSettingVlan *setting)
g_return_val_if_fail (ret == 0, FALSE);
g_return_val_if_fail (cache != NULL, 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);
new_link = rtnl_link_get_by_name (cache, iface);
if (new_link) {
ret = rtnl_link_delete (nlh, new_link);
rtnl_link_put (new_link);
}
free_cache:
nl_cache_free (cache);
return FALSE;
return (ret == 0) ? TRUE : FALSE;
}
......@@ -103,7 +103,9 @@ enum {
int nm_system_get_iface_type (int ifindex, const char *name);
gboolean nm_system_add_vlan_device (NMSettingVlan *setting);
gboolean nm_system_del_vlan_device (NMSettingVlan *setting);
gboolean nm_system_add_vlan_iface (NMConnection *connection,
const char *iface,
int master_ifindex);
gboolean nm_system_del_vlan_iface (const char *iface);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment