mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-02 20:10:28 +01:00
platform: add nmp_utils_bridge_normalized_vlans_equal()
Add a function to compare two arrays of NMPlatformBridgeVlan. It will be used in the next commit to compare the VLANs from platform to the ones we want to set. To compare in a performant way, the vlans need to be normalized (no duplicated VLANS, ranges into their minimal expression...). Add the function nmp_utils_bridge_vlan_normalize.
This commit is contained in:
parent
ac1b3a544c
commit
ce9520919d
5 changed files with 337 additions and 7 deletions
|
|
@ -2275,6 +2275,90 @@ nmp_utils_lifetime_get(guint32 timestamp,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
bridge_vlan_compare(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
const NMPlatformBridgeVlan *vlan_a = a;
|
||||
const NMPlatformBridgeVlan *vlan_b = b;
|
||||
|
||||
return (int) vlan_a->vid_start - (int) vlan_b->vid_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* nmp_utils_bridge_vlan_normalize:
|
||||
* @vlans: the array of VLAN ranges
|
||||
* @num_vlans: the number of VLAN ranges in the array. On return, it contains
|
||||
* the new number.
|
||||
*
|
||||
* Sort the VLAN ranges and merge those that are contiguous or overlapping.It
|
||||
* must not contain invalid data such as 2 overlaping ranges with different
|
||||
* flags.
|
||||
*/
|
||||
void
|
||||
nmp_utils_bridge_vlan_normalize(NMPlatformBridgeVlan *vlans, guint *num_vlans)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
if (*num_vlans <= 1)
|
||||
return;
|
||||
|
||||
g_qsort_with_data(vlans, *num_vlans, sizeof(NMPlatformBridgeVlan), bridge_vlan_compare, NULL);
|
||||
|
||||
/* Merge VLAN ranges that are contiguous or overlap */
|
||||
i = 0;
|
||||
while (i < *num_vlans - 1) {
|
||||
j = i + 1;
|
||||
|
||||
if (vlans[j].vid_start >= vlans[i].vid_start && vlans[j].vid_start <= vlans[i].vid_end + 1
|
||||
&& vlans[j].pvid == vlans[i].pvid && vlans[j].untagged == vlans[i].untagged) {
|
||||
if (vlans[i].vid_end < vlans[j].vid_end)
|
||||
vlans[i].vid_end = vlans[j].vid_end;
|
||||
|
||||
for (; j < *num_vlans - 1; j++)
|
||||
vlans[j] = vlans[j + 1];
|
||||
|
||||
*num_vlans -= 1;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nmp_utils_bridge_normalized_vlans_equal:
|
||||
* @vlans_a: the first array of bridge VLANs
|
||||
* @num_vlans_a: the number of elements of first array
|
||||
* @vlans_b: the second array of bridge VLANs
|
||||
* @num_vlans_b: the number of elements of second array
|
||||
*
|
||||
* Given two arrays of bridge VLAN ranges, compare if they are equal,
|
||||
* i.e. if they represent the same set of VLANs with the same attributes.
|
||||
* The input arrays must be sorted and must not have overlapping or duplicated
|
||||
* ranges.
|
||||
*/
|
||||
gboolean
|
||||
nmp_utils_bridge_normalized_vlans_equal(NMPlatformBridgeVlan *vlans_a,
|
||||
guint num_vlans_a,
|
||||
NMPlatformBridgeVlan *vlans_b,
|
||||
guint num_vlans_b)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (num_vlans_a != num_vlans_b)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < num_vlans_a; i++) {
|
||||
if (vlans_a[i].vid_start != vlans_b[i].vid_start || vlans_a[i].vid_end != vlans_b[i].vid_end
|
||||
|| vlans_a[i].pvid != vlans_b[i].pvid || vlans_a[i].untagged != vlans_b[i].untagged) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
_trunk_first_line(char *str)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -99,4 +99,11 @@ guint32 nmp_utils_lifetime_get(guint32 timestamp,
|
|||
int nmp_utils_modprobe(GError **error, gboolean suppress_error_logging, const char *arg1, ...)
|
||||
G_GNUC_NULL_TERMINATED;
|
||||
|
||||
void nmp_utils_bridge_vlan_normalize(NMPlatformBridgeVlan *vlans, guint *num_vlans);
|
||||
|
||||
gboolean nmp_utils_bridge_normalized_vlans_equal(NMPlatformBridgeVlan *vlans_a,
|
||||
guint num_vlans_a,
|
||||
NMPlatformBridgeVlan *vlans_b,
|
||||
guint num_vlans_b);
|
||||
|
||||
#endif /* __NM_PLATFORM_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -741,13 +741,6 @@ typedef struct {
|
|||
gint8 trust;
|
||||
} NMPlatformVF;
|
||||
|
||||
typedef struct {
|
||||
guint16 vid_start;
|
||||
guint16 vid_end;
|
||||
bool untagged : 1;
|
||||
bool pvid : 1;
|
||||
} NMPlatformBridgeVlan;
|
||||
|
||||
typedef struct {
|
||||
guint16 vlan_default_pvid_val;
|
||||
bool vlan_filtering_val : 1;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,15 @@ typedef enum {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
guint16 vid_start;
|
||||
guint16 vid_end;
|
||||
bool untagged : 1;
|
||||
bool pvid : 1;
|
||||
} NMPlatformBridgeVlan;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
/* We don't want to include <linux/ethtool.h> in header files,
|
||||
* thus create a ABI compatible version of struct ethtool_drvinfo.*/
|
||||
|
|
|
|||
|
|
@ -190,6 +190,239 @@ test_nmp_link_mode_all_advertised_modes_bits(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nmp_utils_bridge_vlans_normalize(void)
|
||||
{
|
||||
NMPlatformBridgeVlan vlans[10];
|
||||
NMPlatformBridgeVlan expect[10];
|
||||
guint vlans_len;
|
||||
|
||||
/* Single one is unmodified */
|
||||
vlans[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
expect[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans_len = 1;
|
||||
nmp_utils_bridge_vlan_normalize(vlans, &vlans_len);
|
||||
g_assert(vlans_len == 1);
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(vlans, vlans_len, expect, vlans_len));
|
||||
|
||||
/* Not merged if flags are different */
|
||||
vlans[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 11,
|
||||
.vid_end = 11,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
vlans[2] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 20,
|
||||
.vid_end = 25,
|
||||
};
|
||||
vlans[3] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 26,
|
||||
.vid_end = 30,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[4] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 40,
|
||||
.vid_end = 40,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[5] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 40,
|
||||
.vid_end = 40,
|
||||
.untagged = TRUE,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
expect[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
expect[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 11,
|
||||
.vid_end = 11,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
expect[2] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 20,
|
||||
.vid_end = 25,
|
||||
};
|
||||
expect[3] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 26,
|
||||
.vid_end = 30,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
expect[4] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 40,
|
||||
.vid_end = 40,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
expect[5] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 40,
|
||||
.vid_end = 40,
|
||||
.untagged = TRUE,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
vlans_len = 6;
|
||||
nmp_utils_bridge_vlan_normalize(vlans, &vlans_len);
|
||||
g_assert(vlans_len == 6);
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(vlans, vlans_len, expect, vlans_len));
|
||||
|
||||
/* Overlaping and contiguous ranges are merged */
|
||||
vlans[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 11,
|
||||
.vid_end = 20,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[2] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 19,
|
||||
.vid_end = 30,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
expect[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 30,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans_len = 3;
|
||||
nmp_utils_bridge_vlan_normalize(vlans, &vlans_len);
|
||||
g_assert(vlans_len == 1);
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(vlans, vlans_len, expect, vlans_len));
|
||||
|
||||
vlans[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 20,
|
||||
.vid_end = 20,
|
||||
};
|
||||
vlans[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 4,
|
||||
.vid_end = 4,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
vlans[2] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 33,
|
||||
.vid_end = 33,
|
||||
};
|
||||
vlans[3] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 100,
|
||||
.vid_end = 100,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans[4] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 34,
|
||||
.vid_end = 40,
|
||||
};
|
||||
vlans[5] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 21,
|
||||
.vid_end = 32,
|
||||
};
|
||||
expect[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 4,
|
||||
.vid_end = 4,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
expect[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 20,
|
||||
.vid_end = 40,
|
||||
};
|
||||
expect[2] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 100,
|
||||
.vid_end = 100,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
vlans_len = 6;
|
||||
nmp_utils_bridge_vlan_normalize(vlans, &vlans_len);
|
||||
g_assert(vlans_len == 3);
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(vlans, vlans_len, expect, vlans_len));
|
||||
}
|
||||
|
||||
static void
|
||||
test_nmp_utils_bridge_normalized_vlans_equal(void)
|
||||
{
|
||||
NMPlatformBridgeVlan a[10];
|
||||
NMPlatformBridgeVlan b[10];
|
||||
|
||||
/* Both empty */
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(NULL, 0, NULL, 0));
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(a, 0, b, 0));
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(a, 0, NULL, 0));
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(NULL, 0, b, 0));
|
||||
|
||||
/* One empty, other not */
|
||||
a[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(a, 1, NULL, 0));
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(NULL, 0, a, 1));
|
||||
|
||||
/* Equal range + VLAN */
|
||||
a[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
a[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 11,
|
||||
.vid_end = 11,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
b[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 10,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
b[1] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 11,
|
||||
.vid_end = 11,
|
||||
.pvid = TRUE,
|
||||
};
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(a, 2, b, 2));
|
||||
g_assert(nmp_utils_bridge_normalized_vlans_equal(b, 2, a, 2));
|
||||
|
||||
/* Different flag */
|
||||
b[1].pvid = FALSE;
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(a, 2, b, 2));
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(b, 2, a, 2));
|
||||
|
||||
/* Different ranges */
|
||||
a[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 30,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
b[0] = (NMPlatformBridgeVlan){
|
||||
.vid_start = 1,
|
||||
.vid_end = 29,
|
||||
.untagged = TRUE,
|
||||
};
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(a, 1, b, 1));
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(b, 1, a, 1));
|
||||
|
||||
b[0].vid_start = 2;
|
||||
b[0].vid_end = 30;
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(a, 1, b, 1));
|
||||
g_assert(!nmp_utils_bridge_normalized_vlans_equal(b, 1, a, 1));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nmpclass_consistency(void)
|
||||
{
|
||||
|
|
@ -252,6 +485,10 @@ main(int argc, char **argv)
|
|||
g_test_add_func("/nm-platform/test_nmp_link_mode_all_advertised_modes_bits",
|
||||
test_nmp_link_mode_all_advertised_modes_bits);
|
||||
g_test_add_func("/nm-platform/test_nmpclass_consistency", test_nmpclass_consistency);
|
||||
g_test_add_func("/nm-platform/test_nmp_utils_bridge_vlans_normalize",
|
||||
test_nmp_utils_bridge_vlans_normalize);
|
||||
g_test_add_func("/nm-platform/nmp-utils-bridge-vlans-equal",
|
||||
test_nmp_utils_bridge_normalized_vlans_equal);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue