mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
bbf : Bug#4038-QoS: tr181, inner vid not configurable in l2 scenario
-Changes done to add support of configuring inner_vid via TR181 for the cases mentioned in the bug description. - Changes done to support L3 Q-in-Q changes.
This commit is contained in:
parent
6738968953
commit
196d11e8df
2 changed files with 196 additions and 8 deletions
|
|
@ -1035,6 +1035,11 @@ static void remove_vlanid_from_device_and_vlanport(char *vid)
|
|||
dmuci_set_value_by_section(s, "name", name);
|
||||
dmuci_set_value_by_section(s, "vid", "");
|
||||
}
|
||||
|
||||
// Check if this vid is set as inner_vid for any interface, then delete it.
|
||||
uci_foreach_option_eq("network", "device", "inner_vid", vid, s) {
|
||||
dmuci_delete_by_section(s, "inner_vid", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_vlanport_section(struct uci_section *vlanport_dmmap_sec, struct uci_section *bridge_sec, char *br_inst)
|
||||
|
|
@ -1679,6 +1684,10 @@ static int delObjBridgingBridgeVLANPort(char *refparam, struct dmctx *ctx, void
|
|||
{
|
||||
struct uci_section *s = NULL, *prev_s = NULL;
|
||||
|
||||
// Get the vlanid associated with the vlanport
|
||||
char *vid = NULL;
|
||||
dmuci_get_value_by_section_string(((struct bridge_vlanport_args *)data)->bridge_vlanport_sec, "vid", &vid);
|
||||
|
||||
switch (del_action) {
|
||||
case DEL_INST:
|
||||
remove_vlanport_section(((struct bridge_vlanport_args *)data)->bridge_vlanport_dmmap_sec, ((struct bridge_vlanport_args *)data)->bridge_sec,
|
||||
|
|
@ -1702,6 +1711,13 @@ static int delObjBridgingBridgeVLANPort(char *refparam, struct dmctx *ctx, void
|
|||
break;
|
||||
}
|
||||
|
||||
if (vid != NULL & vid[0] != '\0') {
|
||||
// Check if this vid is set as inner_vid for any interface, then delete it.
|
||||
uci_foreach_option_eq("network", "device", "inner_vid", vid, s) {
|
||||
dmuci_delete_by_section(s, "inner_vid", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1730,7 +1746,6 @@ static int delObjBridgingBridgeVLAN(char *refparam, struct dmctx *ctx, void *dat
|
|||
{
|
||||
struct uci_section *s = NULL, *prev_s = NULL;
|
||||
char *vid;
|
||||
|
||||
switch (del_action) {
|
||||
case DEL_INST:
|
||||
dmuci_get_value_by_section_string(((struct bridge_vlan_args *)data)->bridge_vlan_sec, "vid", &vid);
|
||||
|
|
@ -2448,6 +2463,64 @@ static int get_BridgingBridgePort_PVID(char *refparam, struct dmctx *ctx, void *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fetch_and_configure_inner_vid(char *br_inst, char *type_val, char **vid) {
|
||||
|
||||
struct uci_section *dev_s = NULL, *sec = NULL;
|
||||
char *name, *instance;
|
||||
|
||||
// Get the vid under device section with type 8021q of port under same br_inst.
|
||||
uci_foreach_option_eq("network", "device", "type", type_val, dev_s) {
|
||||
dmuci_get_value_by_section_string(dev_s, "name", &name);
|
||||
//find out the bridge instance of device section
|
||||
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "device", name, sec) {
|
||||
dmuci_get_value_by_section_string(sec, "br_inst", &instance);
|
||||
break;
|
||||
}
|
||||
|
||||
//Check if the bridge instances are same or not, if yes, then get the vid.
|
||||
char bridge_inst[20] = {0};
|
||||
strncpy(bridge_inst, br_inst, sizeof(bridge_inst));
|
||||
if (strncmp(bridge_inst, instance, sizeof(bridge_inst)) == 0) {
|
||||
if (strcmp(type_val, "8021ad") == 0) {
|
||||
dmuci_set_value_by_section(dev_s, "inner_vid", *vid);
|
||||
} else {
|
||||
dmuci_get_value_by_section_string(dev_s, "vid", vid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_inner_vid() {
|
||||
|
||||
struct uci_section *s = NULL, *sec = NULL;
|
||||
char *br_inst, *vid = NULL;
|
||||
|
||||
uci_foreach_sections("network", "interface", s) {
|
||||
// Get the bridge instance.
|
||||
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "interface", section_name(s), sec) {
|
||||
dmuci_get_value_by_section_string(sec, "br_inst", &br_inst);
|
||||
break;
|
||||
}
|
||||
|
||||
fetch_and_configure_inner_vid(br_inst, "8021q", &vid);
|
||||
|
||||
if (vid == NULL) {
|
||||
fetch_and_configure_inner_vid(br_inst, "untagged", &vid);
|
||||
}
|
||||
|
||||
//loop device section with type 8021ad and fetch the br_inst of it,
|
||||
//if same br_inst then add vid as inner_vid
|
||||
if (vid != NULL && vid[0] != '\0') {
|
||||
fetch_and_configure_inner_vid(br_inst, "8021ad", &vid);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_BridgingBridgePort_PVID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *type;
|
||||
|
|
@ -2483,6 +2556,7 @@ static int set_BridgingBridgePort_PVID(char *refparam, struct dmctx *ctx, void *
|
|||
update_bridge_ifname(((struct bridge_port_args *)data)->bridge_sec, ((struct bridge_port_args *)data)->bridge_port_sec, 0);
|
||||
dmuci_set_value_by_section(((struct bridge_port_args *)data)->bridge_port_sec, "name", new_name);
|
||||
dmuci_set_value_by_section(((struct bridge_port_args *)data)->bridge_port_sec, "vid", value);
|
||||
handle_inner_vid();
|
||||
update_bridge_ifname(((struct bridge_port_args *)data)->bridge_sec, ((struct bridge_port_args *)data)->bridge_port_sec, 1);
|
||||
dmfree(new_name);
|
||||
}
|
||||
|
|
@ -2505,6 +2579,52 @@ static int get_BridgingBridgePort_TPID(char *refparam, struct dmctx *ctx, void *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int configure_interface_type(struct uci_section *bridge_sec, struct uci_section *sec, char *interface, char *br_inst, char *value)
|
||||
{
|
||||
struct uci_section *s, *ss = NULL;
|
||||
char *vid = NULL, *inner_vid = NULL;
|
||||
|
||||
dmuci_set_value_by_section(sec, "type", value);
|
||||
|
||||
if (strncmp(value, "8021q", 5) == 0) {
|
||||
//Check if the interface has inner-vid if so then delete
|
||||
uci_foreach_sections("network", "device", s) {
|
||||
if (strcmp(section_name(sec), section_name(s)) == 0) {
|
||||
dmuci_get_value_by_section_string(s, "inner_vid", &inner_vid);
|
||||
if (inner_vid[0] != '\0') {
|
||||
dmuci_delete_by_section(s, "inner_vid", NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//fetch the vid of the 8021q interface.
|
||||
uci_foreach_option_eq("network", "device", "name", interface, ss) {
|
||||
dmuci_get_value_by_section_string(ss, "vid", &vid);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vid != NULL && vid[0] != '\0') {
|
||||
fetch_and_configure_inner_vid(br_inst, "8021ad", &vid);
|
||||
}
|
||||
|
||||
} else if (strncmp(value, "8021ad", 6) == 0) {
|
||||
fetch_and_configure_inner_vid(br_inst, "8021q", &vid);
|
||||
|
||||
if (vid == NULL) {
|
||||
fetch_and_configure_inner_vid(br_inst, "untagged", &vid);
|
||||
}
|
||||
|
||||
//apply the vid of the interface as the inner_vid of 8021ad port
|
||||
if (vid != NULL && vid[0] != '\0') {
|
||||
dmuci_set_value_by_section(sec, "inner_vid", vid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_BridgingBridgePort_TPID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
switch (action) {
|
||||
|
|
@ -2514,9 +2634,9 @@ static int set_BridgingBridgePort_TPID(char *refparam, struct dmctx *ctx, void *
|
|||
return 0;
|
||||
case VALUESET:
|
||||
if (strcmp(value, "33024") == 0)
|
||||
dmuci_set_value_by_section(((struct bridge_port_args *)data)->bridge_port_sec, "type", "8021q");
|
||||
configure_interface_type(((struct bridge_port_args *)data)->bridge_sec, ((struct bridge_port_args *)data)->bridge_port_sec, ((struct bridge_port_args *)data)->ifname, ((struct bridge_port_args *)data)->br_inst, "8021q");
|
||||
else if (strcmp(value, "34984") == 0)
|
||||
dmuci_set_value_by_section(((struct bridge_port_args *)data)->bridge_port_sec, "type", "8021ad");
|
||||
configure_interface_type(((struct bridge_port_args *)data)->bridge_sec, ((struct bridge_port_args *)data)->bridge_port_sec, ((struct bridge_port_args *)data)->ifname, ((struct bridge_port_args *)data)->br_inst, "8021ad");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -2857,6 +2977,7 @@ static int set_BridgingBridgeVLANPort_VLAN(char *refparam, struct dmctx *ctx, vo
|
|||
dmfree(new_vid);
|
||||
}
|
||||
}
|
||||
handle_inner_vid();
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -2877,6 +2998,7 @@ static int get_BridgingBridgeVLANPort_Port(char *refparam, struct dmctx *ctx, vo
|
|||
|
||||
static int set_BridgingBridgeVLANPort_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
|
||||
char lower_layer[256] = {0}, lower_layer_path[256] = {0};
|
||||
|
||||
switch (action) {
|
||||
|
|
@ -2959,6 +3081,7 @@ static int set_BridgingBridgeVLANPort_Port(char *refparam, struct dmctx *ctx, vo
|
|||
}
|
||||
}
|
||||
}
|
||||
handle_inner_vid();
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1196,13 +1196,21 @@ static int get_EthernetVLANTermination_LastChange(char *refparam, struct dmctx *
|
|||
|
||||
static int get_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
|
||||
{
|
||||
char *name;
|
||||
char *name, *type, *inner_vid, *dev_name;
|
||||
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "name", &name);
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "type", &type);
|
||||
char *vid = strchr(name, '.');
|
||||
if (vid) *vid = '\0';
|
||||
|
||||
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), name, value);
|
||||
if (strncmp(type, "8021ad", 6) == 0) {
|
||||
// 8021ad device, will have a vlan termination object as its lowerlayer
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "inner_vid", &inner_vid);
|
||||
dmasprintf(&dev_name, "%s.%s", name, inner_vid);
|
||||
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cVLANTermination%c", dmroot, dm_delim, dm_delim, dm_delim), dev_name, value);
|
||||
} else {
|
||||
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), name, value);
|
||||
}
|
||||
if (*value == NULL)
|
||||
*value = "";
|
||||
return 0;
|
||||
|
|
@ -1278,7 +1286,32 @@ static int set_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx
|
|||
// Set ifname and name options of device section
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "ifname", linker);
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "name", new_name);
|
||||
} else if (strncmp(lower_layer, "Device.Ethernet.VLANTermination.", 32) == 0) {
|
||||
char new_name[16] = {0}, *linker = NULL;
|
||||
struct uci_section *ss = NULL;
|
||||
char *dev_name, *inner_vid, *vid;
|
||||
|
||||
adm_entry_get_linker_value(ctx, lower_layer, &linker);
|
||||
if (linker == NULL || *linker == '\0')
|
||||
return -1;
|
||||
|
||||
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "vid", &vid);
|
||||
|
||||
uci_foreach_option_eq("network", "device", "name", linker, ss) {
|
||||
dmuci_get_value_by_section_string(ss, "vid", &inner_vid);
|
||||
dmuci_get_value_by_section_string(ss, "ifname", &dev_name);
|
||||
break;
|
||||
}
|
||||
snprintf(new_name, sizeof(new_name), "%s.%s.%s", dev_name, inner_vid, vid);
|
||||
if (is_name_exist_in_devices(new_name))
|
||||
return -1;
|
||||
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "ifname", dev_name);
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "name", new_name);
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "inner_vid", inner_vid);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -1293,8 +1326,9 @@ static int get_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
|
|||
|
||||
static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
|
||||
{
|
||||
char *ifname, *name, *curr_ifname, *type;
|
||||
struct uci_section *s = NULL;
|
||||
char *ifname, *name, *curr_ifname, *type, *inner_vid, *old_vid, *old_name, *sec_name, *ad_vid;
|
||||
char *ad_itf_ifname;
|
||||
struct uci_section *s = NULL, *d_sec = NULL;
|
||||
|
||||
switch (action) {
|
||||
case VALUECHECK:
|
||||
|
|
@ -1310,7 +1344,14 @@ static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
|
|||
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "ifname", &ifname);
|
||||
if (*ifname != '\0') {
|
||||
dmasprintf(&name, "%s.%s", ifname, value);
|
||||
if (strcmp(type, "8021ad") == 0) {
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "inner_vid", &inner_vid);
|
||||
dmasprintf(&name, "%s.%s.%s", ifname, inner_vid, value);
|
||||
} else {
|
||||
dmuci_get_value_by_section_string((struct uci_section *)data, "vid", &old_vid);
|
||||
dmasprintf(&old_name, "%s.%s.", ifname, old_vid);
|
||||
dmasprintf(&name, "%s.%s", ifname, value);
|
||||
}
|
||||
|
||||
if (is_name_exist_in_devices(name))
|
||||
return -1;
|
||||
|
|
@ -1321,6 +1362,30 @@ static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
|
|||
dmuci_set_value_by_section(s, "ifname", name);
|
||||
}
|
||||
|
||||
if (strncmp(type, "8021q", 5) == 0) {
|
||||
// Update the 8021ad instance with vid of lower layer
|
||||
uci_foreach_sections("network", "device", d_sec) {
|
||||
// We do not need to get the type here since we have the name
|
||||
// already with us, we can use that as a key
|
||||
dmuci_get_value_by_section_string(d_sec, "name", &sec_name);
|
||||
if (strncmp(sec_name, old_name, strlen(old_name)) == 0) {
|
||||
dmuci_get_value_by_section_string(d_sec, "vid", &ad_vid);
|
||||
dmasprintf(&ad_itf_ifname, "%s.%s.%s", ifname, value, ad_vid);
|
||||
dmasprintf(&old_name, "%s.%s.%s", ifname, old_vid, ad_vid);
|
||||
|
||||
dmuci_set_value_by_section(d_sec, "inner_vid", value);
|
||||
dmuci_set_value_by_section(d_sec, "name", ad_itf_ifname);
|
||||
// if this 8021ad instance is lowerlayer to an ip interface, then
|
||||
// the ifname of the ip interface also needs to be updated
|
||||
uci_foreach_option_eq("network", "interface", "ifname", old_name, s) {
|
||||
dmuci_set_value_by_section(s, "ifname", ad_itf_ifname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set name option of the device section
|
||||
dmuci_set_value_by_section((struct uci_section *)data, "name", name);
|
||||
dmfree(name);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue