Ticket refs #2582: libbbf: add support for handling macvlan interfaces

This commit is contained in:
Amin Ben Ramdhane 2020-05-17 16:18:42 +01:00
parent 4354aa2117
commit 6acb70c71c
4 changed files with 401 additions and 495 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 iopsys Software Solutions AB
* 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
@ -45,93 +45,126 @@ static int eth_port_sysfs(const struct eth_port_args *args, const char *name, ch
return get_net_device_sysfs(args->ifname, name, value);
}
static int is_device_exist(char *device)
static struct uci_section *is_device_section_exist(char *device)
{
struct uci_section *s = NULL;
char *dev;
uci_path_foreach_sections(bbfdm, DMMAP, "link", s) {
dmuci_get_value_by_section_string(s, "device", &dev);
char *p = strtok(dev, ".");
if (p != NULL) {
if (strcmp(p, device) == 0) {
return 1;
}
}
if (strcmp(dev, device) == 0)
return s;
}
return s;
}
static int check_section_in_curr_section(char *curr_section, char *section)
{
char *pch = NULL, *pchr = NULL, section_list[256] = {0};
strncpy(section_list, curr_section, sizeof(section_list) - 1);
for (pch = strtok_r(section_list, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
if (strcmp(pch, section) == 0)
return 1;
}
return 0;
}
static void create_link(char *ifname)
static void add_section_in_curr_section(struct uci_section *dmmap_section, char *curr_section, char *section)
{
char *macaddr, *v, *device;
struct uci_section *dmmap = NULL;
char section_list[128] = {0}, *p = section_list;
dmstrappendstr(p, curr_section);
dmstrappendchr(p, ',');
dmstrappendstr(p, section);
dmstrappendend(p);
macaddr = get_macaddr(ifname);
dmuci_set_value_by_section(dmmap_section, "section_name", section_list);
}
static int is_name_exist_in_devices(char *name)
{
struct uci_section *s = NULL;
uci_foreach_option_eq("network", "device", "name", name, s) {
return 1;
}
return 0;
}
static void add_new_dmmap_section(char *macaddr, char*interface, char *section_name)
{
struct uci_section *dmmap = NULL;
char *v;
dmuci_add_section_bbfdm(DMMAP, "link", &dmmap, &v);
dmuci_set_value_by_section(dmmap, "mac", macaddr);
dmuci_set_value_by_section(dmmap, "device", interface);
dmuci_set_value_by_section(dmmap, "section_name", section_name);
}
static void create_link(char *sec_name, char *mac_addr)
{
char *macaddr = (*mac_addr != '\0') ? mac_addr : get_macaddr(sec_name);
if (macaddr[0] == '\0')
return;
device = get_device(ifname);
char *device = get_device(sec_name);
if (device[0] == '\0')
return;
/* Interfaces might share the same mac address */
if (is_mac_exist(macaddr))
return;
/* For all the Ethernet link objects pointing to same Ethernet Interface,
* we can omit creating multiple Ethernet link entries.*/
char intf[250] = {0};
/* For all the Ethernet link objects pointing to same Ethernet Interface, only one ethernet link */
char intf[32] = {0};
strncpy(intf, device, sizeof(intf) - 1);
char *p = strtok(intf, ".");
char *p = strchr(intf, '.');
if (p != NULL) {
if (is_device_exist(p))
return;
*p = '\0';
struct uci_section *dmmap_section = is_device_section_exist(intf);
if (dmmap_section) {
char *section_name;
dmuci_get_value_by_section_string(dmmap_section, "section_name", &section_name);
/* Check section name exist => if yes, return*/
if (check_section_in_curr_section(section_name, sec_name))
return;
/* Update only section name */
add_section_in_curr_section(dmmap_section, section_name, sec_name);
} else {
/* Add new dmmap section */
add_new_dmmap_section(macaddr, intf, sec_name);
}
return;
}
/* Check if section_name exists or not, if yes then do not add section just update
* the params else add section and update the params. */
struct uci_section *s = NULL;
char *sec_name;
int ret = 1;
char *dev_sec_name;
uci_path_foreach_sections(bbfdm, DMMAP, "link", s) {
dmuci_get_value_by_section_string(s, "section_name", &sec_name);
if (strcmp(ifname, sec_name) == 0) {
dmuci_get_value_by_section_string(s, "section_name", &dev_sec_name);
if (strcmp(sec_name, dev_sec_name) == 0) {
dmuci_set_value_by_section(s, "mac", macaddr);
dmuci_set_value_by_section(s, "device", device);
dmuci_set_value_by_section(s, "section_name", ifname);
ret = 0;
break;
} else {
ret = 1;
return;
}
}
if (ret == 1 ) {
dmuci_add_section_bbfdm(DMMAP, "link", &dmmap, &v);
dmuci_set_value_by_section(dmmap, "mac", macaddr);
dmuci_set_value_by_section(dmmap, "device", device);
dmuci_set_value_by_section(dmmap, "section_name", ifname);
}
/* Add new dmmap section */
add_new_dmmap_section(macaddr, intf, sec_name);
}
static int dmmap_synchronizeEthernetLink(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
struct uci_section *s = NULL;
char *ifname, *proto;
char *ifname, *macaddr;
uci_foreach_sections("network", "interface", s) {
dmuci_get_value_by_section_string(s, "proto", &proto);
if (strcmp(section_name(s), "loopback") == 0 || *proto == '\0')
if (strcmp(section_name(s), "loopback") == 0)
continue;
dmuci_get_value_by_section_string(s, "ifname", &ifname);
if (*ifname == '\0' || *ifname == '@')
if (*ifname == '\0')
continue;
create_link(section_name(s));
dmuci_get_value_by_section_string(s, "macaddr", &macaddr);
create_link(section_name(s), macaddr);
}
return 0;
}
@ -234,7 +267,7 @@ static int get_linker_interface(char *refparam, struct dmctx *dmctx, void *data,
static int get_linker_link(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker)
{
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", linker);
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", linker);
return 0;
}
@ -252,88 +285,63 @@ static int get_linker_vlan_term(char *refparam, struct dmctx *dmctx, void *data,
**************************************************************/
static int addObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
char *inst, *v;
struct uci_section *dmmap_network= NULL;
char *inst, *v, *val, *interface_name;
struct uci_section *s = NULL, *dmmap_link = NULL;
inst = get_last_instance_bbfdm(DMMAP, "link", "link_instance");
dmuci_add_section_bbfdm(DMMAP, "link", &dmmap_network, &v);
*instance = update_instance_bbfdm(dmmap_network, inst, "link_instance");
return 0;
}
dmasprintf(&interface_name, "link_%d", inst ? atoi(inst)+1 : 1);
static int del_ethernet_link_instance(char *sect_name)
{
char intf_tag[50] = {0};
struct uci_section *s = NULL, *intf_s = NULL, *prev_s = NULL, *dev_s = NULL;
int ret = 0;
/* Get the upstream interface. */
get_upstream_interface(intf_tag, sizeof(intf_tag));
/* Create untagged upstream interface. */
if (intf_tag[0] != '\0')
strcat(intf_tag, ".1");
/* Get section from section_name.*/
uci_foreach_sections("network", "interface", intf_s) {
if (strcmp(section_name(intf_s), sect_name) == 0) {
char *intf;
dmuci_get_value_by_section_string(intf_s, "ifname", &intf);
/* If ifname is same as of WAN port then delete the interface
* section and the device section.*/
if (strncmp(intf_tag, intf, sizeof(intf_tag)) == 0) {
prev_s = intf_s;
ret = 1;
} else {
char *proto;
dmuci_get_value_by_section_string(intf_s, "proto", &proto);
dmuci_delete_by_section(intf_s, "proto", proto);
}
break;
}
}
if (ret == 1) {
/* Remove the section from UCI. */
if (prev_s) dmuci_delete_by_section(prev_s, NULL, NULL);
/* Remove the device section from the UCI. */
uci_foreach_option_eq("network", "device", "name", intf_tag, s) {
dev_s = s;
break;
}
if (dev_s) dmuci_delete_by_section(dev_s, NULL, NULL);
}
/* Remove the Link section from dmmap. */
struct uci_section *dmmap_section = NULL;
get_dmmap_section_of_config_section("dmmap", "link", sect_name, &dmmap_section);
if (dmmap_section) dmuci_delete_by_section(dmmap_section, NULL, NULL);
/* Add device section */
dmuci_add_section("network", "interface", &s, &val);
dmuci_rename_section_by_section(s, interface_name);
/* Add link section in dmmap file */
dmuci_add_section_bbfdm(DMMAP, "link", &dmmap_link, &v);
dmuci_set_value_by_section(dmmap_link, "section_name", interface_name);
*instance = update_instance_bbfdm(dmmap_link, inst, "link_instance");
return 0;
}
static int delObjEthernetLink(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
char *sect_name = NULL;
struct uci_section *s = NULL;
struct uci_section *s = NULL, *stmp = NULL, *ss = NULL, *sstmp = NULL;
char *sect_name = NULL, *section_list = NULL, *pch = NULL, *pchr = NULL;
switch (del_action) {
case DEL_INST:
/* Deletion of EthernetLink to support L2 VLAN deployments. */
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "section_name", &sect_name);
get_config_section_of_dmmap_section("network", "interface", sect_name, &s);
if(!s) {
dmuci_delete_by_section(((struct dm_args *)data)->section, NULL, NULL);
} else {
del_ethernet_link_instance(sect_name);
// Remove dmmap section
dmuci_delete_by_section(((struct dm_args *)data)->section, NULL, NULL);
// Check each network section in the list of sections
if (*sect_name == '\0')
return -1;
section_list = dmstrdup(sect_name);
for (pch = strtok_r(section_list, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
// Remove network and device section
uci_foreach_sections_safe("network", "interface", stmp, s) {
if (strcmp(section_name(s), pch) == 0) {
// Remove the device section corresponding to this interface if exists
char *device = get_device(pch);
uci_foreach_option_eq_safe("network", "device", "name", device, sstmp, ss) {
char *type;
dmuci_get_value_by_section_string(s, "type", &type);
if (strcmp(type, "untagged") == 0) dmuci_delete_by_section(ss, NULL, NULL);
break;
}
// Remove network section
dmuci_delete_by_section(s, NULL, NULL);
break;
}
}
}
dmfree(section_list);
return 0;
case DEL_ALL:
return FAULT_9005;
}
return 0;
}
@ -376,7 +384,7 @@ static int delObjEthernetVLANTermination(char *refparam, struct dmctx *ctx, void
uci_foreach_sections_safe("network", "device", sdevtmp, s_dev) {
dmuci_get_value_by_section_string(s_dev, "type", &type);
dmuci_get_value_by_section_string(s_dev, "name", &name);
if (strcmp(type, "untagged") == 0 || (name && !is_vlan_termination_section(name)))
if (strcmp(type, "untagged") == 0 || (*name != '\0' && !is_vlan_termination_section(name)))
continue;
// Remove device section in dmmap_network file
@ -430,7 +438,7 @@ static int get_Ethernet_VLANTerminationNumberOfEntries(char *refparam, struct dm
uci_foreach_sections("network", "device", s) {
dmuci_get_value_by_section_string(s, "type", &type);
dmuci_get_value_by_section_string(s, "name", &name);
if (strcmp(type, "untagged") == 0 || !is_vlan_termination_section(name))
if (strcmp(type, "untagged") == 0 || (*name != '\0' && !is_vlan_termination_section(name)))
continue;
cnt++;
}
@ -819,276 +827,42 @@ static int get_EthernetLink_LastChange(char *refparam, struct dmctx *ctx, void *
static int get_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
struct uci_section *s = NULL;
char *link_mac, *proto, *type, *ifname, *mac;
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "mac", &link_mac);
uci_foreach_sections("network", "interface", s) {
dmuci_get_value_by_section_string(s, "proto", &proto);
if (strcmp(section_name(s), "loopback") == 0 || *proto == '\0')
continue;
dmuci_get_value_by_section_string(s, "ifname", &ifname);
if (*ifname == '\0' || *ifname == '@')
continue;
mac = get_macaddr(section_name(s));
if (mac[0] == '\0' || strcasecmp(mac, link_mac) != 0)
continue;
dmuci_get_value_by_section_string(s, "type", &type);
if (strcmp(type, "bridge") == 0) {
struct uci_section *dmmap_section, *port;
get_dmmap_section_of_config_section("dmmap_network", "interface", section_name(s), &dmmap_section);
if (dmmap_section != NULL) {
char *br_inst, *mg;
dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst);
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, port) {
dmuci_get_value_by_section_string(port, "management", &mg);
if (strcmp(mg, "1") == 0) {
char *device, linker[512] = "";
dmuci_get_value_by_section_string(port, "device", &device);
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(port), device);
adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
if (*value == NULL)
*value = "";
break;
}
}
}
} else {
/* For upstream interface, set the lowerlayer to wan port of Ethernet.Interface */
char intf_tag[50] = {0};
/* Get the upstream interface. */
get_upstream_interface(intf_tag, sizeof(intf_tag));
if (intf_tag[0] != '\0') {
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), intf_tag, value);
if (*value == NULL)
*value = "";
}
}
break;
}
return 0;
}
static int set_ethlink_lowerlayer_bridge(char *lower_layer, char *instance)
{
int len = 0, i = 0;
char new_if[250] = {0}, key[10] = {0};
struct uci_section *s = NULL, *intf_s = NULL;
char *sec_name;
char *p = strstr(lower_layer, "Port");
if (p) {
/* Get the bridge_key. */
len = strlen(p);
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, sizeof(key), "%c", br_key);
/* Find out bridge section name using bridge key. */
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 section name is present in network UCI wd type as bridge
* and ifname not empty, if yes then update
* the section with proto 'dhcp' else do nothing. */
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) {
char *type, *ifname;
dmuci_get_value_by_section_string(intf_s, "type", &type);
if (*type == '\0' || strcmp(type, "bridge") != 0)
return -1;
dmuci_get_value_by_section_string(intf_s, "ifname", &ifname);
if (*ifname == '\0')
return -1;
/* Add ethernet link params to dmmap link section. */
uci_path_foreach_sections(bbfdm, DMMAP, "link", s) {
char *inst;
char link_inst[10] = {0};
dmuci_get_value_by_section_string(s, "link_instance", &inst);
strncpy(link_inst, instance, sizeof(link_inst) - 1);
/* Check if the link instance are same or not. */
if (strncmp(link_inst, inst, sizeof(link_inst)) == 0) {
dmuci_set_value_by_section(s, "section_name", section_name(intf_s));
break;
}
}
/* Set the value of proto to the section. */
dmuci_set_value_by_section(intf_s, "proto", "dhcp");
}
}
}
return 0;
}
static int check_set_linker_in_uci(char *intf, char *instance, char *mac_addr)
{
struct uci_section *s = NULL, *link_s = NULL, *mac_s = NULL, *prev_s = NULL;
int mac_present = 0;
uci_foreach_option_eq("network", "interface", "ifname", intf, s) {
/* Fetch the mac address of the interface. */
char *macaddr = get_macaddr(section_name(s));
/* Check if mac is present in dmmap link section. */
uci_path_foreach_option_eq(bbfdm, DMMAP, "link", "mac", macaddr, mac_s) {
/* Get the link instance of the section. */
char *link;
dmuci_get_value_by_section_string(mac_s, "link_instance", &link);
/* Check if the link instance are same or not. */
if (strcmp(link, instance) != 0) {
/* Delete the new link inst as mac already exists. */
uci_path_foreach_option_eq(bbfdm, DMMAP, "link", "link_instance", instance, link_s) {
prev_s = link_s;
}
if (prev_s) dmuci_delete_by_section(prev_s, NULL, NULL);
}
mac_present = 1;
break;
}
if (mac_present == 1) {
dmuci_set_value_by_section(s, "proto", "dhcp");
return 1;
} else {
/* Add section name and mac in dmmap link section if
* link instances are same. */
uci_path_foreach_sections(bbfdm, DMMAP, "link", link_s) {
char *inst;
char link_inst[10] = {0};
dmuci_get_value_by_section_string(link_s, "link_instance", &inst);
strncpy(link_inst, instance, sizeof(link_inst) - 1);
/* Check if the link instance are same or not. */
if (strncmp(link_inst, inst, sizeof(link_inst)) == 0) {
dmuci_set_value_by_section(link_s, "section_name", section_name(s));
dmuci_set_value_by_section(link_s, "mac", mac_addr);
char *linker;
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "device", &linker);
char *bridge = strstr(linker, "br-");
if (bridge) {
char *int_name;
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "section_name", &int_name);
struct uci_section *dmmap_section, *port;
get_dmmap_section_of_config_section("dmmap_network", "interface", int_name, &dmmap_section);
if (dmmap_section != NULL) {
char *br_inst, *mg;
dmuci_get_value_by_section_string(dmmap_section, "bridge_instance", &br_inst);
uci_path_foreach_option_eq(bbfdm, "dmmap_bridge_port", "bridge_port", "br_inst", br_inst, port) {
dmuci_get_value_by_section_string(port, "management", &mg);
if (strcmp(mg, "1") == 0) {
char *device, linker[512] = "";
dmuci_get_value_by_section_string(port, "device", &device);
snprintf(linker, sizeof(linker), "br_%s:%s+%s", br_inst, section_name(port), device);
adm_entry_get_linker_param(ctx, dm_print_path("%s%cBridging%cBridge%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
if (*value == NULL)
*value = "";
break;
}
}
dmuci_set_value_by_section(s, "proto", "dhcp");
return 1;
}
} else {
char *vid = strchr(linker, '.');
if (vid) *vid = '\0';
char *macvlan = strchr(linker, '_');
if (macvlan) *macvlan = '\0';
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cInterface%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
if (*value == NULL)
*value = "";
}
return 0;
}
static int set_lowerlayer_in_uci(char *mac_addr, char *instance, char *intf, char *linker)
{
int val_present = 0;
char *val;
struct uci_section *s = NULL, *link_s = NULL, *mac_s = NULL, *prev_s = NULL;
dmuci_add_section_and_rename("network", "interface", &s, &val);
/* Check if mac is present in dmmap link section. */
uci_path_foreach_option_eq(bbfdm, DMMAP, "link", "mac", mac_addr, mac_s) {
/* Get the link instance of the section. */
char *link;
dmuci_get_value_by_section_string(mac_s, "link_instance", &link);
/* Check if the link instance are same or not. */
if (strcmp(link, instance) != 0) {
/* Delete the new link inst as mac already exists. */
uci_path_foreach_option_eq(bbfdm, DMMAP, "link", "link_instance", instance, link_s) {
prev_s = link_s;
}
if (prev_s) dmuci_delete_by_section(prev_s, NULL, NULL);
}
val_present = 1;
break;
}
if (val_present == 0) {
/* Add ethernet link params to dmmap link section. */
uci_path_foreach_sections(bbfdm, DMMAP, "link", link_s) {
char *inst;
char link_inst[10] = {0};
dmuci_get_value_by_section_string(link_s, "link_instance", &inst);
strncpy(link_inst, instance, sizeof(link_inst) - 1);
/* Check if the link instance are same or not. */
if (strncmp(link_inst, inst, sizeof(link_inst)) == 0) {
dmuci_set_value_by_section(link_s, "section_name", section_name(s));
dmuci_set_value_by_section(link_s, "mac", mac_addr);
break;
}
}
}
dmuci_set_value_by_section(s, "proto", "dhcp");
dmuci_set_value_by_section(s, "ifname", intf);
/* Add config device section. */
struct uci_section *dev_s;
dmuci_add_section_and_rename("network", "device", &dev_s, &val);
dmuci_set_value_by_section(dev_s, "type", "untagged");
char *tok = strtok(linker, ".");
dmuci_set_value_by_section(dev_s, "ifname", tok);
dmuci_set_value_by_section(dev_s, "name", intf);
dmuci_set_value_by_section(dev_s, "macaddr", mac_addr);
return 0;
}
static int set_ethlink_lowerlayer_eth_intf(char *lower_layer, char *instance, char *linker)
{
/* Get the upstream interface. */
char intf_tag[50] = {0};
/* Get the upstream interface. */
get_upstream_interface(intf_tag, sizeof(intf_tag));
/* Fetch the macaddress of upstream interface. */
char *mac = get_macaddr_from_device(intf_tag);
/* Create a mac address for the tagged upstream interfaces
* using the base mac address. */
char mac_addr[25] = {0};
create_mac_addr_upstream_intf(mac_addr, mac, sizeof(mac_addr));
/* Create untagged upstream interface. */
if (intf_tag[0] != '\0')
strcat(intf_tag, ".1");
char intf[20] = {0};
if (strcmp(linker, intf_tag) == 0)
strncpy(intf, linker, sizeof(intf) - 1);
else {
snprintf(intf, sizeof(intf), "%s.%s", linker, "1");
if (strcmp(intf, intf_tag) != 0)
return -1;
}
/* Check if linker is present in network UCI, if yes the update
* the proto, else create a interface and device section. */
int ret = check_set_linker_in_uci(intf, instance, mac_addr);
/* Linker is not present in the UCI. */
if (ret == 0) {
set_lowerlayer_in_uci(mac_addr, instance, intf, linker);
}
return 0;
}
static int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
char lower_layer[250] = {0};
@ -1104,14 +878,22 @@ static int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void
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) {
set_ethlink_lowerlayer_bridge(lower_layer, instance);
} else if (strncmp(lower_layer, "Device.Ethernet.Interface.", 26) == 0) {
/* Find the linker of the lowerlayer value to be set. */
char *linker;
if (strncmp(lower_layer, "Device.Ethernet.Interface.", 26) == 0) {
char *linker, *int_name;
adm_entry_get_linker_value(ctx, lower_layer, &linker);
set_ethlink_lowerlayer_eth_intf(lower_layer, instance, linker);
if (linker == NULL || *linker == '\0')
return -1;
dmuci_set_value_by_section(((struct dm_args *)data)->section, "device", linker);
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "section_name", &int_name);
struct uci_section *s;
uci_foreach_sections("network", "interface", s) {
if (strcmp(section_name(s), int_name) == 0) {
dmuci_set_value_by_section(s, "ifname", linker);
break;
}
}
}
break;
}
@ -1251,28 +1033,15 @@ 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 *macaddr, *devname, *linker = "";
char *name;
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &devname);
if (*devname != '\0') {
macaddr = get_macaddr_from_device(devname);
if (macaddr[0] != '\0' && is_mac_exist(macaddr))
linker = macaddr;
else {
char intf_tag[64] = {0};
get_upstream_interface(intf_tag, sizeof(intf_tag));
if (intf_tag[0] != '\0') {
strcat(intf_tag, ".1");
linker = get_macaddr_from_device(intf_tag);
}
}
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &name);
char *vid = strchr(name, '.');
if (vid) *vid = '\0';
if (linker[0] != '\0') {
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
if (*value == NULL)
*value = "";
}
}
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;
}
@ -1292,36 +1061,55 @@ static int set_EthernetVLANTermination_LowerLayers(char *refparam, struct dmctx
strncpy(lower_layer, value, sizeof(lower_layer) - 1);
if (strncmp(lower_layer, "Device.Ethernet.Link.", 21) == 0) {
char new_name[16] = {0}, *linker = NULL, *device, *vid, *curr_name;
char new_name[16] = {0}, *linker = NULL, *type;
adm_entry_get_linker_value(ctx, lower_layer, &linker);
if (linker == NULL || *linker == '\0')
return -1;
struct uci_section *dmmap_s = NULL;
get_dmmap_section_of_config_section_eq("dmmap", "link", "mac", linker, &dmmap_s);
dmuci_get_value_by_section_string(dmmap_s, "device", &device);
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &curr_name);
// Get type option from device section
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "type", &type);
if (*device != '\0') {
char *p = strtok(device, ".");
if ((strcmp(type, "macvlan") == 0)) {
/* type == macvlan */
struct uci_section *s = NULL, *dmmap_s = NULL;
char link_inst[8] = {0}, sec_name[32] = {0};
snprintf(link_inst, sizeof(link_inst), "%c", lower_layer[strlen(lower_layer)-2]);
snprintf(new_name, sizeof(new_name), "%s_%s", linker, link_inst);
if (is_name_exist_in_devices(new_name))
return -1;
uci_foreach_option_eq("network", "interface", "ifname", linker, s) {
dmuci_set_value_by_section(s, "ifname", new_name);
strncpy(sec_name, section_name(s), sizeof(sec_name) - 1);
break;
}
get_dmmap_section_of_config_section_eq("dmmap", "link", "link_instance", link_inst, &dmmap_s);
dmuci_set_value_by_section(dmmap_s, "device", new_name);
dmuci_set_value_by_section(dmmap_s, "section_name", sec_name);
} else {
/* type != macvlan */
char *vid;
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "vid", &vid);
if (*vid != '\0')
snprintf(new_name, sizeof(new_name), "%s.%s", (p)?p:device, vid);
snprintf(new_name, sizeof(new_name), "%s.%s", linker, vid);
else
snprintf(new_name, sizeof(new_name), "%s", (p)?p:device);
snprintf(new_name, sizeof(new_name), "%s", linker);
dmuci_set_value_by_section(((struct dm_args *)data)->section, "ifname", (p)?p:device);
dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", new_name);
if (is_name_exist_in_devices(new_name))
return -1;
}
if (*curr_name != '\0') {
// Update interface section corresponding to this device if it exists
struct uci_section *s = NULL;
uci_foreach_option_eq("network", "interface", "ifname", curr_name, s) {
dmuci_set_value_by_section(s, "ifname", new_name);
}
}
// Set ifname and name options of device section
dmuci_set_value_by_section(((struct dm_args *)data)->section, "ifname", linker);
dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", new_name);
}
break;
}
@ -1338,7 +1126,7 @@ 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;
char *ifname, *name, *curr_ifname, *type;
struct uci_section *s = NULL;
switch (action) {
@ -1347,19 +1135,29 @@ static int set_EthernetVLANTermination_VLANID(char *refparam, struct dmctx *ctx,
return FAULT_9007;
return 0;
case VALUESET:
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
if (*ifname != '\0') {
dmasprintf(&name, "%s.%s", ifname, value);
// Get type option from device section
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "type", &type);
// set ifname option of the corresponding interface section
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &curr_ifname);
uci_foreach_option_eq("network", "interface", "ifname", curr_ifname, s) {
dmuci_set_value_by_section(s, "ifname", name);
if (strcmp(type, "macvlan") != 0) {
/* only when type != macvlan */
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
if (*ifname != '\0') {
dmasprintf(&name, "%s.%s", ifname, value);
if (is_name_exist_in_devices(name))
return -1;
// set ifname option of the corresponding interface section
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &curr_ifname);
uci_foreach_option_eq("network", "interface", "ifname", curr_ifname, s) {
dmuci_set_value_by_section(s, "ifname", name);
}
// set name option of the device section
dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", name);
dmfree(name);
}
// set name option of the device section
dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", name);
dmfree(name);
}
// set vid option of the device section
@ -1399,6 +1197,108 @@ static int set_EthernetVLANTermination_TPID(char *refparam, struct dmctx *ctx, v
return 0;
}
static int get_EthernetVLANTermination_MACVLAN(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "type", value);
*value = (strcmp(*value, "macvlan") == 0) ? "1" : "0";
return 0;
}
static int set_EthernetVLANTermination_MACVLAN(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
char *name, *ifname;
bool b;
switch (action) {
case VALUECHECK:
if (dm_validate_boolean(value))
return FAULT_9007;
break;
case VALUESET:
string_to_bool(value, &b);
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "ifname", &ifname);
dmuci_get_value_by_section_string(((struct dm_args *)data)->section, "name", &name);
struct uci_section *s = NULL, *dmmap_s = NULL;
char *link_instance, new_name[16] = {0};
if (b && *name != '\0') {
int name_found = 0;
uci_foreach_option_eq("network", "interface", "ifname", name, s) {
get_dmmap_section_of_config_section_eq("dmmap", "link", "device", ifname, &dmmap_s);
if (dmmap_s) {
dmuci_get_value_by_section_string(dmmap_s, "link_instance", &link_instance);
snprintf(new_name, sizeof(new_name), "%s_%s", ifname, link_instance);
if (is_name_exist_in_devices(new_name))
return -1;
dmuci_set_value_by_section(dmmap_s, "device", new_name);
dmuci_set_value_by_section(dmmap_s, "section_name", section_name(s));
}
dmuci_set_value_by_section(s, "ifname", new_name);
name_found = 1;
break;
}
if (name_found == 0) {
int ifname_found = 0;
struct uci_section *ss = NULL;
uci_foreach_option_eq("network", "interface", "ifname", ifname, ss) {
uci_path_foreach_option_eq(bbfdm, "dmmap", "link", "device", ifname, dmmap_s) {
char *sec_name;
dmuci_get_value_by_section_string(dmmap_s, "section_name", &sec_name);
/* Check section name exist => if yes, continue*/
if (!check_section_in_curr_section(sec_name, section_name(ss)))
continue;
dmuci_get_value_by_section_string(dmmap_s, "link_instance", &link_instance);
snprintf(new_name, sizeof(new_name), "%s_%s", ifname, link_instance);
if (is_name_exist_in_devices(new_name))
return -1;
dmuci_set_value_by_section(dmmap_s, "device", new_name);
dmuci_set_value_by_section(dmmap_s, "section_name", section_name(ss));
}
dmuci_set_value_by_section(ss, "ifname", new_name);
ifname_found = 1;
break;
}
if (ifname_found == 0) {
get_dmmap_section_of_config_section_eq("dmmap", "link", "device", ifname, &dmmap_s);
if (dmmap_s) {
dmuci_get_value_by_section_string(dmmap_s, "link_instance", &link_instance);
snprintf(new_name, sizeof(new_name), "%s_%s", ifname, link_instance);
if (is_name_exist_in_devices(new_name))
return -1;
dmuci_set_value_by_section(dmmap_s, "device", new_name);
dmuci_set_value_by_section(dmmap_s, "section_name", "");
}
}
}
dmuci_set_value_by_section(((struct dm_args *)data)->section, "name", new_name);
dmuci_set_value_by_section(((struct dm_args *)data)->section, "type", "macvlan");
} else {
dmuci_set_value_by_section(((struct dm_args *)data)->section, "type", b ? "macvlan" : "8021q");
}
break;
}
return 0;
}
/*#Device.Ethernet.VLANTermination.{i}.Stats.BytesSent!SYSFS:/sys/class/net/@Name/statistics/tx_bytes*/
static int get_EthernetVLANTerminationStats_BytesSent(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
@ -1573,6 +1473,7 @@ DMLEAF tEthernetVLANTerminationParams[] = {
{"LowerLayers", &DMWRITE, DMT_STRING, get_EthernetVLANTermination_LowerLayers, set_EthernetVLANTermination_LowerLayers, NULL, NULL, BBFDM_BOTH},
{"VLANID", &DMWRITE, DMT_UNINT, get_EthernetVLANTermination_VLANID, set_EthernetVLANTermination_VLANID, NULL, NULL, BBFDM_BOTH},
{"TPID", &DMWRITE, DMT_UNINT, get_EthernetVLANTermination_TPID, set_EthernetVLANTermination_TPID, NULL, NULL, BBFDM_BOTH},
{CUSTOM_PREFIX"MACVLAN", &DMWRITE, DMT_BOOL, get_EthernetVLANTermination_MACVLAN, set_EthernetVLANTermination_MACVLAN, NULL, NULL, BBFDM_BOTH},
{0}
};

View file

@ -233,9 +233,11 @@ static int get_IP_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, vo
{
struct uci_section *s = NULL;
int cnt = 0;
char *proto;
uci_foreach_sections("network", "interface", s) {
if (strcmp(section_name(s), "loopback") == 0)
dmuci_get_value_by_section_string(s, "proto", &proto);
if (strcmp(section_name(s), "loopback") == 0 || *proto == '\0')
continue;
cnt++;
}
@ -645,7 +647,7 @@ static int get_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *dat
static int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
char *proto, *device, *mac, linker[64] = {0};
char *proto, *device, linker[64] = {0};
dmuci_get_value_by_section_string(((struct ip_args *)data)->ip_sec, "proto", &proto);
if (strstr(proto, "ppp")) {
@ -662,9 +664,12 @@ static int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *
return 0;
}
mac = get_macaddr(section_name(((struct ip_args *)data)->ip_sec));
if (mac[0] != '\0') {
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), mac, value);
if (device[0] != '\0') {
char linker[32] = {0};
strncpy(linker, device, sizeof(linker) - 1);
char *vid = strchr(linker, '.');
if (vid) *vid = '\0';
adm_entry_get_linker_param(ctx, dm_print_path("%s%cEthernet%cLink%c", dmroot, dm_delim, dm_delim, dm_delim), linker, value);
if (*value != NULL)
return 0;
}
@ -685,7 +690,6 @@ static int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *
return FAULT_9007;
return 0;
case VALUESET:
if (value[strlen(value)-1] != '.')
snprintf(lower_layer, sizeof(lower_layer), "%s.", value);
else
@ -693,12 +697,48 @@ static int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *
if (strncmp(lower_layer, "Device.Ethernet.VLANTermination.", 32) == 0) {
adm_entry_get_linker_value(ctx, lower_layer, &linker);
if (linker) {
// Update ifname list
dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ifname", linker);
if (linker == NULL || *linker == '\0')
return -1;
struct uci_section *s = NULL, *stmp = NULL;
// Remove the device section corresponding to this interface if exists
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
uci_foreach_option_eq_safe("network", "device", "name", device, stmp, s) {
char *type;
dmuci_get_value_by_section_string(s, "type", &type);
if (strcmp(type, "untagged") == 0) dmuci_delete_by_section(s, NULL, NULL);
break;
}
} else
return FAULT_9005;
char *mac_vlan = strchr(linker, '_');
if (mac_vlan) {
// Check if there is an interface that has the same ifname ==> if yes, remove it
uci_foreach_option_eq_safe("network", "interface", "ifname", linker, stmp, s) {
dmuci_delete_by_section(s, NULL, NULL);
}
// Check if there is an dmmap link section that has the same device ==> if yes, update section name
get_dmmap_section_of_config_section_eq("dmmap", "link", "device", linker, &s);
dmuci_set_value_by_section_bbfdm(s, "section_name", section_name(((struct ip_args *)data)->ip_sec));
} else {
// Check if there is an interface that has the same name of device ==> if yes, remove it
char device[32] = {0};
strncpy(device, linker, sizeof(device) - 1);
char *vid = strchr(device, '.');
if (vid) {
*vid = '\0';
uci_foreach_option_eq_safe("network", "interface", "ifname", device, stmp, s) {
dmuci_delete_by_section(s, NULL, NULL);
}
}
}
// Update ifname list
dmuci_set_value_by_section(((struct ip_args *)data)->ip_sec, "ifname", linker);
}
return 0;
}
return 0;
@ -1515,8 +1555,17 @@ static int delete_ip_interface(char *refparam, struct dmctx *ctx, void *data, ch
dmuci_set_value_by_section(dmmap_section, "ip_int_instance", "");
dmuci_set_value_by_section(dmmap_section, "ipv4_instance", "");
} else {
/* type is not bridge ==> remove interface and dmmap section */
/* Remove the device section corresponding to this interface if exists */
char *device = get_device(section_name(((struct ip_args *)data)->ip_sec));
struct uci_section *s = NULL, *stmp = NULL;
uci_foreach_option_eq_safe("network", "device", "name", device, stmp, s) {
char *type;
dmuci_get_value_by_section_string(s, "type", &type);
if (strcmp(type, "untagged") == 0) dmuci_delete_by_section(s, NULL, NULL);
break;
}
/* type is not bridge ==> remove interface and dmmap section */
dmuci_delete_by_section(((struct ip_args *)data)->ip_sec, NULL, NULL);
dmuci_delete_by_section(dmmap_section, NULL, NULL);
}

View file

@ -1877,12 +1877,11 @@ int is_vlan_termination_section(char *name)
// check if ifname list contains the device name
if (strstr(ifname, name)) {
char *type, *proto;
dmuci_get_value_by_section_string(s, "type", &type);
dmuci_get_value_by_section_string(s, "proto", &proto);
char *type;
// check type is not bridge
// check type is not bridge and proto is not empty
if (strcmp(type, "bridge") == 0 || *proto == '\0')
dmuci_get_value_by_section_string(s, "type", &type);
if (strcmp(type, "bridge") == 0)
return 0;
break;
@ -1891,46 +1890,6 @@ int is_vlan_termination_section(char *name)
return 1;
}
int get_upstream_interface(char *intf_tag, int len)
{
/* Get the upstream interface. */
struct uci_section *port_s = NULL;
uci_foreach_option_eq("ports", "ethport", "uplink", "1", port_s) {
char *iface;
dmuci_get_value_by_section_string(port_s, "ifname", &iface);
if (*iface != '\0') {
strncpy(intf_tag, iface, len - 1);
break;
}
}
return 0;
}
int create_mac_addr_upstream_intf(char *mac_addr, char *mac, int mac_len)
{
int num = 0;
char macaddr[25] = {0};
if (*mac != '\0') {
strncpy(macaddr, mac, sizeof(macaddr) - 1);
int len = strlen(macaddr);
/* Fetch the last octect of base mac address in integer variable. */
if (sscanf(&macaddr[len - 2], "%02x", &num) > 0) {
num += 1;
snprintf(&macaddr[len - 2], sizeof(macaddr), "%02x", num);
}
if (macaddr[0] != '\0') {
strncpy(mac_addr, macaddr, mac_len);
return 0;
}
}
return -1;
}
void del_dmmap_sec_with_opt_eq(char *dmmap_file, char *section, char *option, char *value)
{
struct uci_section *d_sec = NULL;

View file

@ -324,11 +324,8 @@ int is_regular_file(const char *path);
char *stringToHex(char *text, int length);
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 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