From 1f3e1d8744453e965fd2baea8604eb408531f7b4 Mon Sep 17 00:00:00 2001 From: jjoseph Date: Tue, 18 Feb 2020 16:00:01 +0530 Subject: [PATCH] Layer2 Deployment : Changes done to support VLAN deployments for layer 2 - Changes done in Bridging.Bridge.X.Port, Bridging.Bridge.X.VLAN Objects - Changes done in IP.Interface Objects - Changes done in Ethernet Objects TODO : Few more deployments needs to be covered. Also to add supoort for VLANPort and VLANTermination. --- dmtree/tr181/bridging.c | 102 +++++++++++++++++++++++++++++----------- dmtree/tr181/ethernet.c | 48 +++++++++++++++++-- libbbf_api/dmcommon.c | 84 +++++++++++++++++++++++++++++++++ libbbf_api/dmcommon.h | 1 + 4 files changed, 203 insertions(+), 32 deletions(-) diff --git a/dmtree/tr181/bridging.c b/dmtree/tr181/bridging.c index 6b6a1a12..48a7eb94 100644 --- a/dmtree/tr181/bridging.c +++ b/dmtree/tr181/bridging.c @@ -488,7 +488,8 @@ int get_br_vlan_number_of_entries(char *refparam, struct dmctx *ctx, void *data, struct uci_section *s = NULL; int cnt = 0; - uci_path_foreach_option_eq(bbfdm, "dmmap_network", "device", "bridge_key", instance, s) { + /* Fix: Interface section needs to be browsed to get the vlan entries. */ + uci_path_foreach_option_eq(bbfdm, "dmmap_network", "interface", "bridge_key", instance, s) { cnt++; } dmasprintf(value, "%d", cnt); @@ -1131,7 +1132,8 @@ int get_br_vlan_alias(char *refparam, struct dmctx *ctx, void *data, char *insta { struct uci_section *dmmap_section; - get_dmmap_section_of_config_section("dmmap_network", "device", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), &dmmap_section); + /* Fix: Interface section needs to be browsed to get the value for vlan alias. */ + get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(((struct bridging_vlan_args *)data)->bridge_vlan_sec), &dmmap_section); if (dmmap_section) dmuci_get_value_by_section_string(dmmap_section, "bridge_vlan_alias", value); return 0; } @@ -1346,7 +1348,7 @@ int delete_br_port(char *refparam, struct dmctx *ctx, void *data, char *instance /************************************************************* * LOWER LAYER **************************************************************/ -int check_port_with_ifname (char *ifname, struct uci_section **ss) +int check_port_with_ifname (char *ifname, struct uci_section **ss, int *is_tag) { struct uci_section *sss, *s; char *file_config_name; @@ -1385,7 +1387,7 @@ int check_port_with_ifname (char *ifname, struct uci_section **ss) } } } - } else if (strncmp(ifname, wan_baseifname, strlen(wan_baseifname)) == 0) { + } else if (strncmp(ifname, wan_baseifname, strlen(ifname)) == 0) { uci_foreach_option_eq("network", "device", "name", ifname, s) { *ss = s; break; @@ -1396,10 +1398,37 @@ int check_port_with_ifname (char *ifname, struct uci_section **ss) break; } } else { - uci_foreach_option_eq("ports", "ethport", "ifname", ifname, s) { - *ss = s; - break; + /* Fix : Add support for untagged interfaces(vlan id =1) in lower layer. */ + char intf[50] = {0}; + strncpy(intf, ifname, sizeof(intf)); + char *p = strstr(intf, "."); + if(p) { + char *token , *end= NULL; + token = strtok_r(intf, ".", &end); + if (NULL != token) { + char tag[50] = {0}; + strncpy(tag, end, sizeof(tag)); + if (strncmp(tag, "1", sizeof(tag)) == 0) { + uci_foreach_option_eq("network", "device", "name", ifname, s) { + *ss = s; + break; + } + } else { + /* Fix : Add support for tagged interfaces in lower layer. */ + uci_foreach_option_eq("ports", "ethport", "ifname", token, s) { + *is_tag = 1; + *ss = s; + break; + } + } + } + } else { + uci_foreach_option_eq("ports", "ethport", "ifname", ifname, s) { + *ss = s; + break; + } } + } return 0; } @@ -1416,7 +1445,9 @@ int get_port_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *in ifname_dup = dmstrdup(ifname); p = lbuf; for (pch = strtok_r(ifname_dup, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) { - check_port_with_ifname(pch, &s); + /* Fix: Added support for tagged and untagged interfaces. */ + int is_tag = 0; + check_port_with_ifname(pch, &s, &is_tag); if(s == NULL) continue; snprintf(plinker, sizeof(plinker), "%s+%s", section_name(s), pch); @@ -1703,11 +1734,34 @@ int browseBridgePortInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_da if (((struct bridging_args *)prev_data)->ifname[0] == '\0') return 0; ifname_dup = dmstrdup(((struct bridging_args *)prev_data)->ifname); + char tagged_intf[250] = {0}; + strncpy(tagged_intf, ifname_dup, sizeof(tagged_intf)); for (pch = strtok_r(ifname_dup, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) { found = false; - if (!found) - found= synchronize_multi_config_sections_with_dmmap_eq("ports", "ethport", "dmmap_bridge_port", "bridge_port", "ifname", pch, pch, &dup_list); + if (!found) { + /* Fix : Add support for untagged interfaces.*/ + char val[50] = {0}; + strncpy(val, pch, sizeof(val)); + char *p = strstr(val, "."); + if (p) { + char *tok, *tok_end; + tok = strtok_r(val, ".", &tok_end); + if (tok != NULL) { + char tag[20] = {0}; + strncpy(tag, tok_end, sizeof(tag)); + if (strncmp(tag, "1", sizeof(tag)) == 0) { + found= synchronize_multi_config_sections_with_dmmap_eq("network", "device", "dmmap_bridge_port", "bridge_port", "name", pch, pch, &dup_list); + } else { + /* Fix : Add support for tagged interfaces(eth0.100, eth1.200 etc).*/ + found= synchronize_multi_config_sections_with_dmmap_eq("ports", "ethport", "dmmap_bridge_port", "bridge_port", "ifname", tok, pch, &dup_list); + } + } + } else { + /* Add support for interfaces eth0, eth1, eth2.....etc.*/ + found= synchronize_multi_config_sections_with_dmmap_eq("ports", "ethport", "dmmap_bridge_port", "bridge_port", "ifname", pch, pch, &dup_list); + } + } if (!found) found= synchronize_multi_config_sections_with_dmmap_eq("wireless", "wifi-iface", "dmmap_bridge_port", "bridge_port", "ifname", pch, pch, &dup_list); @@ -1763,30 +1817,24 @@ end: /*#Device.Bridging.Bridge.{i}.VLAN.!UCI:network/device/dmmap_network*/ int browseBridgeVlanInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { - char *vlan = NULL, *vlan_last = NULL, *type, *is_lan = NULL; + char *vlan = NULL, *vlan_last = NULL; struct bridging_vlan_args curr_bridging_vlan_args = {0}; struct bridging_args *br_args = (struct bridging_args *)prev_data; struct dmmap_dup *p; LIST_HEAD(dup_list); - dmuci_get_value_by_section_string(br_args->bridge_sec, "is_lan", &is_lan); - if (is_lan == NULL || strcmp(is_lan, "1") != 0) { - synchronize_specific_config_sections_with_dmmap("network", "device", "dmmap_network", &dup_list); - list_for_each_entry(p, &dup_list, list) { - if(!p->config_section) + synchronize_specific_config_sections_with_dmmap_vlan("network", "interface", "dmmap_network", br_args->ifname, &dup_list); + list_for_each_entry(p, &dup_list, list) { + if(!p->config_section) + goto end; + + dmuci_set_value_by_section(p->dmmap_section, "bridge_key", br_args->br_key); + vlan = handle_update_instance(2, dmctx, &vlan_last, update_instance_alias, 3, p->dmmap_section, "bridge_vlan_instance", "bridge_vlan_alias"); + init_bridging_vlan_args(&curr_bridging_vlan_args, p->config_section, br_args->bridge_sec, vlan_last, br_args->br_key); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_vlan_args, vlan) == DM_STOP) goto end; - //Check if VLAN or NOT - dmuci_get_value_by_section_string(p->config_section, "type", &type); - if (strcmp(type, "untagged") != 0) { - dmuci_set_value_by_section(p->dmmap_section, "bridge_key", br_args->br_key); - vlan = handle_update_instance(2, dmctx, &vlan_last, update_instance_alias, 3, p->dmmap_section, "bridge_vlan_instance", "bridge_vlan_alias"); - init_bridging_vlan_args(&curr_bridging_vlan_args, p->config_section, br_args->bridge_sec, vlan_last, br_args->br_key); - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_bridging_vlan_args, vlan) == DM_STOP) - goto end; - } - } - free_dmmap_config_dup_list(&dup_list); } + free_dmmap_config_dup_list(&dup_list); end: return 0; } diff --git a/dmtree/tr181/ethernet.c b/dmtree/tr181/ethernet.c index e76f59ae..5354cbc4 100644 --- a/dmtree/tr181/ethernet.c +++ b/dmtree/tr181/ethernet.c @@ -171,6 +171,24 @@ inline int init_eth_port(struct eth_port_args *args, struct uci_section *s, char /************************************************************* * COMMON Functions **************************************************************/ +static int is_device_exist(char *device) +{ + struct uci_section *s = NULL; + char *dev; + + uci_path_foreach_sections(bbfdm, DMMAP, "link", s) { + dmuci_get_value_by_section_string(s, "device", &dev); + + char *p = strtok(dev, "."); + if (p != NULL) { + if (strcmp(p, device) == 0) { + return 1; + } + } + } + return 0; +} + static int is_mac_exist(char *macaddr) { struct uci_section *s = NULL; @@ -201,6 +219,17 @@ static void create_link(char *ifname) if (is_mac_exist(macaddr)) return; + /* Fix: For all the Ethernet link objects pointing to same Ethernet Interface, + * we can omit creating multiple Ethernet link entries.*/ + char intf[250] = {0}; + strncpy(intf, device, sizeof(intf)); + char *p = strtok(intf, "."); + if (p != NULL) { + if (is_device_exist(p)) { + return; + } + } + dmuci_add_section_bbfdm(DMMAP, "link", &dmmap, &v); dmuci_set_value_by_section(dmmap, "mac", macaddr); dmuci_set_value_by_section(dmmap, "device", device); @@ -210,12 +239,16 @@ static void create_link(char *ifname) static int dmmap_synchronizeEthernetLink(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { struct uci_section *s = NULL; - char *type, *ifname; + char *type, *ifname, *proto; uci_foreach_sections("network", "interface", s) { dmuci_get_value_by_section_string(s, "type", &type); - if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback") == 0) + /* Fix: The creating of multiple ethernet links.*/ + dmuci_get_value_by_section_string(s, "proto", &proto); + if (strcmp(type, "alias") == 0 || strcmp(section_name(s), "loopback") == 0 || + *proto == '\0') { continue; + } dmuci_get_value_by_section_string(s, "ifname", &ifname); if (*ifname == '\0' || *ifname == '@') @@ -314,7 +347,8 @@ int get_linker_interface(char *refparam, struct dmctx *dmctx, void *data, char * int get_linker_link(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker) { - dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "section_name", linker); + /* Fix: for get linker link */ + dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", linker); return 0; } @@ -1207,7 +1241,7 @@ int get_EthernetVLANTermination_LastChange(char *refparam, struct dmctx *ctx, vo int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - char *pch, *spch, *devifname, *ifname, *dupifname; + char *pch, *spch, *devifname, *ifname, *dupifname, *mac; struct uci_section *section; dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &devifname); @@ -1216,7 +1250,11 @@ int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, v dupifname = dmstrdup(ifname); for (pch = strtok_r(dupifname, " ", &spch); pch != NULL; pch = strtok_r(NULL, " ", &spch)) { if(strcmp(pch, devifname) == 0){ - adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), section_name(section), value); + /* Fix: Use mac address instead of section name for lower layer. */ + mac = get_macaddr(section_name(section)); + if (mac[0] != '\0') { + adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, value); + } break; } } diff --git a/libbbf_api/dmcommon.c b/libbbf_api/dmcommon.c index 2b86bcc9..7411acf0 100644 --- a/libbbf_api/dmcommon.c +++ b/libbbf_api/dmcommon.c @@ -821,6 +821,78 @@ struct uci_section *get_dup_section_in_dmmap_eq(char *dmmap_package, char* secti return NULL; } +void synchronize_specific_config_sections_with_dmmap_vlan(char *package, char *section_type, char *dmmap_package, char *ifname, struct list_head *dup_list) +{ + struct uci_section *s, *stmp, *dmmap_sect; + FILE *fp; + char *v, *dmmap_file_path; + + dmasprintf(&dmmap_file_path, "/etc/bbfdm/%s", dmmap_package); + if (access(dmmap_file_path, F_OK)) { + /* + *File does not exist + **/ + fp = fopen(dmmap_file_path, "w"); // new empty file + fclose(fp); + } + uci_foreach_sections(package, section_type, s) { + /* + * create/update corresponding dmmap section that have same config_section link and using param_value_array + */ + if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) { + dmuci_add_section_bbfdm(dmmap_package, section_type, &dmmap_sect, &v); + DMUCI_SET_VALUE_BY_SECTION(bbfdm, dmmap_sect, "section_name", section_name(s)); + } + + /* Fix : Entry for only VLANS. */ + if (strcmp(package, "network") == 0 && + strcmp(section_type, "interface") == 0 && + strcmp(dmmap_package, "dmmap_network") == 0) { + char *type, *intf; + dmuci_get_value_by_section_string(s, "type", &type); + dmuci_get_value_by_section_string(s, "ifname", &intf); + if (strcmp(type,"bridge") != 0 || strcmp(intf, ifname) != 0){ + continue; + } + } + + /* Fix: Vlan object should not be created for transparent bridges. */ + int tag = 0; + char name[250] = {0}; + strncpy(name, ifname, sizeof(name)); + char *p = strtok(name, " "); + while (p != NULL) { + char intf[250] = {0}; + strncpy(intf, p, sizeof(intf)); + char *find = strstr(intf, "."); + if (find) { + tag = 1; + break; + } + p = strtok(NULL, ""); + } + + if (tag == 0) { + continue; + } + + /* + * Add system and dmmap sections to the list + */ + add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL); + } + + /* + * Delete unused dmmap sections + */ + uci_path_foreach_sections_safe(bbfdm, dmmap_package, section_type, stmp, s) { + dmuci_get_value_by_section_string(s, "section_name", &v); + if(get_origin_section_from_config(package, section_type, v) == NULL){ + dmuci_delete_by_section_unnamed_bbfdm(s, NULL, NULL); + } + } +} + void synchronize_specific_config_sections_with_dmmap(char *package, char *section_type, char *dmmap_package, struct list_head *dup_list) { struct uci_section *s, *stmp, *dmmap_sect; @@ -844,6 +916,18 @@ void synchronize_specific_config_sections_with_dmmap(char *package, char *sectio DMUCI_SET_VALUE_BY_SECTION(bbfdm, dmmap_sect, "section_name", section_name(s)); } + /* Fix : Change to fix multiple IP interface creation. */ + if (strcmp(package, "network") == 0 && + strcmp(section_type, "interface") == 0 && + strcmp(dmmap_package, "dmmap_network") == 0) { + char *value; + char *type; + dmuci_get_value_by_section_string(s, "proto", &value); + if (*value == '\0') { + continue; + } + } + /* * Add system and dmmap sections to the list */ diff --git a/libbbf_api/dmcommon.h b/libbbf_api/dmcommon.h index 2c5d2691..ff59f248 100644 --- a/libbbf_api/dmcommon.h +++ b/libbbf_api/dmcommon.h @@ -220,6 +220,7 @@ void hex_to_ip(char *address, char *ret); void ip_to_hex(char *address, char *ret); void free_dmmap_config_dup_list(struct list_head *dup_list); void synchronize_specific_config_sections_with_dmmap(char *package, char *section_type, char *dmmap_package, struct list_head *dup_list); +void synchronize_specific_config_sections_with_dmmap_vlan(char *package, char *section_type, char *dmmap_package, char *ifname, struct list_head *dup_list); void synchronize_specific_config_sections_with_dmmap_eq(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list); void synchronize_specific_config_sections_with_dmmap_eq_no_delete(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list); void synchronize_specific_config_sections_with_dmmap_cont(char *package, char *section_type, char *dmmap_package,char* option_name, char* option_value, struct list_head *dup_list);