diff --git a/bin/Makefile.am b/bin/Makefile.am index a641808f..224e98bf 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -52,6 +52,7 @@ libbbfdm_la_SOURCES += \ ../dmtree/tr181/times.c \ ../dmtree/tr181/upnp.c \ ../dmtree/tr181/x_iopsys_eu_igmp.c \ + ../dmtree/tr181/x_iopsys_eu_mld.c \ ../dmtree/tr181/x_iopsys_eu_syslog.c \ ../dmtree/tr181/x_iopsys_eu_dropbear.c \ ../dmtree/tr181/x_iopsys_eu_owsd.c \ diff --git a/dmtree/tr181/device.c b/dmtree/tr181/device.c index 01120b1b..c54ea828 100644 --- a/dmtree/tr181/device.c +++ b/dmtree/tr181/device.c @@ -16,6 +16,7 @@ #include "times.h" #include "upnp.h" #include "x_iopsys_eu_igmp.h" +#include "x_iopsys_eu_mld.h" #include "x_iopsys_eu_syslog.h" #include "xmpp.h" #include "x_iopsys_eu_owsd.h" @@ -80,6 +81,7 @@ DMOBJ tRoot_181_Obj[] = { {CUSTOM_PREFIX"Syslog", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, NULL, NULL, tSe_SyslogParam, NULL, BBFDM_BOTH}, {CUSTOM_PREFIX"OWSD", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, NULL, X_IOPSYS_EU_OWSDObj, X_IOPSYS_EU_OWSDParams, NULL, BBFDM_BOTH}, {CUSTOM_PREFIX"IGMP", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, NULL, X_IOPSYS_EU_IGMPObj, X_IOPSYS_EU_IGMPParams, NULL, BBFDM_BOTH}, +{CUSTOM_PREFIX"MLD", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, NULL, X_IOPSYS_EU_MLDObj, X_IOPSYS_EU_MLDParams, NULL, BBFDM_BOTH}, {CUSTOM_PREFIX"Dropbear", &DMWRITE, add_dropbear_instance, delete_dropbear_instance, NULL, browseXIopsysEuDropbear, NULL, &DMNONE, NULL, NULL, X_IOPSYS_EU_DropbearParams, NULL, BBFDM_BOTH}, {CUSTOM_PREFIX"Buttons", &DMREAD, NULL, NULL, NULL, browseXIopsysEuButton, NULL, &DMNONE, NULL, NULL, X_IOPSYS_EU_ButtonParams, NULL, BBFDM_BOTH}, {CUSTOM_PREFIX"WiFiLife", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, NULL, X_IOPSYS_EU_WiFiLifeObj, X_IOPSYS_EU_WiFiLifeParams, NULL, BBFDM_BOTH}, diff --git a/dmtree/tr181/x_iopsys_eu_igmp.c b/dmtree/tr181/x_iopsys_eu_igmp.c index 39c26074..47a98c50 100644 --- a/dmtree/tr181/x_iopsys_eu_igmp.c +++ b/dmtree/tr181/x_iopsys_eu_igmp.c @@ -11,37 +11,6 @@ #include "dmentry.h" #include "x_iopsys_eu_igmp.h" -static void sync_dmmap_bool_to_uci_list(struct uci_section *s, char *section, char *value, - bool b) -{ - struct uci_list *v = NULL; - struct uci_element *e; - char *val; - - dmuci_get_value_by_section_list(s, section, &v); - if (v != NULL) { - uci_foreach_element(v, e) { - val = dmstrdup(e->name); - if (strcmp(val, value) == 0) { - if (!b) { - // remove this entry - dmuci_del_list_value_by_section(s, section, value); - } - - // Further action is not required - return; - } - } - } - - // If control has reached this point, that means, either the entry was not found - // in the list, hence, if b is true, add this entry to the list - if (b) { - dmuci_add_list_value_by_section(s, section, value); - } -} - - static int add_igmp_proxy_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) { char *inst, *value, *v, *s_name; @@ -49,10 +18,11 @@ static int add_igmp_proxy_obj(char *refparam, struct dmctx *ctx, void *data, cha char i_no[16]; check_create_dmmap_package("dmmap_mcast"); - inst = get_last_instance_bbfdm("dmmap_mcast", "proxy", "proxy_instance"); + inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "proxy", "proxy_instance", + "proto", "igmp"); snprintf(i_no, sizeof(i_no), "%d", inst ? atoi(inst)+1 : 1); - dmasprintf(&s_name, "mproxy_%s", i_no); + dmasprintf(&s_name, "igmp_proxy_%s", i_no); dmuci_add_section("mcast", "proxy", &s, &value); dmuci_rename_section_by_section(s, s_name); @@ -64,6 +34,7 @@ static int add_igmp_proxy_obj(char *refparam, struct dmctx *ctx, void *data, cha dmuci_add_section_bbfdm("dmmap_mcast", "proxy", &dmmap, &v); dmuci_set_value_by_section(dmmap, "section_name", section_name(s)); + dmuci_set_value_by_section(dmmap, "proto", "igmp"); *instance = update_instance_bbfdm(dmmap, inst, "proxy_instance"); return 0; @@ -76,6 +47,14 @@ static int del_igmp_proxy_obj(char *refparam, struct dmctx *ctx, void *data, cha switch (del_action) { case DEL_INST: + // first delete all filter child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data)); + // Now delete all interface child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_interface", + "section_name", section_name((struct uci_section *)data)); + + // Now delete the proxy node get_dmmap_section_of_config_section("dmmap_mcast", "proxy", section_name((struct uci_section *)data), &dmmap_section); if (dmmap_section != NULL) @@ -112,7 +91,7 @@ static int browse_igmp_proxy_inst(struct dmctx *dmctx, DMNODE *parent_node, void struct dmmap_dup *p; LIST_HEAD(dup_list); - synchronize_specific_config_sections_with_dmmap("mcast", "proxy", "dmmap_mcast", &dup_list); + synchronize_specific_config_sections_with_dmmap_cont("mcast", "proxy", "dmmap_mcast", "proto", "igmp", &dup_list); list_for_each_entry(p, &dup_list, list) { inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, p->dmmap_section, "proxy_instance", "proxy_alias"); if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) @@ -130,10 +109,11 @@ static int add_igmp_snooping_obj(char *refparam, struct dmctx *ctx, void *data, char i_no[16]; check_create_dmmap_package("dmmap_mcast"); - inst = get_last_instance_bbfdm("dmmap_mcast", "snooping", "snooping_instance"); + inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "snooping", + "snooping_instance", "proto", "igmp"); snprintf(i_no, sizeof(i_no), "%d", inst ? atoi(inst)+1 : 1); - dmasprintf(&s_name, "msnoop_%s", i_no); + dmasprintf(&s_name, "igmp_snoop_%s", i_no); dmuci_add_section("mcast", "snooping", &s, &value); dmuci_rename_section_by_section(s, s_name); @@ -145,6 +125,7 @@ static int add_igmp_snooping_obj(char *refparam, struct dmctx *ctx, void *data, dmuci_add_section_bbfdm("dmmap_mcast", "snooping", &dmmap, &v); dmuci_set_value_by_section(dmmap, "section_name", section_name(s)); + dmuci_set_value_by_section(dmmap, "proto", "igmp"); *instance = update_instance_bbfdm(dmmap, inst, "snooping_instance"); return 0; @@ -157,6 +138,12 @@ static int del_igmp_snooping_obj(char *refparam, struct dmctx *ctx, void *data, switch (del_action) { case DEL_INST: + // first delete all filter child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data)); + // Now delete all interface child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_interface", + "section_name", section_name((struct uci_section *)data)); get_dmmap_section_of_config_section("dmmap_mcast", "snooping", section_name((struct uci_section *)data), &dmmap_section); if (dmmap_section != NULL) @@ -193,7 +180,7 @@ static int browse_igmp_snooping_inst(struct dmctx *dmctx, DMNODE *parent_node, v struct dmmap_dup *p; LIST_HEAD(dup_list); - synchronize_specific_config_sections_with_dmmap("mcast", "snooping", "dmmap_mcast", &dup_list); + synchronize_specific_config_sections_with_dmmap_cont("mcast", "snooping", "dmmap_mcast", "proto", "igmp", &dup_list); list_for_each_entry(p, &dup_list, list) { inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, p->dmmap_section, "snooping_instance", "snooping_alias"); if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) @@ -208,7 +195,7 @@ static int get_igmps_no_of_entries(char *refparam, struct dmctx *ctx, void *data struct uci_section *s = NULL; int cnt = 0; - uci_foreach_sections("mcast", "snooping", s) { + uci_foreach_option_eq("mcast", "snooping", "proto", "igmp", s) { cnt++; } @@ -221,7 +208,7 @@ static int get_igmpp_no_of_entries(char *refparam, struct dmctx *ctx, void *data struct uci_section *s = NULL; int cnt = 0; - uci_foreach_sections("mcast", "proxy", s) { + uci_foreach_option_eq("mcast", "proxy", "proto", "igmp", s) { cnt++; } @@ -263,8 +250,7 @@ static int add_igmps_filter_obj(char *refparam, struct dmctx *ctx, void *data, c static int del_igmps_filter_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) { struct uci_section *d_sec = NULL; - struct uci_section *stmp = NULL; - char *f_inst, *ip_addr, *s_name; + char *f_inst, *ip_addr; int found = 0; switch (del_action) { @@ -297,12 +283,8 @@ static int del_igmps_filter_obj(char *refparam, struct dmctx *ctx, void *data, c } } - uci_path_foreach_sections_safe(bbfdm, "dmmap_mcast", "snooping_filter", stmp, d_sec) { - dmuci_get_value_by_section_string(d_sec, "section_name", &s_name); - if (strcmp(s_name, section_name((struct uci_section *)data)) == 0) - dmuci_delete_by_section_unnamed_bbfdm(d_sec, NULL, NULL); - } - + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data)); break; } @@ -622,75 +604,6 @@ static int get_igmp_snooping_interface(char *refparam, struct dmctx *ctx, void * return 0; } -static int get_br_key_from_lower_layer(char *lower_layer, char *key, size_t s_key) -{ - char *p = strstr(lower_layer, "Port"); - - if (!p) - return -1; - - /* Get the bridge_key. */ - int len = strlen(p); - char new_if[250] = {0}; - int i; - for (i = 0; i < strlen(lower_layer) - len; i++) { - new_if[i] = lower_layer[i]; - } - - char br_key = new_if[strlen(new_if) - 2]; - - snprintf(key, s_key, "%c", br_key); - - return 0; -} - -static int get_igmp_snooping_interface_val(char *value, char *ifname, size_t s_ifname) -{ - char lower_layer[250] = {0}; - - if (value[strlen(value)-1] != '.') - snprintf(lower_layer, sizeof(lower_layer), "%s.", value); - else - strncpy(lower_layer, value, sizeof(lower_layer) - 1); - - /* Check if the value is valid or not. */ - if (strncmp(lower_layer, "Device.Bridging.Bridge.", 23) != 0) - return -1; - - char key[10] = {0}; - if (get_br_key_from_lower_layer(lower_layer, key, sizeof(key)) != 0) - return -1; - - /* Find out bridge section name using bridge key. */ - struct uci_section *s = NULL; - char *sec_name; - uci_path_foreach_option_eq(bbfdm, "dmmap_network", "interface", "bridge_instance", key, s) { - dmuci_get_value_by_section_string(s, "section_name", &sec_name); - break; - } - - // Check if network uci file has this section, if yes, then - // update the snooping interface with value as br-
- struct uci_section *intf_s = NULL; - uci_foreach_sections("network", "interface", intf_s) { - char sec[20] = {0}; - strncpy(sec, section_name(intf_s), sizeof(sec) - 1); - if (strncmp(sec, sec_name, sizeof(sec)) != 0) - continue; - - char *type; - dmuci_get_value_by_section_string(intf_s, "type", &type); - if (*type == '\0' || strcmp(type, "bridge") != 0) - continue; - - snprintf(ifname, s_ifname, "br-%s", sec_name); - break; - - } - - return 0; -} - static int set_igmp_snooping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { char ifname[16]; @@ -717,7 +630,8 @@ static int add_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data char *last_inst, *v; struct uci_section *dmmap_igmpp_interface = NULL; - last_inst = get_last_instance_bbfdm("dmmap_mcast", "proxy_interface", "iface_instance"); + last_inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "proxy_interface", "iface_instance", + "section_name", section_name((struct uci_section *)data)); dmuci_add_section_bbfdm("dmmap_mcast", "proxy_interface", &dmmap_igmpp_interface, &v); dmuci_set_value_by_section(dmmap_igmpp_interface, "section_name", @@ -731,8 +645,7 @@ static int add_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data 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; - struct uci_section *stmp = NULL; - char *f_inst, *if_name, *s_name, *upstream; + char *f_inst, *if_name, *upstream; int found = 0; switch (del_action) { @@ -777,12 +690,8 @@ static int del_igmpp_interface_obj(char *refparam, struct dmctx *ctx, void *data } } - uci_path_foreach_sections_safe(bbfdm, "dmmap_mcast", "proxy_interface", stmp, d_sec) { - dmuci_get_value_by_section_string(d_sec, "section_name", &s_name); - if (strcmp(s_name, section_name((struct uci_section *)data)) == 0) - dmuci_delete_by_section_unnamed_bbfdm(d_sec, NULL, NULL); - } - + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_interface", + "section_name", section_name((struct uci_section *)data)); break; } @@ -833,8 +742,7 @@ static int add_igmpp_filter_obj(char *refparam, struct dmctx *ctx, void *data, c static int del_igmpp_filter_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) { struct uci_section *d_sec = NULL; - struct uci_section *stmp = NULL; - char *f_inst, *ip_addr, *s_name; + char *f_inst, *ip_addr; int found = 0; switch (del_action) { @@ -866,11 +774,8 @@ static int del_igmpp_filter_obj(char *refparam, struct dmctx *ctx, void *data, c "filter", ip_addr); } - uci_path_foreach_sections_safe(bbfdm, "dmmap_mcast", "proxy_filter", stmp, d_sec) { - dmuci_get_value_by_section_string(d_sec, "section_name", &s_name); - if (strcmp(s_name, section_name((struct uci_section *)data)) == 0) - dmuci_delete_by_section_unnamed_bbfdm(d_sec, NULL, NULL); - } + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_filter", "section_name", + section_name((struct uci_section *)data)); break; } diff --git a/dmtree/tr181/x_iopsys_eu_mld.c b/dmtree/tr181/x_iopsys_eu_mld.c new file mode 100644 index 00000000..cb41d90b --- /dev/null +++ b/dmtree/tr181/x_iopsys_eu_mld.c @@ -0,0 +1,1632 @@ +/* + * Copyright (C) 2020 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author Rahul Thakur + * + */ +#include "dmentry.h" +#include "x_iopsys_eu_mld.h" + +static int add_mld_proxy_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) +{ + char *inst, *value, *v, *s_name; + struct uci_section *dmmap = NULL, *s = NULL; + char i_no[16]; + + check_create_dmmap_package("dmmap_mcast"); + inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "proxy", "proxy_instance", + "proto", "mld"); + snprintf(i_no, sizeof(i_no), "%d", inst ? atoi(inst)+1 : 1); + + dmasprintf(&s_name, "mld_proxy_%s", i_no); + + dmuci_add_section("mcast", "proxy", &s, &value); + dmuci_rename_section_by_section(s, s_name); + dmuci_set_value_by_section(s, "enable", "0"); + dmuci_set_value_by_section(s, "proto", "mld"); + dmuci_set_value_by_section(s, "version", "2"); + dmuci_set_value_by_section(s, "robustness", "2"); + dmuci_set_value_by_section(s, "aggregation", "0"); + + dmuci_add_section_bbfdm("dmmap_mcast", "proxy", &dmmap, &v); + dmuci_set_value_by_section(dmmap, "section_name", section_name(s)); + dmuci_set_value_by_section(dmmap, "proto", "mld"); + *instance = update_instance_bbfdm(dmmap, inst, "proxy_instance"); + + return 0; +} + +static int del_mld_proxy_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) +{ + struct uci_section *s = NULL, *ss = NULL, *dmmap_section = NULL; + int found = 0; + + switch (del_action) { + case DEL_INST: + // first delete all filter child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data)); + // Now delete all interface child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_interface", + "section_name", section_name((struct uci_section *)data)); + + // Now delete the proxy node + get_dmmap_section_of_config_section("dmmap_mcast", "proxy", section_name((struct uci_section *)data), &dmmap_section); + + if (dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + + dmuci_delete_by_section((struct uci_section *)data, NULL, NULL); + break; + case DEL_ALL: + uci_foreach_option_eq("mcast", "proxy", "proto", "mld", s) { + if (found != 0){ + get_dmmap_section_of_config_section("dmmap_mcast", "proxy", section_name(s), &dmmap_section); + if(dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + dmuci_delete_by_section(ss, NULL, NULL); + } + ss = s; + found++; + } + if (ss != NULL) { + get_dmmap_section_of_config_section("dmmap_mcast", "proxy", section_name(ss), &dmmap_section); + if(dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + dmuci_delete_by_section(ss, NULL, NULL); + } + + break; + } + return 0; +} + +static int browse_mld_proxy_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + char *inst = NULL, *inst_last = NULL; + struct dmmap_dup *p; + LIST_HEAD(dup_list); + + synchronize_specific_config_sections_with_dmmap_cont("mcast", "proxy", "dmmap_mcast", "proto", "mld", &dup_list); + list_for_each_entry(p, &dup_list, list) { + inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, p->dmmap_section, "proxy_instance", "proxy_alias"); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) + break; + } + + free_dmmap_config_dup_list(&dup_list); + return 0; +} + +static int add_mld_snooping_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) +{ + char *inst, *value, *v, *s_name; + struct uci_section *dmmap = NULL, *s = NULL; + char i_no[16]; + + check_create_dmmap_package("dmmap_mcast"); + inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "snooping", + "snooping_instance", "proto", "mld"); + snprintf(i_no, sizeof(i_no), "%d", inst ? atoi(inst)+1 : 1); + + dmasprintf(&s_name, "mld_snoop_%s", i_no); + + dmuci_add_section("mcast", "snooping", &s, &value); + dmuci_rename_section_by_section(s, s_name); + dmuci_set_value_by_section(s, "enable", "0"); + dmuci_set_value_by_section(s, "proto", "mld"); + dmuci_set_value_by_section(s, "version", "2"); + dmuci_set_value_by_section(s, "robustness", "2"); + dmuci_set_value_by_section(s, "aggregation", "0"); + + dmuci_add_section_bbfdm("dmmap_mcast", "snooping", &dmmap, &v); + dmuci_set_value_by_section(dmmap, "section_name", section_name(s)); + dmuci_set_value_by_section(dmmap, "proto", "mld"); + *instance = update_instance_bbfdm(dmmap, inst, "snooping_instance"); + + return 0; +} + +static int del_mld_snooping_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) +{ + struct uci_section *s = NULL, *ss = NULL, *dmmap_section = NULL; + int found = 0; + + switch (del_action) { + case DEL_INST: + // first delete all filter child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data)); + // Now delete all interface child nodes related to this object + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_interface", + "section_name", section_name((struct uci_section *)data)); + get_dmmap_section_of_config_section("dmmap_mcast", "snooping", section_name((struct uci_section *)data), &dmmap_section); + + if (dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + + dmuci_delete_by_section((struct uci_section *)data, NULL, NULL); + break; + case DEL_ALL: + uci_foreach_option_eq("mcast", "snooping", "proto", "mld", s) { + if (found != 0){ + get_dmmap_section_of_config_section("dmmap_mcast", "snooping", section_name(s), &dmmap_section); + if(dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + dmuci_delete_by_section(ss, NULL, NULL); + } + ss = s; + found++; + } + if (ss != NULL) { + get_dmmap_section_of_config_section("dmmap_mcast", "snooping", section_name(ss), &dmmap_section); + if(dmmap_section != NULL) + dmuci_delete_by_section(dmmap_section, NULL, NULL); + dmuci_delete_by_section(ss, NULL, NULL); + } + + break; + } + return 0; +} + +static int browse_mld_snooping_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + char *inst = NULL, *inst_last = NULL; + struct dmmap_dup *p; + LIST_HEAD(dup_list); + + synchronize_specific_config_sections_with_dmmap_cont("mcast", "snooping", "dmmap_mcast", "proto", "mld", &dup_list); + list_for_each_entry(p, &dup_list, list) { + inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, p->dmmap_section, "snooping_instance", "snooping_alias"); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) + break; + } + free_dmmap_config_dup_list(&dup_list); + return 0; +} + +static int get_mlds_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *s = NULL; + int cnt = 0; + + uci_foreach_option_eq("mcast", "snooping", "proto", "mld", s) { + cnt++; + } + + dmasprintf(value, "%d", cnt); + return 0; +} + +static int get_mldp_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *s = NULL; + int cnt = 0; + + uci_foreach_option_eq("mcast", "proxy", "proto", "mld", s) { + cnt++; + } + + dmasprintf(value, "%d", cnt); + return 0; +} + +static int browse_mlds_cgrp_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} + +#if 0 +static int browse_mldp_cgrp_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} +#endif + +static int add_mlds_filter_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) +{ + char *last_inst, *v; + struct uci_section *dmmap_mlds_filter = NULL; + + last_inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "snooping_filter", "filter_instance", + "section_name", section_name((struct uci_section *)data)); + + dmuci_add_section_bbfdm("dmmap_mcast", "snooping_filter", &dmmap_mlds_filter, &v); + dmuci_set_value_by_section(dmmap_mlds_filter, "section_name", + section_name((struct uci_section *)data)); + dmuci_set_value_by_section(dmmap_mlds_filter, "enable", "0"); + *instance = update_instance_bbfdm(dmmap_mlds_filter, last_inst, "filter_instance"); + + return 0; +} + +static int del_mlds_filter_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) +{ + struct uci_section *d_sec = NULL; + char *f_inst, *ip_addr; + int found = 0; + + switch (del_action) { + case DEL_INST: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "filter_instance", &f_inst); + + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + dmuci_delete_by_section(d_sec, NULL, NULL); + found = 1; + } + + if (found) { + dmuci_del_list_value_by_section((struct uci_section *)data, + "filter", ip_addr); + break; + } + } + + break; + case DEL_ALL: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + if (ip_addr[0] != '\0') { + dmuci_del_list_value_by_section((struct uci_section *)data, + "filter", ip_addr); + } + } + + del_dmmap_sec_with_opt_eq("dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data)); + break; + } + + return 0; +} + +static int browse_mlds_filter_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + struct dmmap_dup *p = NULL; + char *inst = NULL, *inst_last = NULL; + LIST_HEAD(dup_list); + + synchronize_specific_config_sections_with_dmmap_filter("mcast", "snooping", prev_data, "dmmap_mcast", + "snooping_filter", "mld", &dup_list); + list_for_each_entry(p, &dup_list, list) { + if (!p->config_section) + break; + + inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, + p->dmmap_section, "filter_instance", "filter_alias"); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) + break; + + } + + free_dmmap_config_dup_list(&dup_list); + return 0; +} + +static int get_mlds_filter_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *s = NULL; + int cnt = 0; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", "section_name", + section_name((struct uci_section *)data), s) { + cnt++; + } + + dmasprintf(value, "%d", cnt); + return 0; +} + +static int get_mlds_filter_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *f_sec; + char *f_inst, *f_enable; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), f_sec) { + dmuci_get_value_by_section_string(f_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(f_sec, "enable", &f_enable); + break; + } + } + + if (strcmp(f_enable, "1") == 0) { + *value = "true"; + } else { + *value = "false"; + } + + return 0; +} + + +static int set_mlds_filter_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + struct uci_section *f_sec; + char *f_inst, *ip_addr; + bool b; + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), f_sec) { + dmuci_get_value_by_section_string(f_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(f_sec, "ipaddr", &ip_addr); + dmuci_set_value_by_section(f_sec, "enable", (b) ? "1" : "0"); + if (ip_addr[0] != '\0') { + sync_dmmap_bool_to_uci_list((struct uci_section *)data, + "filter", ip_addr, b); + } + break; + } + } + break; + } + + return 0; +} + +static int get_mlds_filter_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *d_sec; + char *f_inst, *ip_addr; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + break; + } + } + + if (ip_addr[0] == '\0') { + *value = ""; + } else { + *value = dmstrdup(ip_addr); + } + + return 0; +} + +static int set_mlds_filter_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + struct uci_section *s = NULL; + char *s_inst, *up; + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_string(value, -1, 45, NULL, 0, IPv6Address, 1)) + return FAULT_9007; + + break; + case VALUESET: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "snooping_filter", + "section_name", section_name((struct uci_section *)data), s) { + dmuci_get_value_by_section_string(s, "filter_instance", &s_inst); + if (strcmp(s_inst, instance) == 0) { + dmuci_set_value_by_section(s, "ipaddr", value); + dmuci_get_value_by_section_string(s, "enable", &up); + string_to_bool(up, &b); + sync_dmmap_bool_to_uci_list((struct uci_section *)data, + "filter", value, b); + break; + } + } + + break; + } + + return 0; +} + +static int get_mld_snooping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &val); + + if (strcmp(val, "1") == 0) + *value = "true"; + else + *value = "false"; + + return 0; +} + +static int set_mld_snooping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_set_value_by_section((struct uci_section *)data, "enable", (b) ? "1" : "0"); + break; + } + + return 0; +} + +static int get_mld_snooping_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "version", &val); + + if (strcmp(val, "2") == 0) + *value = "V2"; + else + *value = "V1"; + + return 0; +} + +static int set_mld_snooping_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + char val[4]; + + switch (action) { + case VALUECHECK: + if ((strcmp("V2", value) != 0) && (strcmp("V1", value) != 0)) + return FAULT_9007; + break; + case VALUESET: + if (strcmp(value, "V2") == 0) + strcpy(val, "2"); + else + strcpy(val, "1"); + + dmuci_set_value_by_section((struct uci_section *)data, "version", val); + break; + } + + return 0; +} + +static int get_mld_snooping_robustness(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + dmuci_get_value_by_section_string((struct uci_section *)data, "robustness", value); + return 0; +} + +static int set_mld_snooping_robustness(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section((struct uci_section *)data, "robustness", value); + break; + } + + return 0; +} + +static int get_mld_snooping_aggregation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "aggregation", &val); + + if (strcmp(val, "1") == 0) + *value = "true"; + else + *value = "false"; + + return 0; +} + +static int set_mld_snooping_aggregation(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_set_value_by_section((struct uci_section *)data, "aggregation", (b) ? "1" : "0"); + break; + } + + return 0; +} + +static int get_mld_snooping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char val[16], sec_name[16]; // taking 16 here is same as that is size of linux names usually supported + char *val1; + + dmuci_get_value_by_section_string((struct uci_section *)data, "interface", &val1); + + // The value is linux interface name so it would be br-wan for example, but the network + // section would be wan, so extract wan from br-wan + char *tok, *end; + + strncpy(val, val1, sizeof(val)); + tok = strtok_r(val, "-", &end); + if ((tok == NULL) || (end == NULL)) { + return 0; + } + + if (strcmp(tok, "br") != 0) { + return 0; + } + + strncpy(sec_name, end, sizeof(sec_name)); + // In the dmmap_network 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. + struct uci_section *dmmap_section, *port; + char *br_inst, *mg, linker[64] = ""; + + get_dmmap_section_of_config_section("dmmap_network", "interface", sec_name, &dmmap_section); + if (dmmap_section != NULL) { + dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst); + uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "bridge_key", br_inst, port) { + dmuci_get_value_by_section_string(port, "mg_port", &mg); + if (strcmp(mg, "true") == 0) { + snprintf(linker, sizeof(linker), "%s+", section_name(port)); + adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, + dm_delim, dm_delim, dm_delim), linker, value); + break; + } + } + } + + if (*value == NULL) + *value = ""; + + return 0; +} + +static int set_mld_snooping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + char ifname[16]; + switch (action) { + case VALUECHECK: + if (dm_validate_string_list(value, -1, -1, 1024, -1, -1, NULL, 0, NULL, 0)) + return FAULT_9007; + break; + case VALUESET: + + if (get_igmp_snooping_interface_val(value, ifname, sizeof(ifname)) != 0) + return -1; + + dmuci_set_value_by_section((struct uci_section *)data, "interface", ifname); + break; + } + + return 0; +} + +static int add_mldp_interface_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) +{ + // This section works but commented for now as it is tested not much yet. + char *last_inst, *v; + struct uci_section *dmmap_mldp_interface = NULL; + + last_inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "proxy_interface", "iface_instance", + "section_name", section_name((struct uci_section *)data)); + + dmuci_add_section_bbfdm("dmmap_mcast", "proxy_interface", &dmmap_mldp_interface, &v); + dmuci_set_value_by_section(dmmap_mldp_interface, "section_name", + section_name((struct uci_section *)data)); + dmuci_set_value_by_section(dmmap_mldp_interface, "upstream", "0"); + + *instance = update_instance_bbfdm(dmmap_mldp_interface, last_inst, "iface_instance"); + return 0; +} + +static int del_mldp_interface_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) +{ + struct uci_section *d_sec = NULL; + char *f_inst, *if_name, *upstream; + int found = 0; + + switch (del_action) { + case DEL_INST: + 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_get_value_by_section_string(d_sec, "ifname", &if_name); + dmuci_get_value_by_section_string(d_sec, "upstream", &upstream); + dmuci_delete_by_section(d_sec, NULL, NULL); + found = 1; + } + + 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); + } + break; + } + } + + break; + case DEL_ALL: + 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, "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); + } + } + } + + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_interface", + "section_name", section_name((struct uci_section *)data)); + break; + } + + return 0; +} + +static int browse_mldp_interface_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + struct dmmap_dup *p = NULL; + char *inst = NULL, *inst_last = NULL; + LIST_HEAD(dup_list); + + synchronize_specific_config_sections_with_dmmap_mcast_iface("mcast", "proxy", prev_data, + "dmmap_mcast", "proxy_interface", "mld", &dup_list); + list_for_each_entry(p, &dup_list, list) { + if (!p->config_section) + break; + + inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, + p->dmmap_section, "iface_instance", "iface_alias"); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) + break; + + } + + free_dmmap_config_dup_list(&dup_list); + return 0; +} + +static int add_mldp_filter_obj(char *refparam, struct dmctx *ctx, void *data, char **instance) +{ + char *last_inst, *v; + struct uci_section *dmmap_mldp_filter = NULL; + + last_inst = get_last_instance_lev2_bbfdm_dmmap_opt("dmmap_mcast", "proxy_filter", "filter_instance", + "section_name", section_name((struct uci_section *)data)); + + dmuci_add_section_bbfdm("dmmap_mcast", "proxy_filter", &dmmap_mldp_filter, &v); + dmuci_set_value_by_section(dmmap_mldp_filter, "section_name", + section_name((struct uci_section *)data)); + dmuci_set_value_by_section(dmmap_mldp_filter, "enable", "0"); + + *instance = update_instance_bbfdm(dmmap_mldp_filter, last_inst, "filter_instance"); + + return 0; +} + +static int del_mldp_filter_obj(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) +{ + struct uci_section *d_sec = NULL; + char *f_inst, *ip_addr; + int found = 0; + + switch (del_action) { + case DEL_INST: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "filter_instance", &f_inst); + + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + dmuci_delete_by_section(d_sec, NULL, NULL); + found = 1; + } + + if (found) { + dmuci_del_list_value_by_section((struct uci_section *)data, + "filter", ip_addr); + break; + } + } + + break; + case DEL_ALL: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + if (ip_addr[0] != '\0') + dmuci_del_list_value_by_section((struct uci_section *)data, + "filter", ip_addr); + } + + del_dmmap_sec_with_opt_eq("dmmap_mcast", "proxy_filter", "section_name", + section_name((struct uci_section *)data)); + + break; + } + + return 0; +} + +static int browse_mldp_filter_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + struct dmmap_dup *p = NULL; + char *inst = NULL, *inst_last = NULL; + LIST_HEAD(dup_list); + + synchronize_specific_config_sections_with_dmmap_filter("mcast", "proxy", prev_data, "dmmap_mcast", + "proxy_filter", "mld", &dup_list); + list_for_each_entry(p, &dup_list, list) { + if (!p->config_section) + break; + + inst = handle_update_instance(1, dmctx, &inst_last, update_instance_alias, 3, + p->dmmap_section, "filter_instance", "filter_alias"); + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) + break; + + } + + free_dmmap_config_dup_list(&dup_list); + return 0; +} + +static int get_mldp_interface_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *s = NULL; + int cnt = 0; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_interface", "section_name", + section_name((struct uci_section *)data), s) { + cnt++; + } + + dmasprintf(value, "%d", cnt); + return 0; +} + +static int get_mldp_filter_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *f_sec; + char *f_inst, *f_enable; + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), f_sec) { + dmuci_get_value_by_section_string(f_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(f_sec, "enable", &f_enable); + break; + } + } + + if (strcmp(f_enable, "1") == 0) { + *value = "true"; + } else { + *value = "false"; + } + + return 0; +} + +static int set_mldp_filter_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + struct uci_section *f_sec; + char *f_inst, *ip_addr; + bool b; + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), f_sec) { + dmuci_get_value_by_section_string(f_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(f_sec, "ipaddr", &ip_addr); + dmuci_set_value_by_section(f_sec, "enable", (b) ? "1" : "0"); + sync_dmmap_bool_to_uci_list((struct uci_section *)data, + "filter", ip_addr, b); + break; + } + } + break; + } + + return 0; +} + +static int get_mldp_filter_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *d_sec; + char *f_inst, *ip_addr; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), d_sec) { + dmuci_get_value_by_section_string(d_sec, "filter_instance", &f_inst); + if (strcmp(instance, f_inst) == 0) { + dmuci_get_value_by_section_string(d_sec, "ipaddr", &ip_addr); + break; + } + } + + if (ip_addr[0] == '\0') { + *value = ""; + } else { + *value = dmstrdup(ip_addr); + } + + return 0; +} + +static int set_mldp_filter_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + struct uci_section *s = NULL; + char *s_inst, *up; + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_string(value, -1, 45, NULL, 0, IPv6Address, 1)) + return FAULT_9007; + + break; + case VALUESET: + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", + "section_name", section_name((struct uci_section *)data), s) { + dmuci_get_value_by_section_string(s, "filter_instance", &s_inst); + if (strcmp(s_inst, instance) == 0) { + dmuci_set_value_by_section(s, "ipaddr", value); + dmuci_get_value_by_section_string(s, "enable", &up); + string_to_bool(up, &b); + sync_dmmap_bool_to_uci_list((struct uci_section *)data, + "filter", value, b); + break; + } + + } + + break; + } + + return 0; +} + +static int browse_mlds_cgrp_assoc_dev_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} + +static int browse_mldp_cgrp_assoc_dev_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} + +static int browse_mlds_cgrp_stats_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} + +static int browse_mldp_cgrp_stats_inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) +{ + //ToDo + return 0; +} +static int get_mlds_cgrp_gaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_gaddr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_assoc_dev_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_assoc_dev_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_adev_iface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_adev_iface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_rsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_rsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_rrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_rrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_qsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_qsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_qrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_qrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_lsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_lsent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mlds_cgrp_stats_lrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mldp_cgrp_stats_lrcvd(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int get_mld_proxy_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "enable", &val); + + if (strcmp(val, "1") == 0) + *value = "true"; + else + *value = "false"; + + return 0; +} +static int set_mld_proxy_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_set_value_by_section((struct uci_section *)data, "enable", (b) ? "1" : "0"); + break; + } + + return 0; +} + +static int get_mld_proxy_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "version", &val); + + if (strcmp(val, "2") == 0) + *value = "V2"; + else + *value = "V1"; + + return 0; +} + +static int set_mld_proxy_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + char val[4]; + + switch (action) { + case VALUECHECK: + if ((strcmp("V2", value) != 0) && (strcmp("V1", value) != 0)) + return FAULT_9007; + break; + case VALUESET: + if (strcmp(value, "V2") == 0) + strcpy(val, "2"); + else + strcpy(val, "1"); + + dmuci_set_value_by_section((struct uci_section *)data, "version", val); + break; + } + + return 0; +} + +static int get_mld_proxy_robustness(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + dmuci_get_value_by_section_string((struct uci_section *)data, "robustness", value); + return 0; +} + +static int get_mldp_query_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + dmuci_get_value_by_section_string((struct uci_section *)data, "query_interval", value); + return 0; +} + +static int get_mldp_q_response_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + dmuci_get_value_by_section_string((struct uci_section *)data, "query_response_interval", value); + return 0; +} + +static int get_mldp_last_mq_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + dmuci_get_value_by_section_string((struct uci_section *)data, "last_member_query_interval", value); + return 0; +} + +static int set_mldp_query_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section((struct uci_section *)data, "query_interval", value); + break; + } + + return 0; +} + +static int set_mldp_q_response_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section((struct uci_section *)data, "query_response_interval", value); + break; + } + + return 0; +} + +static int set_mldp_last_mq_interval(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section((struct uci_section *)data, "last_member_query_interval", value); + break; + } + + return 0; +} + +static int set_mld_proxy_robustness(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + + switch (action) { + case VALUECHECK: + if (dm_validate_unsignedInt(value, RANGE_ARGS{{NULL,"65535"}}, 1)) + return FAULT_9007; + break; + case VALUESET: + dmuci_set_value_by_section((struct uci_section *)data, "robustness", value); + break; + } + + return 0; +} + +static int get_mld_proxy_aggregation(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "aggregation", &val); + + if (strcmp(val, "1") == 0) + *value = "true"; + else + *value = "false"; + + return 0; +} + +static int get_mld_proxy_fast_leave(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *val; + dmuci_get_value_by_section_string((struct uci_section *)data, "fast_leave", &val); + + if (strcmp(val, "1") == 0) + *value = "true"; + else + *value = "false"; + + return 0; +} + +static int set_mld_proxy_fast_leave(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_set_value_by_section((struct uci_section *)data, "fast_leave", (b) ? "1" : "0"); + break; + } + + return 0; +} + +static int set_mld_proxy_aggregation(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_set_value_by_section((struct uci_section *)data, "aggregation", (b) ? "1" : "0"); + break; + } + + return 0; +} + +static int get_mldp_filter_no_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *s = NULL; + int cnt = 0; + + uci_path_foreach_option_eq(bbfdm, "dmmap_mcast", "proxy_filter", "section_name", + section_name((struct uci_section *)data), s) { + cnt++; + } + + dmasprintf(value, "%d", cnt); + return 0; +} + +#if 0 +static int get_mldp_interface_snooping(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + //ToDo + return 0; +} + +static int set_mldp_interface_snooping(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + //ToDo + return 0; +} +#endif + +static int set_mldp_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; + + switch (action) { + case VALUECHECK: + if (dm_validate_string(value, -1, 256, NULL, 0, NULL, 0)) + return FAULT_9007; + break; + case VALUESET: + // First check if this is a bridge type interface + if (get_igmp_snooping_interface_val(value, ifname, sizeof(ifname)) == 0) { + interface_linker = dmstrdup(ifname); + } 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) + dmasprintf(&interface_linker, "br-%s", linker); + 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); + break; + } + } + + break; + } + + return 0; +} + +static int get_mldp_interface_iface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *d_sec, *s; + char *ifname, *f_inst; + char sec_name[16]; + int found = 0; + + 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_get_value_by_section_string(d_sec, "ifname", &ifname); + found = 1; + break; + } + } + + if ((found == 0) || (ifname[0] == '\0')) { + *value = ""; + return 0; + } + + // Check if this is bridge type interface + if (strstr(ifname, "br-")) { + // Interface is bridge type, convert to network uci file section name + char val[16]; + strncpy(val, ifname, sizeof(val)); + char *tok, *end; + tok = strtok_r(val, "-", &end); + if (strcmp(tok, "br") == 0) { + strncpy(sec_name, end, sizeof(sec_name)); + } else { + goto end; + } + + char *proto; + uci_foreach_sections("network", "interface", s) { + if(strcmp(section_name(s), sec_name) != 0) + continue; + + dmuci_get_value_by_section_string(s, "proto", &proto); + if (proto[0] != '\0') { + // It is a L3 bridge, get the linker accordingly + adm_entry_get_linker_param(ctx, dm_print_path("%s%cIP%cInterface%c", + dmroot, dm_delim, dm_delim, dm_delim), sec_name, value); + } else { + // It is a L2 bridge, get the linker accordingly + struct uci_section *dmmap_section, *port; + char *br_inst, *mg, linker[64] = ""; + + get_dmmap_section_of_config_section("dmmap_network", "interface", sec_name, + &dmmap_section); + if (dmmap_section != NULL) { + dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst); + uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", + "bridge_port", "bridge_key", br_inst, port) { + dmuci_get_value_by_section_string(port, "mg_port", &mg); + if (strcmp(mg, "true") == 0) + snprintf(linker, sizeof(linker), "%s+", section_name(port)); + else + continue; + + adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, + dm_delim, dm_delim, dm_delim), linker, value); + break; + } + } + } + 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) + 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); + } + +end: + if (*value == NULL) + *value = ""; + + return 0; +} + +static int set_mldp_interface_upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + char *f_inst, *ifname; + struct uci_section *d_sec; + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &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) { + dmuci_get_value_by_section_string(d_sec, "ifname", &ifname); + 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); + break; + } + } + + break; + } + return 0; +} + +static int get_mldp_interface_upstream(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + struct uci_section *d_sec; + char *f_inst, *up; + + 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_get_value_by_section_string(d_sec, "upstream", &up); + break; + } + } + + if (strcmp(up, "1") == 0) { + *value = "true"; + } else { + *value = "false"; + } + + return 0; +} + +/* ***Device.X_IOPSYS_EU_MLD. *** */ +DMOBJ X_IOPSYS_EU_MLDObj[] = { +/* OBJ, permission, addobj, delobj, checkobj, browseinstobj, forced_inform, notification, nextdynamicobj, nextobj, leaf, linker, bbfdm_type*/ +{"Snooping", &DMWRITE, add_mld_snooping_obj, del_mld_snooping_obj, NULL, browse_mld_snooping_inst, NULL, NULL, NULL, X_IOPSYS_EU_MLDSnoopingObj, X_IOPSYS_EU_MLDSnoopingParams, NULL, BBFDM_BOTH}, +{"Proxy", &DMWRITE, add_mld_proxy_obj, del_mld_proxy_obj, NULL, browse_mld_proxy_inst, NULL, NULL, NULL, X_IOPSYS_EU_MLDProxyObj, X_IOPSYS_EU_MLDProxyParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF X_IOPSYS_EU_MLDParams[] = { +{"SnoopingNumberOfEntries", &DMREAD, DMT_UNINT, get_mlds_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{"ProxyNumberOfEntries", &DMREAD, DMT_UNINT, get_mldp_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMOBJ X_IOPSYS_EU_MLDSnoopingObj[] = { +{"ClientGroup", &DMREAD, NULL, NULL, NULL, browse_mlds_cgrp_inst, NULL, NULL, NULL, MLDSnoopingCLientGroupObj, MLDSnoopingClientGroupParams, NULL, BBFDM_BOTH}, +{"Filter", &DMWRITE, add_mlds_filter_obj, del_mlds_filter_obj, NULL, browse_mlds_filter_inst, NULL, NULL, NULL, NULL, MLDSnoopingFilterParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMOBJ MLDSnoopingCLientGroupObj[] = { +{"AssociatedDevice", &DMREAD, NULL, NULL, NULL, browse_mlds_cgrp_assoc_dev_inst, NULL, NULL, NULL, NULL, MLDSnoopingClientGroupAssociatedDeviceParams, NULL, BBFDM_BOTH}, +{"ClientGroupStats", &DMREAD, NULL, NULL, NULL, browse_mlds_cgrp_stats_inst, NULL, NULL, NULL, NULL, MLDSnoopingClientGroupStatsParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDSnoopingClientGroupParams[] = { +{"GroupAddress", &DMREAD, DMT_STRING, get_mlds_cgrp_gaddr, NULL, NULL, NULL, BBFDM_BOTH}, +{"AssociatedDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_mlds_cgrp_assoc_dev_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDSnoopingFilterParams[] = { +{"Enable", &DMWRITE, DMT_BOOL, get_mlds_filter_enable, set_mlds_filter_enable, NULL, NULL, BBFDM_BOTH}, +{"IPAddress", &DMWRITE, DMT_STRING, get_mlds_filter_address, set_mlds_filter_address, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDSnoopingClientGroupAssociatedDeviceParams[] = { +{"Interface", &DMREAD, DMT_STRING, get_mlds_cgrp_adev_iface, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDSnoopingClientGroupStatsParams[] = { +{"ReportsSent", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_rsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"ReportsReceived", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_rrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{"QueriesSent", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_qsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"QueriesReceived", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_qrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{"LeavesSent", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_lsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"LeavesReceived", &DMREAD, DMT_UNINT, get_mlds_cgrp_stats_lrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF X_IOPSYS_EU_MLDSnoopingParams[] = { +{"Enable", &DMWRITE, DMT_BOOL, get_mld_snooping_enable, set_mld_snooping_enable, NULL, NULL, BBFDM_BOTH}, +{"Version", &DMWRITE, DMT_STRING, get_mld_snooping_version, set_mld_snooping_version, NULL, NULL, BBFDM_BOTH}, +{"Robustness", &DMWRITE, DMT_UNINT, get_mld_snooping_robustness, set_mld_snooping_robustness, NULL, NULL, BBFDM_BOTH}, +{"Aggregation", &DMWRITE, DMT_BOOL, get_mld_snooping_aggregation, set_mld_snooping_aggregation, NULL, NULL, BBFDM_BOTH}, +{"Interface", &DMWRITE, DMT_STRING, get_mld_snooping_interface, set_mld_snooping_interface, NULL, NULL, BBFDM_BOTH}, +{"FilterNumberOfEntries", &DMREAD, DMT_UNINT, get_mlds_filter_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +//{"ClientGroupNumberOfEntries", &DMREAD, DMT_UNINT, get_mldp_cgrps_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMOBJ X_IOPSYS_EU_MLDProxyObj[] = { +{"Interface", &DMWRITE, add_mldp_interface_obj, del_mldp_interface_obj, NULL, browse_mldp_interface_inst, NULL, NULL, NULL, NULL, MLDProxyInterfaceParams, NULL, BBFDM_BOTH}, +//{"ClientGroup", &DMREAD, NULL, NULL, NULL, browse_mldp_cgrp_inst, NULL, NULL, NULL, MLDProxyCLientGroupObj, MLDProxyClientGroupParams, NULL, BBFDM_BOTH}, +{"Filter", &DMWRITE, add_mldp_filter_obj, del_mldp_filter_obj, NULL, browse_mldp_filter_inst, NULL, NULL, NULL, NULL, MLDProxyFilterParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMOBJ MLDProxyCLientGroupObj[] = { +{"AssociatedDevice", &DMREAD, NULL, NULL, NULL, browse_mldp_cgrp_assoc_dev_inst, NULL, NULL, NULL, NULL, MLDProxyClientGroupAssociatedDeviceParams, NULL, BBFDM_BOTH}, +{"ClientGroupStats", &DMREAD, NULL, NULL, NULL, browse_mldp_cgrp_stats_inst, NULL, NULL, NULL, NULL, MLDProxyClientGroupStatsParams, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDProxyClientGroupParams[] = { +{"GroupAddress", &DMREAD, DMT_STRING, get_mldp_cgrp_gaddr, NULL, NULL, NULL, BBFDM_BOTH}, +{"AssociatedDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_mldp_cgrp_assoc_dev_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDProxyFilterParams[] = { +{"Enable", &DMWRITE, DMT_BOOL, get_mldp_filter_enable, set_mldp_filter_enable, NULL, NULL, BBFDM_BOTH}, +{"IPAddress", &DMWRITE, DMT_STRING, get_mldp_filter_address, set_mldp_filter_address, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDProxyClientGroupAssociatedDeviceParams[] = { +{"Interface", &DMREAD, DMT_STRING, get_mldp_cgrp_adev_iface, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDProxyClientGroupStatsParams[] = { +{"ReportsSent", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_rsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"ReportsReceived", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_rrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{"QueriesSent", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_qsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"QueriesReceived", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_qrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{"LeavesSent", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_lsent, NULL, NULL, NULL, BBFDM_BOTH}, +{"LeavesReceived", &DMREAD, DMT_UNINT, get_mldp_cgrp_stats_lrcvd, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF MLDProxyInterfaceParams[] = { +{"Interface", &DMWRITE, DMT_STRING, get_mldp_interface_iface, set_mldp_interface_iface, NULL, NULL, BBFDM_BOTH}, +{"Upstream", &DMWRITE, DMT_BOOL, get_mldp_interface_upstream, set_mldp_interface_upstream, NULL, NULL, BBFDM_BOTH}, +//{"Snooping", &DMWRITE, DMT_STRING, get_mldp_interface_snooping, set_mldp_interface_snooping, NULL, NULL, BBFDM_BOTH}, +{0} +}; + +DMLEAF X_IOPSYS_EU_MLDProxyParams[] = { +{"Enable", &DMWRITE, DMT_BOOL, get_mld_proxy_enable, set_mld_proxy_enable, NULL, NULL, BBFDM_BOTH}, +{"Version", &DMWRITE, DMT_STRING, get_mld_proxy_version, set_mld_proxy_version, NULL, NULL, BBFDM_BOTH}, +{"QueryInterval",&DMWRITE, DMT_UNINT, get_mldp_query_interval, set_mldp_query_interval, NULL, NULL, BBFDM_BOTH}, +{"QueryResponseInterval",&DMWRITE, DMT_UNINT, get_mldp_q_response_interval, set_mldp_q_response_interval, NULL, NULL, BBFDM_BOTH}, +{"LastMemberQueryInterval",&DMWRITE, DMT_UNINT, get_mldp_last_mq_interval, set_mldp_last_mq_interval, NULL, NULL, BBFDM_BOTH}, +{"ImmediateLeave", &DMWRITE, DMT_BOOL, get_mld_proxy_fast_leave, set_mld_proxy_fast_leave, NULL, NULL, BBFDM_BOTH}, +{"Robustness", &DMWRITE, DMT_UNINT, get_mld_proxy_robustness, set_mld_proxy_robustness, NULL, NULL, BBFDM_BOTH}, +{"Aggregation", &DMWRITE, DMT_BOOL, get_mld_proxy_aggregation, set_mld_proxy_aggregation, NULL, NULL, BBFDM_BOTH}, +{"FilterNumberOfEntries", &DMREAD, DMT_UNINT, get_mldp_filter_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{"InterfaceNumberOfEntries", &DMREAD, DMT_UNINT, get_mldp_interface_no_of_entries, NULL, NULL, NULL, BBFDM_BOTH}, +{0} +}; diff --git a/dmtree/tr181/x_iopsys_eu_mld.h b/dmtree/tr181/x_iopsys_eu_mld.h new file mode 100644 index 00000000..1d1b88ce --- /dev/null +++ b/dmtree/tr181/x_iopsys_eu_mld.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author Rahul Thakur + * + */ + +#ifndef __SE_MLD_H +#define __SE_MLD_H + +#include + +extern DMOBJ X_IOPSYS_EU_MLDObj[]; +extern DMLEAF X_IOPSYS_EU_MLDParams[]; + +extern DMOBJ X_IOPSYS_EU_MLDSnoopingObj[]; +extern DMLEAF X_IOPSYS_EU_MLDSnoopingParams[]; +extern DMOBJ MLDSnoopingCLientGroupObj[]; +extern DMLEAF MLDSnoopingClientGroupParams[]; +extern DMLEAF MLDSnoopingClientGroupStatsParams[]; +extern DMLEAF MLDSnoopingClientGroupAssociatedDeviceParams[]; +extern DMLEAF MLDSnoopingFilterParams[]; + +extern DMOBJ X_IOPSYS_EU_MLDProxyObj[]; +extern DMLEAF X_IOPSYS_EU_MLDProxyParams[]; +extern DMLEAF MLDProxyInterfaceParams[]; +extern DMOBJ MLDProxyCLientGroupObj[]; +extern DMLEAF MLDProxyClientGroupParams[]; +extern DMLEAF MLDProxyClientGroupStatsParams[]; +extern DMLEAF MLDProxyClientGroupAssociatedDeviceParams[]; +extern DMLEAF MLDProxyFilterParams[]; +#endif diff --git a/libbbf_api/dmcommon.c b/libbbf_api/dmcommon.c index c32d1f14..8e71c201 100644 --- a/libbbf_api/dmcommon.c +++ b/libbbf_api/dmcommon.c @@ -787,7 +787,7 @@ void synchronize_specific_config_sections_with_dmmap_mcast_iface(char *package, char *s_name; dmmap_file_path_get(dmmap_package); - uci_foreach_sections(package, section_type, s) { + uci_foreach_option_eq(package, section_type, "proto", proto, s) { if (strcmp(section_name(s), section_name((struct uci_section *)data)) != 0) continue; @@ -889,7 +889,7 @@ void synchronize_specific_config_sections_with_dmmap_filter(char *package, char dmmap_file_path_get(dmmap_package); - uci_foreach_sections(package, section_type, s) { + uci_foreach_option_eq(package, section_type, "proto", proto, s) { if (strcmp(section_name(s), section_name((struct uci_section *)data)) != 0) continue; /* @@ -2303,3 +2303,115 @@ int create_mac_addr_upstream_intf(char *mac_addr, char *mac, int mac_len) return -1; } + +void del_dmmap_sec_with_opt_eq(char *dmmap_file, char *section, char *option, char *value) +{ + struct uci_section *d_sec = NULL; + struct uci_section *stmp = NULL; + char *opt_val; + + uci_path_foreach_sections_safe(bbfdm, dmmap_file, section, stmp, d_sec) { + dmuci_get_value_by_section_string(d_sec, option, &opt_val); + if (strcmp(opt_val, value) == 0) + dmuci_delete_by_section_unnamed_bbfdm(d_sec, NULL, NULL); + } +} + +void sync_dmmap_bool_to_uci_list(struct uci_section *s, char *section, + char *value, bool b) +{ + struct uci_list *v = NULL; + struct uci_element *e; + char *val; + + dmuci_get_value_by_section_list(s, section, &v); + if (v != NULL) { + uci_foreach_element(v, e) { + val = dmstrdup(e->name); + if (strcmp(val, value) == 0) { + if (!b) { + // remove this entry + dmuci_del_list_value_by_section(s, section, value); + } + + // Further action is not required + return; + } + } + } + + // If control has reached this point, that means, either the entry was not found + // in the list, hence, if b is true, add this entry to the list + if (b) { + dmuci_add_list_value_by_section(s, section, value); + } +} + +int get_br_key_from_lower_layer(char *lower_layer, char *key, size_t s_key) +{ + char *p = strstr(lower_layer, "Port"); + + if (!p) + return -1; + + /* Get the bridge_key. */ + int len = strlen(p); + char new_if[250] = {0}; + int i; + for (i = 0; i < strlen(lower_layer) - len; i++) { + new_if[i] = lower_layer[i]; + } + + char br_key = new_if[strlen(new_if) - 2]; + + snprintf(key, s_key, "%c", br_key); + + return 0; +} + +int get_igmp_snooping_interface_val(char *value, char *ifname, size_t s_ifname) +{ + char lower_layer[250] = {0}; + + if (value[strlen(value)-1] != '.') + snprintf(lower_layer, sizeof(lower_layer), "%s.", value); + else + strncpy(lower_layer, value, sizeof(lower_layer) - 1); + + /* Check if the value is valid or not. */ + if (strncmp(lower_layer, "Device.Bridging.Bridge.", 23) != 0) + return -1; + + char key[10] = {0}; + if (get_br_key_from_lower_layer(lower_layer, key, sizeof(key)) != 0) + return -1; + + /* Find out bridge section name using bridge key. */ + struct uci_section *s = NULL; + char *sec_name; + uci_path_foreach_option_eq(bbfdm, "dmmap_network", "interface", "bridge_instance", key, s) { + dmuci_get_value_by_section_string(s, "section_name", &sec_name); + break; + } + + // Check if network uci file has this section, if yes, then + // update the snooping interface with value as br-
+ struct uci_section *intf_s = NULL; + uci_foreach_sections("network", "interface", intf_s) { + char sec[20] = {0}; + strncpy(sec, section_name(intf_s), sizeof(sec) - 1); + if (strncmp(sec, sec_name, sizeof(sec)) != 0) + continue; + + char *type; + dmuci_get_value_by_section_string(intf_s, "type", &type); + if (*type == '\0' || strcmp(type, "bridge") != 0) + continue; + + snprintf(ifname, s_ifname, "br-%s", sec_name); + break; + + } + + return 0; +} diff --git a/libbbf_api/dmcommon.h b/libbbf_api/dmcommon.h index 8d254ed2..029df11f 100644 --- a/libbbf_api/dmcommon.h +++ b/libbbf_api/dmcommon.h @@ -340,4 +340,9 @@ char *replace_char(char *str, char find, char replace); int is_vlan_termination_section(char *name); int get_upstream_interface(char *intf_tag, int len); int create_mac_addr_upstream_intf(char *mac_addr, char *mac, int len); +int get_br_key_from_lower_layer(char *lower_layer, char *key, size_t s_key); +int get_igmp_snooping_interface_val(char *value, char *ifname, size_t s_ifname); +void sync_dmmap_bool_to_uci_list(struct uci_section *s, char *section, + char *value, bool b); +void del_dmmap_sec_with_opt_eq(char *dmmap_file, char *section, char *option, char *value); #endif