Bridging: Align Bridge management port handling with TR181 standard

This commit is contained in:
Amin Ben Romdhane 2023-02-19 23:16:46 +01:00
parent ca1b8a41ca
commit 52921f8ff3
13 changed files with 2098 additions and 1520 deletions

View file

@ -433,7 +433,7 @@ int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *obje
for (; *objects; objects++) {
if (DM_STRNCMP(value, *objects, DM_STRLEN(*objects)) == 0) {
if (match(value, *objects)) {
char *linker = NULL;
adm_entry_get_linker_value(ctx, value, &linker);

File diff suppressed because it is too large Load diff

View file

@ -17,11 +17,12 @@
struct bridge_port_args
{
struct uci_section *bridge_sec;
struct uci_section *bridge_dmmap_sec;
struct uci_section *bridge_port_sec;
struct uci_section *bridge_port_dmmap_sec;
struct uci_section *bridge_sec;
bool is_management_port;
char *br_inst;
char *br_port_device;
};
extern DMOBJ tBridgingObj[];

View file

@ -73,33 +73,6 @@ struct uci_section *ethernet___get_device_section(char *dev_name)
return NULL;
}
static void get_bridge_port_linker(struct dmctx *ctx, char *device_s_name, char **value)
{
struct uci_section *dmmap_section = NULL, *bridge_port = NULL;
*value = "";
get_dmmap_section_of_config_section("dmmap_bridge", "device", device_s_name, &dmmap_section);
if (dmmap_section != NULL) {
char *br_inst = NULL;
dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst);
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, bridge_port) {
char *management = NULL;
dmuci_get_value_by_section_string(bridge_port, "management", &management);
if (management && DM_LSTRCMP(management, "1") == 0) {
char linker[512] = {0};
char *port = NULL;
dmuci_get_value_by_section_string(bridge_port, "port", &port);
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(bridge_port), port);
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", linker, value);
break;
}
}
}
}
static int eth_iface_sysfs(const struct uci_section *data, const char *name, char **value)
{
char *device;
@ -1151,8 +1124,8 @@ static int get_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void
if (br_device_s) dmuci_get_value_by_section_string(br_device_s, "type", &device_s_type);
if (br_device_s && DM_LSTRCMP(device_s_type, "bridge") == 0) {
get_bridge_port_linker(ctx, section_name(br_device_s), value);
if (DM_LSTRCMP(device_s_type, "bridge") == 0) {
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", linker, value);
} else {
char *vid = DM_STRCHR(linker, '.');
if (vid) *vid = '\0';
@ -1171,7 +1144,7 @@ static int get_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void
static int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
char eth_interface[64] = "Device.Ethernet.Interface.";
char bridge_port[64] = "Device.Bridging.Bridge.";
char bridge_port[64] = "Device.Bridging.Bridge.*.Port.";
char atm_link[32] = "Device.ATM.Link.";
char ptm_link[32] = "Device.PTM.Link.";
char *allowed_objects[] = {
@ -1233,77 +1206,42 @@ static int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void
dmuci_set_value_by_section(ppp_s, "device", link_linker);
}
} else if (DM_STRNCMP(value, bridge_port, DM_STRLEN(bridge_port)) == 0) {
char br_linker[250] = {0};
} else if (match(value, bridge_port)) {
char *int_name = NULL;
DM_STRNCPY(br_linker, link_linker, sizeof(br_linker));
dmuci_get_value_by_section_string((struct uci_section *)data, "section_name", &int_name);
if (*int_name) {
/* There is an IP.Interface Object maps to this Ethernet.Link. Object */
struct uci_section *s;
char new_device[32] = {0};
char *bridge = DM_STRCHR(br_linker, ':');
if (bridge) {
struct uci_section *s = NULL;
char *device_name = NULL;
char *int_name = NULL;
char br_inst[8] = {0};
snprintf(new_device, sizeof(new_device), "br-%s", int_name);
*bridge = '\0';
DM_STRNCPY(br_inst, br_linker+3, sizeof(br_inst));
// Remove unused Interface section created by Bridge Object if it exists
s = get_dup_section_in_config_opt("network", "interface", "device", link_linker);
dmuci_delete_by_section(s, NULL, NULL);
dmuci_get_value_by_section_string((struct uci_section *)data, "section_name", &int_name);
// Add device option to Interface section that maps to this Ethernet.Link. Object
s = get_origin_section_from_config("network", "interface", int_name);
dmuci_set_value_by_section(s, "device", new_device);
if (*int_name) {
/* There is an IP.Interface Object maps to this Ethernet.Link. Object */
char old_device[16] = {0};
char new_device[16] = {0};
// Update device section with the new name value
s = get_dup_section_in_config_opt("network", "device", "name", link_linker);
dmuci_set_value_by_section(s, "name", new_device);
snprintf(old_device, sizeof(old_device), "br-dev%s", br_inst);
snprintf(new_device, sizeof(new_device), "br-%s", int_name);
// Update management port section with the new port value if it exists
s = get_dup_section_in_dmmap_opt("dmmap_bridge_port", "bridge_port", "port", link_linker);
dmuci_set_value_by_section(s, "port", new_device);
// Remove unused Interface section created by Bridge Object if it exists
uci_foreach_sections("network", "interface", s) {
char *device = NULL;
dmuci_set_value_by_section((struct uci_section *)data, "device", new_device);
} else {
/* There is no IP.Interface Object maps to this Ethernet.Link. Object so Update only device option */
dmuci_get_value_by_section_string(s, "device", &device);
if (device && DM_STRCMP(device, old_device) == 0) {
dmuci_delete_by_section(s, NULL, NULL);
break;
}
}
// Add device option to Interface section that maps to this Ethernet.Link. Object
s = get_origin_section_from_config("network", "interface", int_name);
dmuci_set_value_by_section(s, "device", new_device);
// Update all bridge_port section with the new device value
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, s) {
if (device_name == NULL || *device_name == '\0')
dmuci_get_value_by_section_string(s, "device_section_name", &device_name);
dmuci_set_value_by_section(s, "device", new_device);
}
// Update device section with the new name value
if (device_name && *device_name) {
s = get_origin_section_from_config("network", "device", device_name);
dmuci_set_value_by_section(s, "name", new_device);
}
dmuci_set_value_by_section((struct uci_section *)data, "device", new_device);
} else {
/* This is a new Ethernet.Link. Object so section_name is empty */
// Get the device value
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, s) {
dmuci_get_value_by_section_string(s, "device", &device_name);
if (device_name && *device_name)
break;
}
dmuci_set_value_by_section((struct uci_section *)data, "device", device_name ? device_name : "");
}
dmuci_set_value_by_section((struct uci_section *)data, "is_eth", "1");
dmuci_set_value_by_section((struct uci_section *)data, "device", link_linker);
}
dmuci_set_value_by_section((struct uci_section *)data, "is_eth", "1");
}
break;
}

