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.
This commit is contained in:
@@ -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 */
|
||||
|
168
src/nm-system.c
168
src/nm-system.c
@@ -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);
|
||||
|
||||
if_index = nm_netlink_iface_to_index (vlan_slave);
|
||||
g_return_val_if_fail (if_index > 0, FALSE);
|
||||
vlan_id = nm_setting_vlan_get_id (s_vlan);
|
||||
|
||||
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);
|
||||
vlan_flags = nm_setting_vlan_get_flags (s_vlan);
|
||||
if (vlan_flags) {
|
||||
guint kernel_flags = 0;
|
||||
|
||||
list = nm_setting_vlan_get_ingress_priority_map (setting);
|
||||
if (list != NULL)
|
||||
g_slist_foreach ((GSList *)list, (GFunc)ingress_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;
|
||||
|
||||
list = nm_setting_vlan_get_egress_priority_map (setting);
|
||||
if (list != NULL)
|
||||
g_slist_foreach((GSList *)list, (GFunc)egress_priority_iterator, new_link);
|
||||
rtnl_link_vlan_set_flags (new_link, kernel_flags);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ret = rtnl_link_add (nlh, new_link, NLM_F_CREATE);
|
||||
if (ret < 0)
|
||||
goto free_new_link;
|
||||
|
||||
out:
|
||||
if (new_link)
|
||||
rtnl_link_put (new_link);
|
||||
|
||||
return TRUE;
|
||||
|
||||
free_new_link:
|
||||
rtnl_link_put (new_link);
|
||||
|
||||
return FALSE;
|
||||
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;
|
||||
|
||||
interface_name = nm_setting_vlan_get_interface_name (setting);
|
||||
g_return_val_if_fail (interface_name != NULL, FALSE);
|
||||
g_return_val_if_fail (iface != 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;
|
||||
|
||||
new_link = rtnl_link_get_by_name (cache, iface);
|
||||
if (new_link) {
|
||||
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;
|
||||
}
|
||||
|
||||
nl_cache_free (cache);
|
||||
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
|
||||
|
Reference in New Issue
Block a user