diff --git a/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh b/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh index ce6d74489..8b71db471 100755 --- a/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh +++ b/feeds/wlan-ap/opensync/files/bin/check_wan_link.sh @@ -1,6 +1,21 @@ #!/bin/sh +. /usr/share/libubox/jshn.sh -if="$(uci get network.wan.ifname)" +json_init +json_load "$(cat /etc/board.json)" +json_select network + json_select "wan" + json_get_vars ifname + json_select .. +json_select .. + +[ -n "$ifname" ] || { + ifname=$(uci get network.wan.ifname) + ifname=${ifname%% *} +} + + +if="$ifname" [ "$(cat /sys/class/net/"${if}"/carrier)" = 0 ] && { return 0 } diff --git a/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/30-bridge b/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/30-bridge index ab22432eb..43c018db2 100644 --- a/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/30-bridge +++ b/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/30-bridge @@ -1,7 +1,21 @@ #!/bin/sh +. /usr/share/libubox/jshn.sh [ "$ACTION" = "add" ] || exit 0 +json_init +json_load "$(cat /etc/board.json)" +json_select network + json_select "wan" + json_get_vars ifname + json_select .. +json_select .. + +[ -n "$ifname" ] || { + ifname=$(uci get network.wan.ifname) + ifname=${ifname%% *} +} + net=$(uci get wireless.${DEVICENAME}.network) vid=$(uci get wireless.${DEVICENAME}.vid) @@ -9,6 +23,6 @@ vid=$(uci get wireless.${DEVICENAME}.vid) bridge vlan add vid $vid dev br-lan self bridge vlan add vid $vid dev br-wan self -bridge vlan add vid $vid dev $(uci get network.wan.ifname) +bridge vlan add vid $vid dev $ifname bridge vlan add pvid $vid vid $vid dev ${DEVICENAME} untagged exit 0 diff --git a/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/60-dynamic-vlan b/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/60-dynamic-vlan index 368d13fe8..b883f861f 100644 --- a/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/60-dynamic-vlan +++ b/feeds/wlan-ap/opensync/files/etc/hotplug.d/net/60-dynamic-vlan @@ -1,5 +1,20 @@ +#!/bin/sh +. /usr/share/libubox/jshn.sh [ "$ACTION" = "add" ] || exit 0 +json_init +json_load "$(cat /etc/board.json)" +json_select network + json_select "wan" + json_get_vars ifname + json_select .. +json_select .. + +[ -n "$ifname" ] || { + ifname=$(uci get network.wan.ifname) + ifname=${ifname%% *} +} + dvid=`echo $DEVICENAME | awk -F "." '{ printf $2 }'` [ -z "$dvid" -o "$dvid" = 0 -o "$dvid" = 1 ] && exit 0 @@ -13,7 +28,7 @@ brctl delif br-wan.$dvid $DEVICENAME brctl addif br-wan $DEVICENAME bridge vlan add vid $dvid dev br-wan self -bridge vlan add vid $dvid dev $(uci get network.wan.ifname) +bridge vlan add vid $dvid dev $ifname bridge vlan add pvid $dvid vid $dvid dev $DEVICENAME untagged bridge vlan add vid $dvid dev br-lan self diff --git a/feeds/wlan-ap/opensync/patches/44-wifi_inet_eth_ports_schema.patch b/feeds/wlan-ap/opensync/patches/44-wifi_inet_eth_ports_schema.patch new file mode 100644 index 000000000..b273e822f --- /dev/null +++ b/feeds/wlan-ap/opensync/patches/44-wifi_inet_eth_ports_schema.patch @@ -0,0 +1,45 @@ +Index: opensync-2.0.5.0/interfaces/opensync.ovsschema +=================================================================== +--- opensync-2.0.5.0.orig/interfaces/opensync.ovsschema ++++ opensync-2.0.5.0/interfaces/opensync.ovsschema +@@ -900,6 +900,17 @@ + "min": 0, + "max": 64 + } ++ }, ++ "eth_ports": { ++ "type": { ++ "key": { ++ "type": "string", ++ "minLength": 1, ++ "maxLength": 32 ++ }, ++ "min": 0, ++ "max": 1 ++ } + } + }, + "isRoot": true, +@@ -1170,6 +1181,22 @@ + "min": 0, + "max": 64 + } ++ }, ++ "eth_ports": { ++ "type": { ++ "key": { ++ "type": "string", ++ "minLength": 1, ++ "maxLength": 32 ++ }, ++ "value": { ++ "type": "string", ++ "minLength": 1, ++ "maxLength": 64 ++ }, ++ "min": 0, ++ "max": 32 ++ } + } + }, + "isRoot": true, diff --git a/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_config.c b/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_config.c index 9fb346cf5..27cae114d 100644 --- a/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_config.c +++ b/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_config.c @@ -90,6 +90,24 @@ const char mesh_options_table[SCHEMA_MESH_OPTS_MAX][SCHEMA_MESH_OPT_SZ] = SCHEMA_CONSTS_MESH_HOP_PENALTY, }; + +char* get_eth_map_info(char* iface); +static void init_eth_ports_config(struct schema_Wifi_Inet_Config *config) +{ + char *wan = NULL; + char *lan = NULL; + + wan = get_eth_map_info("wan"); + if (!strncmp(config->if_name, "wan", 3)) { + SCHEMA_SET_STR(config->eth_ports, wan); + } + + lan = get_eth_map_info("lan"); + if (!strncmp(config->if_name, "lan", 3)) { + SCHEMA_SET_STR(config->eth_ports, lan); + } +} + static void wifi_inet_conf_load(struct uci_section *s) { struct blob_attr *tb[__NET_ATTR_MAX] = { }; @@ -190,6 +208,7 @@ static void wifi_inet_conf_load(struct uci_section *s) } } + init_eth_ports_config(&conf); firewall_get_config(&conf); if (!ovsdb_table_upsert(&table_Wifi_Inet_Config, &conf, false)) @@ -261,8 +280,9 @@ static int wifi_inet_conf_add(struct schema_Wifi_Inet_Config *iconf) snprintf(uci_ifname, sizeof(uci_ifname), "gre4t-%s.%d", iconf->parent_ifname, iconf->vlan_id); blobmsg_add_string(&b, "ifname", uci_ifname); blobmsg_add_string(&b, "type", "bridge"); - } - else { + } else if(!strncmp(iconf->parent_ifname, "eth", strlen("eth"))) { + blobmsg_add_string(&b, "ifname", iconf->parent_ifname); + } else { snprintf(uci_ifname, sizeof(uci_ifname), "br-%s.%d", iconf->parent_ifname, iconf->vlan_id); blobmsg_add_string(&b, "ifname", uci_ifname); } @@ -345,6 +365,101 @@ static int wifi_inet_conf_add(struct schema_Wifi_Inet_Config *iconf) return 0; } +static int wifi_inet_dup_conf_single(struct blob_buf *dup, char *if_name, int exclude) + +{ + struct blob_attr *tb[__NET_ATTR_MAX] = { }; + struct uci_package *network = NULL; + struct uci_section *s; + int i = 0; + + /* Load the network uci and lookup the if_name section */ + uci_load(uci, "network", &network); + s = uci_lookup_section(uci, network , if_name); + + if(!s) { + LOG(ERR, " %s: Failed to load uci", __func__); + uci_unload(uci, network); + return -1; + } + + /* Copy the uci section to blob and parse it */ + blob_buf_init(&b, 0); + uci_to_blob(&b, s, &network_param); + uci_unload(uci, network); + blobmsg_parse(network_policy, __NET_ATTR_MAX, + tb, blob_data(b.head), + blob_len(b.head)); + + blob_buf_init(dup, 0); + blob_buf_init(&del, 0); + + /* copy the parsed data to the passed blob buffer */ + for (i = 0; i < __NET_ATTR_MAX; i++) { + if (i == exclude) + continue; + if (tb[i]) { + switch (network_policy[i].type) { + case BLOBMSG_TYPE_STRING: + blobmsg_add_string(dup, network_policy[i].name, + blobmsg_get_string(tb[i])); + break; + case BLOBMSG_TYPE_INT32: + blobmsg_add_u32(dup, network_policy[i].name, + blobmsg_get_u32(tb[i])); + break; + case BLOBMSG_TYPE_BOOL: + blobmsg_add_bool(dup, network_policy[i].name, + blobmsg_get_bool(tb[i])); + break; + default: + break; + + } + } + } + return 0; +} + +static int wifi_inet_conf_modify(struct schema_Wifi_Inet_Config *iconf) +{ + struct blob_buf dup = { }; + + if (iconf->eth_ports_changed) { + LOGI("%s+%d: changed=%d if_name=%s, eth_ports=%s", + __func__, __LINE__, iconf->eth_ports_changed, + iconf->if_name, iconf->eth_ports); + + iconf->eth_ports_changed = 0; + + /* Copy the current uci interface section to the blob excluding + * the passed NET_ATTR (changed config attribute) */ + if (wifi_inet_dup_conf_single(&dup, iconf->if_name, + NET_ATTR_IFNAME) != 0) + return -1; + + /* Add the changed configuration to the blob */ + blobmsg_add_string(&dup, "ifname", iconf->eth_ports); + + /* Delete the current uci interface section */ + if (uci_section_del(uci, "network", "network", + iconf->if_name, "interface") != 0) + return -1; + + /* Add the resulting modified blob to uci */ + if (blob_to_uci_section(uci, "network", + iconf->if_name, + "interface", dup.head, + &network_param, + del.head) != 0) + return -1; + + uci_commit_all(uci); + blob_buf_free(&dup); + } + return 0; +} + static void wifi_inet_conf_del(struct schema_Wifi_Inet_Config *iconf) { if (!strcmp(iconf->if_name, "wan") || !strcmp(iconf->if_name, "lan")) { @@ -386,6 +501,13 @@ static void callback_Wifi_Inet_Config(ovsdb_update_monitor_t *mon, } wifi_inet_conf_add(iconf); + system("cp /etc/config/network /tmp/bkp-network"); + if (wifi_inet_conf_modify(iconf) != 0) { + LOG(ERR, "Failed to modify network Conf restoring old conf"); + system("cp /tmp/bkp-network /etc/config/network"); + } + system("rm /tmp/bkp-network"); + netifd_modify_inet_conf(iconf); break; case OVSDB_UPDATE_DEL: @@ -413,10 +535,12 @@ void wifi_inet_config_init(void) uci_foreach_element(&network->sections, e) { struct uci_section *s = uci_to_section(e); - if (!strcmp(s->type, "interface")) + if (!strcmp(s->type, "interface")) { wifi_inet_conf_load(s); + } } uci_unload(uci, network); + OVSDB_TABLE_MONITOR(Wifi_Inet_Config, false); return; diff --git a/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_state.c b/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_state.c index 049e38ec0..739a0af31 100644 --- a/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_state.c +++ b/feeds/wlan-ap/opensync/src/platform/openwrt/src/netifd/src/wifi_inet_state.c @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include enum { NET_ATTR_INTERFACE, @@ -100,6 +103,259 @@ int l3_device_split(char *l3_device, struct iface_info *info) return 0; } +bool wifi_inet_state_del(const char *ifname); +bool wifi_inet_master_del(const char *ifname); +#define DOT_OR_DOTDOT(s) ((s)[0] == '.' && (!(s)[1] || ((s)[1] == '.' && !(s)[2]))) +static struct blob_buf bb; +#define DEFAULT_BOARD_JSON "/etc/board.json" +#define MAX_ETH_PORTS 5 +static struct blob_attr *board_info; + +struct eth_port_state { + char ifname[8]; + char state[8]; + char speed[8]; + char duplex[16]; + char bridge[8]; +}; + +static struct eth_port_state wanport; +static struct eth_port_state lanport[MAX_ETH_PORTS]; + +static struct blob_attr* config_find_blobmsg_attr(struct blob_attr *attr, const char *name, int type) +{ + struct blobmsg_policy policy = { .name = name, .type = type }; + struct blob_attr *cur; + + blobmsg_parse(&policy, 1, &cur, blobmsg_data(attr), blobmsg_len(attr)); + + return cur; +} + + +char* get_eth_map_info(char* iface) +{ + struct blob_attr *cur; + + blob_buf_init(&bb, 0); + + if (!blobmsg_add_json_from_file(&bb, DEFAULT_BOARD_JSON)) { + return NULL; + } + if (board_info != NULL) { + free(board_info); + board_info = NULL; + } + cur = config_find_blobmsg_attr(bb.head, "network", BLOBMSG_TYPE_TABLE); + if (!cur) { + LOGD("Failed to find network in board.json file"); + return NULL; + } + board_info = blob_memdup(cur); + if (!board_info) + return NULL; + + cur = config_find_blobmsg_attr(board_info, iface, BLOBMSG_TYPE_TABLE); + if (!cur) { + LOGD("Failed to find %s in board.json file", iface); + return NULL; + } + cur = config_find_blobmsg_attr(cur, "ifname", BLOBMSG_TYPE_STRING); + if (!cur) { + LOGD("Failed to find ifname in board.json file"); + return NULL; + } + return blobmsg_get_string(cur); +} + + + +static void update_eth_state (char *eth, struct eth_port_state *eth_state) +{ + char sysfs_path[128]; + int fd = 0; + struct dirent *ent; + DIR *iface; + int carrier = 1; + ssize_t len = 0; + + memset(eth_state, 0, sizeof(struct eth_port_state)); + /* eth interface name */ + strncpy(eth_state->ifname, eth, sizeof(eth_state->ifname)); + + /* eth interface state */ + snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/class/net/%s/carrier", eth); + + fd = open(sysfs_path, O_RDONLY); + if (fd < 0) { + carrier = 0; + close(fd); + } else { + len = read(fd, eth_state->state, 15); + if (len < 0) { + carrier = 0; + } + close(fd); + } + + + if(!strncmp(eth_state->state, "0", 1)) + carrier = 0; + + strncpy(eth_state->state, carrier? "up":"down", sizeof(eth_state->state)); + + /* eth interface wan bridge */ + snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/class/net/br-wan/brif"); + + iface = opendir(sysfs_path); + if (iface) { + while ((ent = readdir(iface)) != NULL) { + if (DOT_OR_DOTDOT(ent->d_name)) + continue; + if (strncmp(ent->d_name, eth_state->ifname, sizeof(eth_state->ifname)) == 0) + strncpy(eth_state->bridge, "br-wan", sizeof(eth_state->ifname)); + } + closedir(iface); + } + + /* eth interface lan bridge */ + snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/class/net/br-lan/brif"); + + iface = opendir(sysfs_path); + if (iface) { + while ((ent = readdir(iface)) != NULL) { + if (DOT_OR_DOTDOT(ent->d_name)) + continue; + if (strncmp(ent->d_name, eth_state->ifname, sizeof(eth_state->ifname)) == 0) + strncpy(eth_state->bridge, "br-lan", sizeof(eth_state->bridge)); + } + closedir(iface); + } + + /* eth interface speed Mbits/sec */ + snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/class/net/%s/speed", eth); + + fd = open(sysfs_path, O_RDONLY); + if (fd < 0) { + close(fd); + } else { + + len = read(fd, eth_state->speed, sizeof(eth_state->speed) -1); + + if (len < 0) + snprintf(eth_state->speed, sizeof(eth_state->speed), "0"); + else + eth_state->speed[len-1] = '\0'; + close(fd); + } + + /* eth interface duplex */ + snprintf(sysfs_path, sizeof(sysfs_path), + "/sys/class/net/%s/duplex", eth); + + fd = open(sysfs_path, O_RDONLY); + if (fd < 0) { + close(fd); + } else { + len = read(fd, eth_state->duplex, sizeof(eth_state->duplex) -1); + + if (len < 0) + snprintf(eth_state->duplex, sizeof(eth_state->duplex), "none"); + else + eth_state->duplex[len-1] = '\0'; + + close(fd); + } +} + + +static void update_eth_ports_states(struct schema_Wifi_Inet_State *state) +{ + char *wan = NULL; + char *lan = NULL; + char *eth = NULL; + int cnt = 0; + int i = 0; + char port_status[128] = {'\0'}; + char brname[IFNAMSIZ] = {'\0'}; + + wan = get_eth_map_info("wan"); + update_eth_state(wan, &wanport); + + lan = get_eth_map_info("lan"); + eth = strtok (lan," "); + for (i = 0; i < MAX_ETH_PORTS && eth != NULL; i++) + { + update_eth_state(eth, &lanport[i]); + eth = strtok (NULL, " "); + } + + if (!strncmp(state->if_name, "wan", 3)) + strncpy(brname, "br-wan", 6); + else if (!strncmp(state->if_name, "lan", 3)) + strncpy(brname, "br-lan", 6); + + if (strcmp(wanport.bridge, brname) == 0) { + STRSCPY(state->eth_ports_keys[0], wanport.ifname); + snprintf(port_status, sizeof(port_status), "%s wan %sMbps %s", + wanport.state, wanport.speed, wanport.duplex); + STRSCPY(state->eth_ports[0], port_status); + cnt++; + state->eth_ports_len = cnt; + } + for (i = 0; i < MAX_ETH_PORTS && lanport[i].ifname != NULL; i++) { + if (strcmp(lanport[i].bridge, brname) == 0) { + STRSCPY(state->eth_ports_keys[cnt+i], lanport[i].ifname); + memset(port_status, '\0', sizeof(port_status)); + snprintf(port_status, sizeof(port_status), "%s lan %sMbps %s", + lanport[i].state, lanport[i].speed, lanport[i].duplex); + + STRSCPY(state->eth_ports[cnt+i], port_status); + cnt++; + state->eth_ports_len = cnt; + } + } + + if (!strncmp(state->if_name, "eth", 3)) { + + char *delim = NULL; + char name[IFNAMSIZ] = {'\0'}; + + delim = strstr(state->if_name, "_"); + if (delim) + strncpy(name, state->if_name, delim - state->if_name); + + if (name[0] == '\0') + return; + + + if (strcmp(wanport.ifname, name) == 0) { + STRSCPY(state->eth_ports_keys[0], wanport.ifname); + memset(port_status, '\0', sizeof(port_status)); + snprintf(port_status, sizeof(port_status), "%s wan %sMbps %s", + wanport.state, wanport.speed, wanport.duplex); + STRSCPY(state->eth_ports[0], port_status); + state->eth_ports_len = 1; + } else { + for (i = 0; i < MAX_ETH_PORTS && lanport[i].ifname != NULL; i++) { + if (strcmp(lanport[i].ifname, name) == 0) { + STRSCPY(state->eth_ports_keys[0], lanport[i].ifname); + memset(port_status, '\0', sizeof(port_status)); + snprintf(port_status, sizeof(port_status), "%s lan %sMbps %s", + lanport[i].state, lanport[i].speed, lanport[i].duplex); + + STRSCPY(state->eth_ports[0], port_status); + state->eth_ports_len = 1; + } + } + } + } +} + void wifi_inet_state_set(struct blob_attr *msg) { struct blob_attr *tb[__NET_ATTR_MAX] = { }; @@ -124,6 +380,13 @@ void wifi_inet_state_set(struct blob_attr *msg) state.enabled = true; state.network = true; } else { + + /* Delete VLAN interface state column if disabled */ + if (strstr(state.if_name, "_") != NULL) { + wifi_inet_state_del(state.if_name); + return; + } + state.enabled = false; state.network = false; } @@ -143,6 +406,23 @@ void wifi_inet_state_set(struct blob_attr *msg) else if (!strncmp(l3_device, "gre4", strlen("gre4")) || !strncmp(l3_device, "gre6", strlen("gre6"))) SCHEMA_SET_STR(state.if_type, "gre"); + /* Fill if_type, vlan_id and parent_ifname using + * if_name (eg:eth0_100) */ + else if (!strncmp(l3_device, "eth", strlen("eth"))) { + char *delim = NULL; + delim = strstr(state.if_name, "_"); + if (delim) { + struct iface_info info; + memset (&info, 0, sizeof(info)); + SCHEMA_SET_STR(state.if_type, "vlan"); + strncpy(info.name, &l3_device[0], + delim - state.if_name); + SCHEMA_SET_STR(state.parent_ifname, info.name); + info.vid = atoi(&delim[1]); + SCHEMA_SET_INT(state.vlan_id, info.vid); + } + + } else SCHEMA_SET_STR(state.if_type, "eth"); if (!l3_device_split(l3_device, &info) && strcmp(info.name, state.if_name)) { @@ -262,6 +542,8 @@ void wifi_inet_state_set(struct blob_attr *msg) } } + update_eth_ports_states(&state); + if (!ovsdb_table_upsert(&table_Wifi_Inet_State, &state, false)) LOG(ERR, "inet_state: failed to insert"); } @@ -289,6 +571,12 @@ void wifi_inet_master_set(struct blob_attr *msg) SCHEMA_SET_STR(state.port_state, "active"); SCHEMA_SET_STR(state.network_state, "up"); } else { + /* Delete VLAN interface state column if disabled */ + if (strstr(state.if_name, "_") != NULL) { + wifi_inet_master_del(state.if_name); + return; + } + SCHEMA_SET_STR(state.port_state, "inactive"); SCHEMA_SET_STR(state.network_state, "down"); } @@ -329,7 +617,14 @@ void wifi_inet_master_set(struct blob_attr *msg) if (!net_is_bridge(l3_device)) SCHEMA_SET_STR(state.if_type, "bridge"); - else + /* Fill if_type, vlan_id and parent_ifname using + * if_name (eg:eth0_100) */ + else if (!strncmp(l3_device, "eth", strlen("eth"))) { + char *delim = NULL; + delim = strstr(state.if_name, "_"); + if (delim) + SCHEMA_SET_STR(state.if_type, "vlan"); + } else SCHEMA_SET_STR(state.if_type, "eth"); } else SCHEMA_SET_STR(state.if_type, "eth"); @@ -349,6 +644,17 @@ void wifi_inet_master_set(struct blob_attr *msg) LOG(ERR, "master_state: failed to insert"); } + +bool wifi_inet_master_del(const char *ifname) +{ + int ret; + + ret = ovsdb_table_delete_simple(&table_Wifi_Master_State, SCHEMA_COLUMN(Wifi_Inet_State, if_name), ifname); + if (ret <= 0) + LOG(ERR, "inet_state: Error deleting Wifi_Master_State for interface %s.", ifname); + return ret; +} + bool wifi_inet_state_del(const char *ifname) { int ret; @@ -356,11 +662,6 @@ bool wifi_inet_state_del(const char *ifname) ret = ovsdb_table_delete_simple(&table_Wifi_Inet_State, SCHEMA_COLUMN(Wifi_Inet_State, if_name), ifname); if (ret <= 0) LOG(ERR, "inet_state: Error deleting Wifi_Inet_State for interface %s.", ifname); - - ret = ovsdb_table_delete_simple(&table_Wifi_Master_State, SCHEMA_COLUMN(Wifi_Inet_State, if_name), ifname); - if (ret <= 0) - LOG(ERR, "inet_state: Error deleting Wifi_Master_State for interface %s.", ifname); - return ret; } diff --git a/feeds/wlan-ap/wlan-ap-config/files/etc/hotplug.d/iface/30-eth-vlan b/feeds/wlan-ap/wlan-ap-config/files/etc/hotplug.d/iface/30-eth-vlan new file mode 100644 index 000000000..79908a69e --- /dev/null +++ b/feeds/wlan-ap/wlan-ap-config/files/etc/hotplug.d/iface/30-eth-vlan @@ -0,0 +1,40 @@ +#!/bin/sh +. /usr/share/libubox/jshn.sh +[ "$ACTION" = ifup -o "$ACTION" = ifupdate -o "$ACTION" = ifdown ] || exit 0 + +json_init +json_load "$(cat /etc/board.json)" +json_select network + json_select "wan" + json_get_vars ifname + json_select .. +json_select .. + +[ -n "$ifname" ] || { + ifname=$(uci get network.wan.ifname) + ifname=${ifname%% *} +} + +if [ "$ACTION" = ifup -o "$ACTION" = ifupdate ]; then + vid=$(uci get network.${INTERFACE}.vid) + net=$(uci get network.${INTERFACE}.ifname) + + [ -z "$net" -o -z "$vid" -o "$vid" = 0 ] && exit 0 + + bridge vlan add vid $vid dev br-lan self + bridge vlan add vid $vid dev br-wan self + bridge vlan add vid $vid dev $ifname + bridge vlan add pvid $vid vid $vid dev $net untagged + exit 0 +else + if [ "$ACTION" = ifdown ]; then + vid=`echo $INTERFACE | awk -F "_" '{ print $2 }'` + net=`echo $INTERFACE | awk -F "_" '{ print $1 }'` + [ -z "$net" -o -z "$vid" -o "$vid" = 0 ] && exit 0 + + bridge vlan del vid $vid dev $ifname + bridge vlan del pvid $vid vid $vid dev $net untagged + bridge vlan add pvid 1 vid 1 dev $net untagged + exit 0 + fi +fi diff --git a/patches/0063-ubus-notify-when-ethernet-ports-change-state.patch b/patches/0063-ubus-notify-when-ethernet-ports-change-state.patch new file mode 100644 index 000000000..1c3e25c3d --- /dev/null +++ b/patches/0063-ubus-notify-when-ethernet-ports-change-state.patch @@ -0,0 +1,85 @@ +From b14c0b96644cf86b36b0e60da800dd11733b26a9 Mon Sep 17 00:00:00 2001 +From: Chaitanya Godavarthi +Date: Tue, 14 Sep 2021 10:23:49 -0400 +Subject: [PATCH] ubus notify when ethernet ports change state + +Signed-off-by: Chaitanya Godavarthi +--- + .../0106-add-ubus-notify-eth-state.patch | 65 +++++++++++++++++++ + 1 file changed, 65 insertions(+) + create mode 100644 package/network/config/netifd/patches/0106-add-ubus-notify-eth-state.patch + +diff --git a/package/network/config/netifd/patches/0106-add-ubus-notify-eth-state.patch b/package/network/config/netifd/patches/0106-add-ubus-notify-eth-state.patch +new file mode 100644 +index 0000000000..3c8eaa530d +--- /dev/null ++++ b/package/network/config/netifd/patches/0106-add-ubus-notify-eth-state.patch +@@ -0,0 +1,65 @@ ++Index: netifd-2019-08-05-5e02f944/device.c ++=================================================================== ++--- netifd-2019-08-05-5e02f944.orig/device.c +++++ netifd-2019-08-05-5e02f944/device.c ++@@ -29,6 +29,7 @@ ++ #include "netifd.h" ++ #include "system.h" ++ #include "config.h" +++#include "ubus.h" ++ ++ static struct list_head devtypes = LIST_HEAD_INIT(devtypes); ++ static struct avl_tree devices; ++@@ -638,6 +639,7 @@ void device_set_present(struct device *d ++ ++ void device_set_link(struct device *dev, bool state) ++ { +++ ubus_link_state_notify(dev, state); ++ if (dev->link_active == state) ++ return; ++ ++Index: netifd-2019-08-05-5e02f944/ubus.c ++=================================================================== ++--- netifd-2019-08-05-5e02f944.orig/ubus.c +++++ netifd-2019-08-05-5e02f944/ubus.c ++@@ -817,6 +817,29 @@ netifd_dump_status(struct interface *ifa ++ netifd_add_interface_errors(&b, iface); ++ } ++ +++void ubus_link_state_notify(struct device *dev, bool state) +++{ +++ struct interface *iface = NULL; +++ /* proceed to notify if eth link state change and bridge change */ +++ if((strncmp(dev->ifname, "eth", 3) && (dev->link_active == state)) && +++ strncmp(dev->ifname, "br-wan", 6) && +++ strncmp(dev->ifname, "br-lan", 6)) +++ return; +++ netifd_log_message(L_NOTICE, "%s:%s\n", __func__, dev->ifname); +++ +++ vlist_for_each_element(&interfaces, iface, node) { +++ if( !strncmp(iface->name, "wan", 3) || +++ !strncmp(iface->name, "lan", 3) || +++ !strncmp(iface->name, "eth", 3)) { +++ blob_buf_init(&b, 0); +++ blobmsg_add_string(&b, "interface", iface->name); +++ netifd_dump_status(iface); +++ ubus_notify(ubus_ctx, &iface->ubus, "interface.update", +++ b.head, -1); +++ } +++ } +++} +++ ++ static int ++ netifd_handle_status(struct ubus_context *ctx, struct ubus_object *obj, ++ struct ubus_request_data *req, const char *method, ++Index: netifd-2019-08-05-5e02f944/ubus.h ++=================================================================== ++--- netifd-2019-08-05-5e02f944.orig/ubus.h +++++ netifd-2019-08-05-5e02f944/ubus.h ++@@ -22,5 +22,6 @@ void netifd_ubus_add_interface(struct in ++ void netifd_ubus_remove_interface(struct interface *iface); ++ void netifd_ubus_interface_event(struct interface *iface, bool up); ++ void netifd_ubus_interface_notify(struct interface *iface, bool up); +++void ubus_link_state_notify(struct device *dev, bool state); ++ ++ #endif +-- +2.25.1 +