View file

@ -342,27 +342,11 @@ int browseInterfaceStackInst(struct dmctx *dmctx, DMNODE *parent_node, void *pre
if (br_device_s && DM_LSTRCMP(device_s_type, "bridge") == 0) {
// The lower layer is Device.Bridging.Bridge.{i}.Port.{i}.
struct uci_section *dmmap_section, *port = NULL;
get_dmmap_section_of_config_section("dmmap_bridge", "device", section_name(br_device_s), &dmmap_section);
if (dmmap_section != NULL) {
char *br_inst, *mg = NULL;
dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst);
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, port) {
dmuci_get_value_by_section_string(port, "management", &mg);
if (mg && DM_LSTRCMP(mg, "1") == 0) {
char *device, linker_buf[512] = {0};
dmuci_get_value_by_section_string(port, "port", &device);
snprintf(linker_buf, sizeof(linker_buf), "br_%s:%s+%s", br_inst, section_name(port), device);
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", linker_buf, &value);
dmuci_get_value_by_section_string(port, "bridge_port_alias", &loweralias);
dmuci_get_value_by_section_string(port, "bridge_port_instance", &layer_inst);
break;
}
}
struct uci_section *port = get_dup_section_in_dmmap_opt("dmmap_bridge_port", "bridge_port", "port", linker);
if (port != NULL) {
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", linker, &value);
dmuci_get_value_by_section_string(port, "bridge_port_alias", &loweralias);
dmuci_get_value_by_section_string(port, "bridge_port_instance", &layer_inst);
}
} else {
// The lower layer is Device.Ethernet.Interface.{i}.
@ -412,40 +396,31 @@ int browseInterfaceStackInst(struct dmctx *dmctx, DMNODE *parent_node, void *pre
char *mg = NULL;
dmuci_get_value_by_section_string(port, "management", &mg);
if (mg && DM_LSTRCMP(mg, "1") == 0) {
char *device, linker[512] = {0};
if (DM_LSTRCMP(mg, "1") == 0) {
char *device = NULL;
dmuci_get_value_by_section_string(port, "port", &device);
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(port), device);
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", linker, &mg_value);
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", device, &mg_value);
dmuci_get_value_by_section_string(port, "bridge_port_alias", &higheralias);
dmuci_get_value_by_section_string(port, "bridge_port_instance", &bridge_port_inst);
snprintf(buf_mngr, sizeof(buf_mngr), "%s%s", *higheralias ? higheralias : *bridge_port_inst ? "cpe-" : "", (*higheralias == '\0' && *bridge_port_inst) ? bridge_port_inst : "");
if (mg_value == NULL)
mg_value = "";
break;
}
}
struct uci_section *sd = NULL;
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, sd) {
char *mg = NULL;
char *mg = NULL, *vb = NULL, *device = NULL;
dmuci_get_value_by_section_string(sd, "management", &mg);
if (mg && DM_LSTRCMP(mg, "1") == 0)
if (DM_LSTRCMP(mg, "1") == 0)
continue;
char *vb = NULL, *device, linker[512] = {0};
dmuci_get_value_by_section_string(sd, "port", &device);
// The lower layer is Device.Bridging.Bridge.{i}.Port.{i}.
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(sd), device);
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", linker, &vb);
if (vb == NULL)
vb = "";
adm_entry_get_linker_param(dmctx, "Device.Bridging.Bridge.", section_name(sd), &vb);
dmuci_get_value_by_section_string(sd, "bridge_port_alias", &loweralias);
dmuci_get_value_by_section_string(sd, "bridge_port_instance", &bridge_port_inst);

