vlan: handle vlan flags, ingress and egress map in NMDeviceVlan

In update_connection(), pickup the configuration of
the vlan interface from platform and create the proper
NMSettingVlan setting.

And during stage1, configure the flags of the device.

Also, change all the ingress/egress mappings at once
instead of having a netlink request for each mapping.
Also, ensure we *clear* all other mappings so that
only those are set, that were configured (done by
the *gress_reset_all argument).
This commit is contained in:
Thomas Haller 2015-10-30 11:02:44 +01:00
parent d2650a88bd
commit 5feda42813
3 changed files with 134 additions and 19 deletions

View file

@ -251,4 +251,15 @@ NMUtilsStrStrDictKey *_nm_utils_strstrdictkey_create (const char *v1, const char
/***********************************************************/
gboolean _nm_setting_vlan_set_priorities (NMSettingVlan *setting,
NMVlanPriorityMap map,
const NMVlanQosMapping *qos_map,
guint n_qos_map);
void _nm_setting_vlan_get_priorities (NMSettingVlan *setting,
NMVlanPriorityMap map,
NMVlanQosMapping **out_qos_map,
guint *out_n_qos_map);
/***********************************************************/
#endif

View file

@ -396,6 +396,88 @@ nm_setting_vlan_add_priority (NMSettingVlan *setting,
return TRUE;
}
gboolean
_nm_setting_vlan_set_priorities (NMSettingVlan *setting,
NMVlanPriorityMap map,
const NMVlanQosMapping *qos_map,
guint n_qos_map)
{
gboolean has_changes = FALSE;
GSList *map_prev, *map_new;
guint i;
gint64 from_last;
map_prev = get_map (setting, map);
if (n_qos_map != g_slist_length (map_prev))
has_changes = TRUE;
else {
const GSList *iter;
iter = map_prev;
for (i = 0; i < n_qos_map; i++, iter = iter->next) {
const NMVlanQosMapping *m = iter->data;
if ( m->from != qos_map[i].from
|| m->to != qos_map[i].to) {
has_changes = TRUE;
break;
}
}
}
if (!has_changes)
return FALSE;
map_new = NULL;
from_last = G_MAXINT64;
for (i = n_qos_map; i > 0;) {
const NMVlanQosMapping *m = &qos_map[--i];
NMVlanQosMapping *item;
/* We require the array to be presorted. */
if (m->from >= from_last)
g_return_val_if_reached (FALSE);
from_last = m->from;
item = g_malloc0 (sizeof (NMVlanQosMapping));
item->from = m->from;
item->to = m->to;
map_new = g_slist_prepend (map_new, item);
}
g_slist_free_full (map_prev, g_free);
set_map (setting, map, map_new);
return TRUE;
}
void
_nm_setting_vlan_get_priorities (NMSettingVlan *setting,
NMVlanPriorityMap map,
NMVlanQosMapping **out_qos_map,
guint *out_n_qos_map)
{
GSList *list;
NMVlanQosMapping *qos_map = NULL;
guint n_qos_map, i;
list = get_map (setting, map);
n_qos_map = g_slist_length (list);
if (n_qos_map > 0) {
qos_map = g_new (NMVlanQosMapping, n_qos_map);
for (i = 0; list; i++, list = list->next) {
nm_assert (i < n_qos_map);
qos_map[i] = *((const NMVlanQosMapping *) list->data);
}
}
*out_qos_map = qos_map;
*out_n_qos_map = n_qos_map;
}
/**
* nm_setting_vlan_remove_priority:
* @setting: the #NMSettingVlan

View file

@ -36,6 +36,7 @@
#include "nm-device-factory.h"
#include "nm-manager.h"
#include "nm-core-internal.h"
#include "nmp-object.h"
#include "nmdbus-device-vlan.h"
@ -468,25 +469,27 @@ update_connection (NMDevice *device, NMConnection *connection)
NMDevice *parent;
const char *setting_parent, *new_parent;
const NMPlatformLink *plink;
const NMPlatformLnkVlan *plnk;
const NMPObject *polnk;
nm_auto_nmpobj NMPObject *polnk_ref = NULL;
if (!s_vlan) {
s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
nm_connection_add_setting (connection, (NMSetting *) s_vlan);
}
plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, &plink);
if (!plnk) {
polnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink);
if (!polnk) {
_LOGW (LOGD_VLAN, "failed to get VLAN interface info while updating connection.");
return;
}
polnk_ref = nmp_object_ref ((NMPObject *) polnk);
if (priv->vlan_id != plnk->id) {
priv->vlan_id = plnk->id;
if (priv->vlan_id != polnk->lnk_vlan.id) {
priv->vlan_id = polnk->lnk_vlan.id;
g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID);
}
if (plnk->id != nm_setting_vlan_get_id (s_vlan))
if (polnk->lnk_vlan.id != nm_setting_vlan_get_id (s_vlan))
g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL);
if (plink->parent != NM_PLATFORM_LINK_OTHER_NETNS)
@ -511,6 +514,16 @@ update_connection (NMDevice *device, NMConnection *connection)
g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL);
} else
g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL);
if (polnk->lnk_vlan.flags != nm_setting_vlan_get_flags (s_vlan))
g_object_set (s_vlan, NM_SETTING_VLAN_FLAGS, (NMVlanFlags) polnk->lnk_vlan.flags, NULL);
_nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_INGRESS_MAP,
polnk->_lnk_vlan.ingress_qos_map,
polnk->_lnk_vlan.n_ingress_qos_map);
_nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_EGRESS_MAP,
polnk->_lnk_vlan.egress_qos_map,
polnk->_lnk_vlan.n_egress_qos_map);
}
static NMActStageReturn
@ -545,20 +558,29 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
s_vlan = nm_connection_get_setting_vlan (connection);
if (s_vlan) {
int ifindex = nm_device_get_ifindex (dev);
int num, i;
guint32 from, to;
gs_free NMVlanQosMapping *ingress_map = NULL;
gs_free NMVlanQosMapping *egress_map = NULL;
guint n_ingress_map = 0, n_egress_map = 0;
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))
nm_platform_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, from, 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))
nm_platform_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, from, to);
}
_nm_setting_vlan_get_priorities (s_vlan,
NM_VLAN_INGRESS_MAP,
&ingress_map,
&n_ingress_map);
_nm_setting_vlan_get_priorities (s_vlan,
NM_VLAN_EGRESS_MAP,
&egress_map,
&n_egress_map);
nm_platform_link_vlan_change (NM_PLATFORM_GET,
nm_device_get_ifindex (dev),
NM_VLAN_FLAGS_ALL,
nm_setting_vlan_get_flags (s_vlan),
TRUE,
ingress_map,
n_ingress_map,
TRUE,
egress_map,
n_egress_map);
}
return ret;