bbf: add support anywan type upstream iface in igmp

It was observed on dg400prime that the uci config was not correctly
generated when wan was of type anywan, this has been taken care of in
this patch. For anywan type IP interface, the list of upstream interfaces
is generated to keep each interface in mind. So, Device.IP.Interface.2
in this case will generate
	list upstream_interface 'eth5.1'
	list upstream_interface 'atm0.1'
	list upstream_interface 'ptm0.1'

test:
- Verify that config is correctly generated for normal interface.
- Verify that config is correctly generated for anywan interface.
- Verify that config is correctly generated for bridge interface.
This commit is contained in:
Rahul 2020-07-04 08:27:56 +05:30
parent 1992e2a560
commit 1cf9c8330f
2 changed files with 267 additions and 117 deletions

View file

@ -707,6 +707,33 @@ static int add_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data
return 0;
}
static void get_igmpp_iface_del_key_val(char *key, size_t key_size, char *if_name)
{
struct uci_section *s;
char *ifval;
if (strstr(if_name, "br-") != NULL) {
strncpy(key, if_name, key_size - 1);
} else {
uci_foreach_sections("network", "interface", s) {
if(strcmp(section_name(s), if_name) == 0) {
dmuci_get_value_by_section_string(s, "ifname", &ifval);
strncpy(key, ifval, key_size - 1);
break;
}
}
}
}
static void del_igmpp_iface_val(char *upstream, void *data, char *pch)
{
if (strcmp(upstream, "1") == 0) {
dmuci_del_list_value_by_section((struct uci_section *)data,
"upstream_interface", pch);
} else {
dmuci_del_list_value_by_section((struct uci_section *)data,
"downstream_interface", pch);
}
}
static int del_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
struct uci_section *d_sec = NULL;
@ -724,20 +751,25 @@ static int del_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data
dmuci_get_value_by_section_string(d_sec, "upstream", &upstream);
dmuci_delete_by_section(d_sec, NULL, NULL);
found = 1;
} else {
continue;
}
if (found) {
if (strcmp(upstream, "1") == 0) {
dmuci_del_list_value_by_section((struct uci_section *)data,
"upstream_interface", if_name);
} else {
dmuci_del_list_value_by_section((struct uci_section *)data,
"downstream_interface", if_name);
char key[1024];
get_igmpp_iface_del_key_val(key, sizeof(key), if_name);
char *pch, *spch;
pch = strtok_r(key, " ", &spch);
while (pch != NULL) {
del_igmpp_iface_val(upstream, data, pch);
pch = strtok_r(NULL, " ", &spch);
}
del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_interface",
"ifname", if_name);
break;
}
}
break;
case DEL_ALL:
uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_interface",
@ -745,12 +777,14 @@ static int del_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data
dmuci_get_value_by_section_string(d_sec, "ifname", &if_name);
dmuci_get_value_by_section_string(d_sec, "upstream", &upstream);
if (if_name[0] != '\0') {
if (strcmp(upstream, "1") == 0) {
dmuci_del_list_value_by_section((struct uci_section *)data,
"upstream_interface", if_name);
} else {
dmuci_del_list_value_by_section((struct uci_section *)data,
"downstream_interface", if_name);
char key[1024];
get_igmpp_iface_del_key_val(key, sizeof(key), if_name);
char *pch, *spch;
pch = strtok_r(key, " ", &spch);
while (pch != NULL) {
del_igmpp_iface_val(upstream, data, pch);
pch = strtok_r(NULL, " ", &spch);
}
}
}
@ -1400,13 +1434,95 @@ static void update_snooping_mode(struct uci_section *s)
return;
}
static void sync_proxy_interface_sections(struct uci_section *s, char *section,
char *value, bool up_iface)
{
struct uci_list *v = NULL;
struct uci_element *e;
char *val;
dmuci_get_value_by_section_list(s, section, &v);
// value here is a list of space separated names of interface so,
// the first task is to tokenise this and then for each interface,
// update the downstream or upstream interface list.
value = dmstrdup(value);
char *pch = NULL, *spch = NULL;
pch = strtok_r(value, " ", &spch);
while (pch != NULL) {
int found = 0; // use to avoid duplicate entries
if (v != NULL) {
// For each pch value check if entry already exists
// in the qos uci file in the downstream or upstream list
uci_foreach_element(v, e) {
val = dmstrdup(e->name);
if (strcmp(val, pch) == 0) {
found = 1;
if (!up_iface) {
// if entry is found and upstream was set to
// false, then, remove this entry
dmuci_del_list_value_by_section(s, section, val);
}
// Further action is not required
break;
}
}
// if entry was not found and b is true create entry. Check for
// found in needed otherwise, duplicate entry maybe created
if (up_iface && !found) {
dmuci_add_list_value_by_section(s, section, pch);
}
} else {
// The list of downstream or upstream interfaces in uci file is
// empty, so just add entries if needed
if (up_iface) {
dmuci_add_list_value_by_section(s, section, pch);
}
}
pch = strtok_r(NULL, " ", &spch);
}
}
static void set_igmpp_iface_val(void *data, char *instance, char *linker, char *interface_linker, bool is_br)
{
struct uci_section *d_sec;
char *up, *f_inst;
bool b;
uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_interface",
"section_name", section_name((struct uci_section *)data), d_sec) {
dmuci_get_value_by_section_string(d_sec, "iface_instance", &f_inst);
if (strcmp(instance, f_inst) == 0) {
if (is_br)
dmuci_set_value_by_section(d_sec, "ifname", interface_linker);
else
dmuci_set_value_by_section(d_sec, "ifname", linker);
dmuci_get_value_by_section_string(d_sec, "upstream", &up);
string_to_bool(up, &b);
sync_proxy_interface_sections((struct uci_section *)data,
"downstream_interface", interface_linker, !b);
// Now update the proxy_interface list
sync_proxy_interface_sections((struct uci_section *)data,
"upstream_interface", interface_linker, b);
update_snooping_mode((struct uci_section *)data);
break;
}
}
}
static int set_igmpp_interface_iface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
char *linker, *interface_linker = NULL;
char ifname[16];
char *up, *f_inst, *if_type;
struct uci_section *d_sec, *s;
bool b;
char *if_type;
struct uci_section *s;
bool is_br = false;
switch (action) {
case VALUECHECK:
@ -1417,38 +1533,26 @@ static int set_igmpp_interface_iface(char *refparam, struct dmctx *ctx, void *da
// First check if this is a bridge type interface
if (get_igmp_snooping_interface_val(value, ifname, sizeof(ifname)) == 0) {
interface_linker = dmstrdup(ifname);
is_br = true;
} else {
adm_entry_get_linker_value(ctx, value, &linker);
uci_foreach_sections("network", "interface", s) {
if(strcmp(section_name(s), linker) != 0) {
continue;
}
dmuci_get_value_by_section_string(s, "type", &if_type);
if (strcmp(if_type, "bridge") == 0)
if (strcmp(if_type, "bridge") == 0) {
dmasprintf(&interface_linker, "br-%s", linker);
else
is_br = true;
} else {
dmuci_get_value_by_section_string(s, "ifname", &interface_linker);
break;
}
}
uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_interface",
"section_name", section_name((struct uci_section *)data), d_sec) {
dmuci_get_value_by_section_string(d_sec, "iface_instance", &f_inst);
if (strcmp(instance, f_inst) == 0) {
dmuci_set_value_by_section(d_sec, "ifname", interface_linker);
dmuci_get_value_by_section_string(d_sec, "upstream", &up);
string_to_bool(up, &b);
sync_dmmap_bool_to_uci_list((struct uci_section *)data,
"downstream_interface", interface_linker, !b);
// Now update the proxy_interface list
sync_dmmap_bool_to_uci_list((struct uci_section *)data,
"upstream_interface", interface_linker, b);
update_snooping_mode((struct uci_section *)data);
}
break;
}
}
set_igmpp_iface_val(data, instance, linker, interface_linker, is_br);
break;
}
@ -1526,21 +1630,13 @@ static int get_igmpp_interface_iface(char *refparam, struct dmctx *ctx, void *da
break;
}
} else {
char *device_name, *tmp_linker = NULL;
// it is a L3 interface, get the section name from device name to construct the linker
uci_foreach_sections("network", "interface", s) {
dmuci_get_value_by_section_string(s, "ifname", &device_name);
if (strcmp(device_name, ifname) == 0) {
tmp_linker = dmstrdup(section_name(s));
break;
}
}
if (tmp_linker == NULL)
// in case its a L3 interface, the ifname would be section name of network file in the dmmap file,
// which infact is the linker, just use that directly.
if (ifname == NULL)
goto end;
adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", dmroot, dm_delim,
dm_delim, dm_delim), tmp_linker, value);
dm_delim, dm_delim), ifname, value);
}
end:
@ -1553,7 +1649,7 @@ end:
static int set_igmpp_interface_upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
char *f_inst, *ifname;
struct uci_section *d_sec;
struct uci_section *d_sec, *s;
bool b;
switch (action) {
@ -1567,13 +1663,33 @@ static int set_igmpp_interface_upstream(char *refparam, struct dmctx *ctx, void
"section_name", section_name((struct uci_section *)data), d_sec) {
dmuci_get_value_by_section_string(d_sec, "iface_instance", &f_inst);
if (strcmp(instance, f_inst) == 0) {
// The interface is a part of downstream or upstream list in the
// uci file based on the value of upstream parameter, hence, when
// this parameter is updated, need arises to update the lists as well.
// Reading the interface name to be updated associated with the
// instance for which upstream parameter is being updated is hence
// needed. This value is read into variable key.
char key[1024];
char *ifval;
dmuci_get_value_by_section_string(d_sec, "ifname", &ifname);
if (strstr(ifname, "br-") != NULL) {
strncpy(key, ifname, sizeof(key) - 1);
} else {
uci_foreach_sections("network", "interface", s) {
if(strcmp(section_name(s), ifname) == 0) {
dmuci_get_value_by_section_string(s, "ifname", &ifval);
strncpy(key, ifval, sizeof(key) - 1);
break;
}
}
}
dmuci_set_value_by_section(d_sec, "upstream", (b) ? "1" : "0");
sync_dmmap_bool_to_uci_list((struct uci_section *)data,
"downstream_interface", ifname, !b);
sync_dmmap_bool_to_uci_list((struct uci_section *)data,
"upstream_interface", ifname, b);
sync_proxy_interface_sections((struct uci_section *)data,
"downstream_interface", key, !b);
sync_proxy_interface_sections((struct uci_section *)data,
"upstream_interface", key, b);
update_snooping_mode((struct uci_section *)data);
break;
@ -1763,7 +1879,7 @@ DMLEAF IGMPProxyClientGroupParams[] = {
DMLEAF IGMPProxyFilterParams[] = {
{"Enable", &DMWRITE, DMT_BOOL, get_igmpp_filter_enable, set_igmpp_filter_enable, NULL, NULL, BBFDM_BOTH},
{"IPAddress", &DMWRITE, DMT_STRING, get_igmpp_filter_address, set_igmpp_filter_address, NULL, NULL, BBFDM_BOTH},
{"IPPrefix", &DMWRITE, DMT_STRING, get_igmpp_filter_address, set_igmpp_filter_address, NULL, NULL, BBFDM_BOTH},
{0}
};

View file

@ -608,13 +608,103 @@ struct uci_section *get_dup_section_in_dmmap_eq(char *dmmap_package, char* secti
return NULL;
}
static void get_mcast_iface_key(char *p_ifname, char *key, size_t key_size)
{
int itf_found = 0;
struct uci_section *n_sec;
char *intf_name;
uci_foreach_sections("network", "interface", n_sec) {
itf_found = 0;
dmuci_get_value_by_section_string(n_sec, "ifname", &intf_name);
intf_name = dmstrdup(intf_name);
char *pch, *spch;
pch = strtok_r(intf_name, " ", &spch);
while (pch != NULL) {
if (strcmp(pch, p_ifname) == 0) {
strncpy(key, section_name(n_sec), key_size - 1);
itf_found = 1;
break;
}
pch = strtok_r(NULL, " ", &spch);
}
if (itf_found)
break;
}
}
static void sync_mcast_dmmap_iface_sec(struct uci_list *proxy_iface, char *s_mode,
struct uci_section *s, char *dmmap_package, char *dmmap_sec,
struct list_head *dup_list, char *up_iface)
{
struct uci_element *e;
struct uci_section *d_sec;
int found = 0;
char key[1024] = "";
char *s_name;
char *v;
uci_foreach_element(proxy_iface, e) {
char *p_ifname = dmstrdup(e->name);
if (strstr(p_ifname, "br-") != NULL) {
strncpy(key, p_ifname, sizeof(key) - 1);
} else {
get_mcast_iface_key(p_ifname, key, sizeof(key));
}
// Now that we have the key which is the ifname, verify if interface
// section for this already exists in dmmap_mcast file. In case yes,
// add this to the dup_list, else create entry in the dmmap_mcast
// file corresponding to this interface
uci_path_foreach_option_eq(bbfdm, dmmap_package, dmmap_sec, "ifname",
key, d_sec) {
dmuci_get_value_by_section_string(d_sec, "section_name", &s_name);
if (strcmp(s_name, section_name(s)) == 0) {
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
found = 1;
break;
}
}
if (found == 0) {
// add entry in dmmap for this
dmuci_add_section_bbfdm(dmmap_package, dmmap_sec, &d_sec, &v);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "section_name",
section_name(s));
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "ifname",
key);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "upstream",
up_iface);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "snooping_mode",
s_mode);
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
}
}
}
static void add_empty_mcast_iface_to_list(char *dmmap_package, char *dmmap_sec,
struct uci_section *s, struct list_head *dup_list)
{
struct uci_section *dmmap_sect;
char *f_ifname;
uci_path_foreach_option_eq(bbfdm, dmmap_package, dmmap_sec, "section_name",
section_name(s), dmmap_sect) {
dmuci_get_value_by_section_string(dmmap_sect, "ifname", &f_ifname);
if (strcmp(f_ifname, "") == 0)
add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
}
}
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)
{
struct uci_section *s, *dmmap_sect, *d_sec, *stmp;
struct uci_section *s, *stmp;
char *v;
char *s_name;
dmmap_file_path_get(dmmap_package);
uci_foreach_option_eq(package, section_type, "proto", proto, s) {
@ -626,36 +716,12 @@ void synchronize_specific_config_sections_with_dmmap_mcast_iface(char *package,
// and update the dmmap section accordingly. The do the same exercise for the list
// snooping_interface
struct uci_list *proxy_iface = NULL;
dmuci_get_value_by_section_list(s, "upstream_interface", &proxy_iface);
if (proxy_iface != NULL) {
struct uci_element *e;
uci_foreach_element(proxy_iface, e) {
char *p_ifname = dmstrdup(e->name);
int found = 0;
uci_path_foreach_option_eq(bbfdm, dmmap_package, dmmap_sec, "ifname",
p_ifname, d_sec) {
dmuci_get_value_by_section_string(d_sec, "section_name", &s_name);
if (strcmp(s_name, section_name(s)) == 0) {
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
found = 1;
break;
}
}
sync_mcast_dmmap_iface_sec(proxy_iface, "0", s, dmmap_package,
dmmap_sec, dup_list, "1");
if (found == 0) {
// add entry in dmmap for this
dmuci_add_section_bbfdm(dmmap_package, dmmap_sec, &d_sec, &v);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "section_name",
section_name(s));
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "ifname",
p_ifname);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "upstream",
"1");
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "snooping_mode",
"0");
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
}
}
}
struct uci_list *snooping_iface = NULL;
@ -663,46 +729,14 @@ void synchronize_specific_config_sections_with_dmmap_mcast_iface(char *package,
dmuci_get_value_by_section_list(s, "downstream_interface", &snooping_iface);
dmuci_get_value_by_section_string(s, "snooping_mode", &s_mode);
if (snooping_iface != NULL) {
struct uci_element *e;
uci_foreach_element(snooping_iface, e) {
char *s_ifname = dmstrdup(e->name);
int found = 0;
uci_path_foreach_option_eq(bbfdm, dmmap_package, dmmap_sec, "ifname",
s_ifname, d_sec) {
dmuci_get_value_by_section_string(d_sec, "section_name", &s_name);
if (strcmp(s_name, section_name(s)) == 0) {
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
found = 1;
break;
}
}
if (found == 0) {
// add entry in dmmap for this
dmuci_add_section_bbfdm(dmmap_package, dmmap_sec, &d_sec, &v);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "section_name",
section_name(s));
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "ifname",
s_ifname);
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "upstream",
"0");
DMUCI_SET_VALUE_BY_SECTION(bbfdm, d_sec, "snooping_mode",
s_mode);
add_sectons_list_paramameter(dup_list, s, d_sec, NULL);
}
}
sync_mcast_dmmap_iface_sec(snooping_iface, s_mode, s, dmmap_package,
dmmap_sec, dup_list, "0");
}
char *f_ifname;
// There can be entries in the dmmap_mcast file that do not have an ifname set.
// For such entries, now add to dup_list
uci_path_foreach_option_eq(bbfdm, dmmap_package, dmmap_sec, "section_name",
section_name(s), dmmap_sect) {
dmuci_get_value_by_section_string(dmmap_sect, "ifname", &f_ifname);
add_empty_mcast_iface_to_list(dmmap_package, dmmap_sec, s, dup_list);
if (strcmp(f_ifname, "") == 0)
add_sectons_list_paramameter(dup_list, s, dmmap_sect, NULL);
}
}
/*