View file

@ -1407,25 +1407,16 @@ static int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *
struct uci_section *s = NULL;
// Remove unused Interface section created by Bridge Object if it exists
uci_foreach_sections("network", "interface", s) {
char *br_device = NULL;
s = get_dup_section_in_config_opt("network", "interface", "device", linker_buf);
dmuci_delete_by_section(s, NULL, NULL);
dmuci_get_value_by_section_string(s, "device", &br_device);
if (br_device && DM_STRCMP(br_device, linker_buf) == 0) {
dmuci_delete_by_section(s, NULL, NULL);
break;
}
}
// Update all bridge_port section with the new device value
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "device", linker_buf, s) {
dmuci_set_value_by_section(s, "device", device);
}
// Update amanagement port section with the new port value if it exists
s = get_dup_section_in_dmmap_opt("dmmap_bridge_port", "bridge_port", "port", linker_buf);
dmuci_set_value_by_section(s, "port", device);
// Update device section with the new name value
uci_foreach_option_eq("network", "device", "name", linker_buf, s) {
dmuci_set_value_by_section(s, "name", device);
}
s = get_dup_section_in_config_opt("network", "device", "name", linker_buf);
dmuci_set_value_by_section(s, "name", device);
// Update device option in dmmap section related to this Interface section
dmuci_set_value_by_section(eth_link_s, "device", device);

View file

