From cb968e382b63ca79468e24e2c04539e00f9080a9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 30 Oct 2015 11:02:44 +0100 Subject: 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). --- libnm-core/nm-core-internal.h | 11 ++++++ libnm-core/nm-setting-vlan.c | 82 +++++++++++++++++++++++++++++++++++++++++++ src/devices/nm-device-vlan.c | 62 +++++++++++++++++++++----------- 3 files changed, 135 insertions(+), 20 deletions(-) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index b78a996ea6..4c95d0d0a7 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -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 diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index cb971b6d53..8428a36904 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -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 diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index de3a57e110..55790a9273 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -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; - - 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); - } + gs_free NMVlanQosMapping *ingress_map = NULL; + gs_free NMVlanQosMapping *egress_map = NULL; + guint n_ingress_map = 0, n_egress_map = 0; + + _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; -- cgit v1.2.1