Ticket refs #6361: LowerLayers of "Device.Ethernet.VLANTermination.{i}." points to wrong Link instance when VLANID is set

This commit is contained in:
Arun Muthusamy 2021-10-21 07:39:16 +02:00 committed by Amin Ben Ramdhane
parent 0f3a18aef6
commit 977693a9ba
2 changed files with 45 additions and 32 deletions

View file

@ -1205,24 +1205,29 @@ static int get_EthernetVLANTermination_LastChange(char *refparam, struct dmctx *
static int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) static int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{ {
char *name, *type, *inner_vid, *dev_name; char *name, *type, *ifname;
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "name", &name); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "name", &name);
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "type", &type); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "type", &type);
char *vid = strchr(name, '.'); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "ifname", &ifname);
if (vid) *vid = '\0';
if (strncmp(type, "8021ad", 6) == 0) { if (strncmp(type, "8021ad", 6) == 0) {
// 8021ad device, will have a vlan termination object as its lowerlayer // 8021ad device, will have a vlan termination object as its lowerlayer
char *inner_vid, *dev_name;
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "inner_vid", &inner_vid); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "inner_vid", &inner_vid);
dmasprintf(&dev_name, "%s.%s", name, inner_vid); dmasprintf(&dev_name, "%s.%s", name, inner_vid);
adm_entry_get_linker_param(ctx, "Device.Ethernet.VLANTermination.", dev_name, value); adm_entry_get_linker_param(ctx, "Device.Ethernet.VLANTermination.", dev_name, value);
} else { } else {
adm_entry_get_linker_param(ctx, "Device.Ethernet.Link.", name, value); adm_entry_get_linker_param(ctx, "Device.Ethernet.Link.", name, value);
if (*value == NULL)
adm_entry_get_linker_param(ctx, "Device.Ethernet.Link.", ifname, value);
} }
if (*value == NULL) if (*value == NULL)
*value = ""; *value = "";
return 0; return 0;
} }
@ -1328,9 +1333,8 @@ static int get_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{ {
char *ifname, *name, *curr_ifname, *type, *inner_vid, *old_vid, *old_name, *sec_name, *ad_vid; char *ifname, *name, *type;
char *ad_itf_ifname; struct uci_section *s = NULL, *dmap_sec = NULL;
struct uci_section *s = NULL, *d_sec = NULL;
switch (action) { switch (action) {
case VALUECHECK: case VALUECHECK:
@ -1346,46 +1350,55 @@ static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "ifname", &ifname); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "ifname", &ifname);
if (*ifname != '\0') { if (*ifname != '\0') {
char old_name[32] = {0};
if (strcmp(type, "8021ad") == 0) { if (strcmp(type, "8021ad") == 0) {
char *inner_vid;
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "inner_vid", &inner_vid); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "inner_vid", &inner_vid);
dmasprintf(&name, "%s.%s.%s", ifname, inner_vid, value); dmasprintf(&name, "%s.%s.%s", ifname, inner_vid, value);
} else { } else {
char *old_vid;
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "vid", &old_vid); dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "vid", &old_vid);
dmasprintf(&old_name, "%s.%s.", ifname, old_vid); if (old_vid[0] == '\0') {
snprintf(old_name, sizeof(old_name), "%s", ifname);
} else {
snprintf(old_name, sizeof(old_name), "%s.%s", ifname, old_vid);
}
dmasprintf(&name, "%s.%s", ifname, value); dmasprintf(&name, "%s.%s", ifname, value);
} }
if (ethernet_name_exists_in_devices(name)) if (ethernet_name_exists_in_devices(name))
return -1; return -1;
// set ifname option of the corresponding interface section if (strcmp(type, "8021ad") == 0) {
dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->config_section, "name", &curr_ifname); dmuci_set_value_by_section(((struct dmmap_dup *)data)->config_section, "inner_vid", value);
uci_foreach_option_eq("network", "interface", "device", curr_ifname, s) { } else {
dmuci_set_value_by_section(s, "device", name); char *interface_macaddr = NULL;
}
if (strncmp(type, "8021q", 5) == 0) { // set device option of the corresponding interface section
// Update the 8021ad instance with vid of lower layer uci_foreach_option_eq("network", "interface", "device", old_name, s) {
uci_foreach_sections("network", "device", d_sec) { dmuci_get_value_by_section_string(s, "macaddr", &interface_macaddr);
// We do not need to get the type here since we have the name dmuci_set_value_by_section(s, "device", name);
// already with us, we can use that as a key break;
dmuci_get_value_by_section_string(d_sec, "name", &sec_name); }
if (strncmp(sec_name, old_name, strlen(old_name)) == 0) {
dmuci_get_value_by_section_string(d_sec, "vid", &ad_vid);
dmasprintf(&ad_itf_ifname, "%s.%s.%s", ifname, value, ad_vid);
dmasprintf(&old_name, "%s.%s.%s", ifname, old_vid, ad_vid);
dmuci_set_value_by_section(d_sec, "inner_vid", value); /* Write vlan change to the dmmap file */
dmuci_set_value_by_section(d_sec, "name", ad_itf_ifname); uci_path_foreach_sections(bbfdm, "dmmap", "link", dmap_sec) {
// if this 8021ad instance is lowerlayer to an ip interface, then char *link_device, *link_macaddr;
// the ifname of the ip interface also needs to be updated
uci_foreach_option_eq("network", "interface", "device", old_name, s) { dmuci_get_value_by_section_string(dmap_sec, "device", &link_device);
dmuci_set_value_by_section(s, "device", ad_itf_ifname); dmuci_get_value_by_section_string(dmap_sec, "mac", &link_macaddr);
}
if (interface_macaddr && *interface_macaddr && strcmp(link_macaddr, interface_macaddr) != 0)
continue;
if (strcmp(link_device, old_name) == 0) {
dmuci_set_value_by_section(dmap_sec, "device", name);
break; break;
} }
} }
} }
// set name option of the device section // set name option of the device section

View file

@ -40,7 +40,7 @@ static int set_EthernetVLANTermination_MACVLAN(char *refparam, struct dmctx *ctx
uci_foreach_option_eq("network", "interface", "device", name, s) { uci_foreach_option_eq("network", "interface", "device", name, s) {
get_dmmap_section_of_config_section_eq("dmmap", "link", "device", ifname, &dmmap_s); get_dmmap_section_of_config_section_eq("dmmap", "link", "device", name, &dmmap_s);
if (dmmap_s) { if (dmmap_s) {
dmuci_get_value_by_section_string(dmmap_s, "link_instance", &link_instance); dmuci_get_value_by_section_string(dmmap_s, "link_instance", &link_instance);
snprintf(new_name, sizeof(new_name), "%s_%s", ifname, link_instance); snprintf(new_name, sizeof(new_name), "%s_%s", ifname, link_instance);
@ -122,7 +122,7 @@ static int set_EthernetVLANTermination_MACVLAN(char *refparam, struct dmctx *ctx
if (ethernet_name_exists_in_devices(new_name)) if (ethernet_name_exists_in_devices(new_name))
return -1; return -1;
dmuci_set_value_by_section(dmmap_s, "device", ifname); dmuci_set_value_by_section(dmmap_s, "device", new_name);
} }
dmuci_set_value_by_section(s, "device", new_name); dmuci_set_value_by_section(s, "device", new_name);