@ -28,7 +28,7 @@ static int set_BridgingBridgePort_Egress_PriorityRegeneration(char *refparam, st
return FAULT_9007;
dmuci_get_value_by_section_string(((struct bridge_port_args *)data)->bridge_port_sec, "type", &type);
if (DM_STRLEN(type) == 0)
if (((struct bridge_port_args *)data)->is_management_port || DM_STRLEN(type) == 0)
return FAULT_9007;
return 0;

View file

@ -109,32 +109,6 @@ static void add_empty_mcast_iface_to_list(char *dmmap_package, char *dmmap_sec,
}
}
void get_mcast_bridge_port_linker(struct dmctx *ctx, char *device_name, char **value)
{
struct uci_section *dmmap_br_section = NULL, *bridge_port_s = NULL;
*value = NULL;
get_dmmap_section_of_config_section("dmmap_bridge", "device", device_name, &dmmap_br_section);
if (dmmap_br_section != NULL) {
char *br_inst;
dmuci_get_value_by_section_string(dmmap_br_section, "bridge_instance", &br_inst);
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, bridge_port_s) {
char *mg = NULL;
dmuci_get_value_by_section_string(bridge_port_s, "management", &mg);
if (mg && DM_LSTRCMP(mg, "1") == 0) {
char *device, linker[512] = "";
dmuci_get_value_by_section_string(bridge_port_s, "port", &device);
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(bridge_port_s), device);
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", linker, value);
break;
}
}
}
}
void synchronize_specific_config_sections_with_dmmap_mcast_iface(char *package, char *section_type,
void *data, char *dmmap_package, char *dmmap_sec, char *proto,
struct list_head *dup_list)
@ -263,7 +237,7 @@ static int get_br_key_from_lower_layer(char *lower_layer, char *key, size_t s_ke
return 0;
}
int get_mcast_snooping_interface_val(char *value, char *ifname, size_t s_ifname)
int get_mcast_snooping_interface_val(struct dmctx *ctx, char *value, char *ifname, size_t s_ifname)
{
/* Check if the value is valid or not. */
if (DM_LSTRNCMP(value, "Device.Bridging.Bridge.", 23) != 0)
@ -273,35 +247,9 @@ int get_mcast_snooping_interface_val(char *value, char *ifname, size_t s_ifname)
if (get_br_key_from_lower_layer(value, key, sizeof(key)) != 0)
return -1;
/* Find out bridge section name using bridge key. */
struct uci_section *s = NULL;
char *device_sec_name = NULL;
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge", "device", "bridge_instance", key, s) {
dmuci_get_value_by_section_string(s, "section_name", &device_sec_name);
break;
}
if (!device_sec_name)
return -1;
// Check if network uci file has this section, if yes, then
// update the snooping interface with value as br-<section name>
struct uci_section *device_s = NULL;
uci_foreach_sections("network", "device", device_s) {
if (strcmp(section_name(device_s), device_sec_name) != 0)
continue;
char *type, *name;
dmuci_get_value_by_section_string(device_s, "type", &type);
if (*type == '\0' || DM_LSTRCMP(type, "bridge") != 0)
continue;
dmuci_get_value_by_section_string(device_s, "name", &name);
snprintf(ifname, s_ifname, "%s", name);
break;
}
char *linker = NULL;
adm_entry_get_linker_value(ctx, value, &linker);
snprintf(ifname, s_ifname, "%s", linker);
return 0;
}
@ -993,10 +941,7 @@ int get_mcast_snooping_interface(char *refparam, struct dmctx *ctx, void *data,
DM_STRNCPY(sec_name, end, sizeof(sec_name));
// In the dmmap_bridge file, the details related to the instance id etc. associated with this bridge
// is stored, we now switch our focus to it to extract the necessary information.
get_mcast_bridge_port_linker(ctx, sec_name, value);
if (*value == NULL)
*value = "";
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", val1, value);
return 0;
}
@ -1010,7 +955,7 @@ int set_mcast_snooping_interface(char *refparam, struct dmctx *ctx, void *data,
return FAULT_9007;
break;
case VALUESET:
if (get_mcast_snooping_interface_val(value, ifname, sizeof(ifname)) != 0)
if (get_mcast_snooping_interface_val(ctx, value, ifname, sizeof(ifname)) != 0)
return -1;
dmuci_set_value_by_section((struct uci_section *)data, "interface", ifname);
@ -1767,7 +1712,7 @@ static int set_igmpp_interface_iface(char *refparam, struct dmctx *ctx, void *da
break;
case VALUESET:
// First check if this is a bridge type interface
if (get_mcast_snooping_interface_val(value, ifname, sizeof(ifname)) == 0) {
if (get_mcast_snooping_interface_val(ctx, value, ifname, sizeof(ifname)) == 0) {
interface_linker = dmstrdup(ifname);
is_br = true;
} else {
@ -1845,7 +1790,7 @@ static int get_igmpp_interface_iface(char *refparam, struct dmctx *ctx, void *da
adm_entry_get_linker_param(ctx, "Device.IP.Interface.", sec_name, value);
} else {
// It is a L2 bridge, get the linker accordingly
get_mcast_bridge_port_linker(ctx, sec_name, value);
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", igmpp_ifname, value);
}
break;
}

View file

@ -81,12 +81,11 @@ int get_mcasts_filter_no_of_entries(char *refparam, struct dmctx *ctx, void *dat
int del_mcasts_filter_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
void update_snooping_mode(struct uci_section *s);
int get_mcast_snooping_interface_val(char *value, char *ifname, size_t s_ifname);
int get_mcast_snooping_interface_val(struct dmctx *ctx, char *value, char *ifname, size_t s_ifname);
int del_proxy_obj(void *data, char *proto, unsigned char del_action);
void del_dmmap_sec_with_opt_eq(char *dmmap_file, char *section, char *option, char *value);
void sync_dmmap_bool_to_uci_list(struct uci_section *s, char *section, char *value, bool b);
int del_snooping_obj(void *data, char *proto, unsigned char del_action);
void get_mcast_bridge_port_linker(struct dmctx *ctx, char *intf_name, char **value);
int browse_proxy_interface_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *proto);
int browse_filter_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *section_type,
char *option_name, char *option_value);

View file

@ -453,7 +453,7 @@ static int set_mldp_interface_iface(char *refparam, struct dmctx *ctx, void *dat
break;
case VALUESET:
// First check if this is a bridge type interface
if (get_mcast_snooping_interface_val(value, ifname, sizeof(ifname)) == 0) {
if (get_mcast_snooping_interface_val(ctx, value, ifname, sizeof(ifname)) == 0) {
interface_linker = dmstrdup(ifname);
} else {
adm_entry_get_linker_value(ctx, value, &linker);
@ -542,7 +542,7 @@ static int get_mldp_interface_iface(char *refparam, struct dmctx *ctx, void *dat
adm_entry_get_linker_param(ctx, "Device.IP.Interface.", sec_name, value);
} else {
// It is a L2 bridge, get the linker accordingly
get_mcast_bridge_port_linker(ctx, sec_name, value);
adm_entry_get_linker_param(ctx, "Device.Bridging.Bridge.", mldp_ifname, value);
}
break;
}

File diff suppressed because it is too large Load diff

View file

@ -347,6 +347,18 @@ struct uci_section *get_origin_section_from_config(char *package, char *section_
return NULL;
}
struct uci_section *get_origin_section_from_dmmap(char *package, char *section_type, char *orig_section_name)
{
struct uci_section *s = NULL;
uci_path_foreach_sections(bbfdm, package, section_type, s) {
if (strcmp(section_name(s), orig_section_name) == 0)
return s;
}
return NULL;
}
struct uci_section *get_dup_section_in_dmmap(char *dmmap_package, char *section_type, char *orig_section_name)
{
struct uci_section *s;
@ -930,7 +942,7 @@ char *get_device_from_wifi_iface(const char *wifi_iface, const char *wifi_sectio
bool value_exists_in_uci_list(struct uci_list *list, const char *value)
{
struct uci_element *e;
struct uci_element *e = NULL;
if (list == NULL)
return false;

View file

@ -245,6 +245,7 @@ bool value_exits_in_str_list(char *str_list, const char *delimitor, const char *
void add_elt_to_str_list(char **str_list, char *elt);
void remove_elt_from_str_list(char **str_list, char *ifname);
struct uci_section *get_origin_section_from_config(char *package, char *section_type, char *orig_section_name);
struct uci_section *get_origin_section_from_dmmap(char *package, char *section_type, char *orig_section_name);
struct uci_section *get_dup_section_in_dmmap(char *dmmap_package, char *section_type, char *orig_section_name);
struct uci_section *get_dup_section_in_config_opt(char *package, char *section_type, char *opt_name, char *opt_value);
struct uci_section *get_dup_section_in_dmmap_opt(char *dmmap_package, char *section_type, char *opt_name, char *opt_value);