[OpenWrt-Devel] [PATCH] ralink: fixbug for mt7530, unused vlan entry will take effect to other vlan.
It will fail when you have an uci network config (swconfig part) like this: ``` config switch option name 'switch0' option reset '1' option enable_vlan '1' config switch_vlan option device 'switch0' option vlan '15' option vid '1' option ports '0 6t' config switch_port option name 'switch0' option port '0' option pvid '1' ``` It will be good until you run: $ swconfig dev switch0 vlan 1 set vid 333 So it seems that when REG_ESW_VLAN_VAWD1_VALID is unset, it will still take effect for VTU matching when two VTU entries have a same VID. Signed-off-by: Xiongfei Guo --- .../files/drivers/net/ethernet/ralink/mt7530.c | 26 ++ 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c index 1352b25..27fc51a 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c @@ -408,6 +408,22 @@ mt7530_apply_config(struct switch_dev *dev) u8 etags = priv->vlan_entries[i].etags; u32 val; + + /* vlan port membership */ + if (member) + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | + REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | + REG_ESW_VLAN_VAWD1_VALID); + else { + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + + /* ignore vid (just set it to 0) when the ports is empty, +* because even the REG_ESW_VLAN_VAWD1_VALID is set to disable, +* it will still take effect to other vlan when they have +* a same vid. */ + vid = 0; + } + /* vid of vlan */ val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); if (i % 2 == 0) { @@ -417,16 +433,8 @@ mt7530_apply_config(struct switch_dev *dev) val &= 0xfff; val |= (vid << 12); } - mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); - - /* vlan port membership */ - if (member) - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | - REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | - REG_ESW_VLAN_VAWD1_VALID); - else - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); /* egress mode */ val = 0; for (j = 0; j < MT7530_NUM_PORTS; j++) { -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH] BB: ralink/mt7530: fixbug: unused vlan entry will take effect to other vlan.
It will fail when you have an uci network config like this: ``` config switch option name 'switch0' option reset '1' option enable_vlan '1' config switch_vlan option device 'switch0' option vlan '15' option vid '1' option ports '0 6t' config switch_port option name 'switch0' option port '0' option pvid '1' ``` It will be good until you run: $ swconfig dev switch0 vlan 1 set vid 333 So it seems that when REG_ESW_VLAN_VAWD1_VALID is unset, it will still take effect for VTU matching when two VTU entries have a same VID. Signed-off-by: Xiongfei Guo --- .../files/drivers/net/ethernet/ralink/mt7530.c | 26 ++ 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c index 1352b25..27fc51a 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c @@ -408,6 +408,22 @@ mt7530_apply_config(struct switch_dev *dev) u8 etags = priv->vlan_entries[i].etags; u32 val; + + /* vlan port membership */ + if (member) + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | + REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | + REG_ESW_VLAN_VAWD1_VALID); + else { + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + + /* ignore vid (just set it to 0) when the ports is empty, +* because even the REG_ESW_VLAN_VAWD1_VALID is set to disable, +* it will still take effect to other vlan when they have +* a same vid. */ + vid = 0; + } + /* vid of vlan */ val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); if (i % 2 == 0) { @@ -417,16 +433,8 @@ mt7530_apply_config(struct switch_dev *dev) val &= 0xfff; val |= (vid << 12); } - mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); - - /* vlan port membership */ - if (member) - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | - REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | - REG_ESW_VLAN_VAWD1_VALID); - else - mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); /* egress mode */ val = 0; for (j = 0; j < MT7530_NUM_PORTS; j++) { -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH] [libubox] uloop: fixbug, 'end' is the keyword of Lua, use 'cancel' replace it.
Signed-off-by: Xiongfei Guo --- lua/uloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/uloop.c b/lua/uloop.c index 4abc4c3..2a0a516 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -369,7 +369,7 @@ static luaL_reg uloop_func[] = { {"timer", ul_timer}, {"process", ul_process}, {"fd_add", ul_ufd_add}, - {"end", ul_end}, + {"cancel", ul_end}, {NULL, NULL}, }; -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH] ramips: set default vid of each vlan, so it won't need be set explicitly.
Signed-off-by: Xiongfei Guo --- ...8-NET-MIPS-add-ralink-SoC-ethernet-driver.patch | 24 ++ 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch index c5d6623..6eb624f 100644 --- a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch +++ b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch @@ -2814,7 +2814,7 @@ Signed-off-by: John Crispin +#endif --- /dev/null +++ b/drivers/net/ethernet/ralink/mt7530.c -@@ -0,0 +1,571 @@ +@@ -0,0 +1,579 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License @@ -2912,15 +2912,15 @@ Signed-off-by: John Crispin + { + .name = "w", + .pvids = { 1, 1, 1, 1, 2, 1, 1 }, -+ .members = { 0x6f, 0x50 }, -+ .etags = { 0x40, 0x40 }, -+ .vids = { 1, 2 }, ++ .members = { 0, 0x6f, 0x50 }, ++ .etags = { 0, 0x40, 0x40 }, ++ .vids = { 0, 1, 2 }, + }, { + .name = "w", + .pvids = { 2, 1, 1, 1, 1, 1, 1 }, -+ .members = { 0x7e, 0x41 }, -+ .etags = { 0x40, 0x40 }, -+ .vids = { 1, 2 }, ++ .members = { 0, 0x7e, 0x41 }, ++ .etags = { 0, 0x40, 0x40 }, ++ .vids = { 0, 1, 2 }, + }, +}; + @@ -2961,10 +2961,18 @@ Signed-off-by: John Crispin +mt7530_reset_switch(struct switch_dev *dev) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); ++ int i; + + memset(priv->port_entries, 0, sizeof(priv->port_entries)); + memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); + ++ /* set default vid of each vlan to the same number of vlan, so the vid ++ * won't need be set explicitly. ++ */ ++ for (i = 0; i < MT7530_NUM_VLANS; i++) { ++ priv->vlan_entries[i].vid = i; ++ } ++ + return 0; +} + @@ -3158,7 +3166,7 @@ Signed-off-by: John Crispin + vid = (u16)val->value.i; + + if (vlan < 0 || vlan >= MT7530_NUM_VLANS) -+ return -EINVAL; ++ return -EINVAL; + + if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) + return -EINVAL; -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH] Update MT7530 switch driver.
From: Xiongfei Guo - Support set VLAN ID of each vlan. - Support untag feature. - Replace register address with C MACRO. - There are 8 ports for MT7530 actually. Signed-off-by: Xiongfei Guo --- ...8-NET-MIPS-add-ralink-SoC-ethernet-driver.patch | 268 ++--- 1 file changed, 186 insertions(+), 82 deletions(-) diff --git a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch index 75f78bf..c8ec17c 100644 --- a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch +++ b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch @@ -2814,7 +2814,7 @@ Signed-off-by: John Crispin +#endif --- /dev/null +++ b/drivers/net/ethernet/ralink/mt7530.c -@@ -0,0 +1,467 @@ +@@ -0,0 +1,571 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License @@ -2851,25 +2851,45 @@ Signed-off-by: John Crispin +#include "mt7530.h" + +#define MT7530_CPU_PORT 6 -+#define MT7530_NUM_PORTS 7 ++#define MT7530_NUM_PORTS 8 +#define MT7530_NUM_VLANS 16 -+#define MT7530_NUM_VIDS 16 ++#define MT7530_MAX_VID4095 ++#define MT7530_MIN_VID0 + -+#define REG_ESW_VLAN_VTCR 0x90 -+#define REG_ESW_VLAN_VAWD10x94 -+#define REG_ESW_VLAN_VAWD20x98 ++/* registers */ ++#define REG_ESW_VLAN_VTCR 0x90 ++#define REG_ESW_VLAN_VAWD10x94 ++#define REG_ESW_VLAN_VAWD20x98 ++#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2)) ++ ++#define REG_ESW_VLAN_VAWD1_IVL_MACBIT(30) ++#define REG_ESW_VLAN_VAWD1_VTAG_ENBIT(28) ++#define REG_ESW_VLAN_VAWD1_VALID BIT(0) ++ ++/* vlan egress mode */ ++enum { ++ ETAG_CTRL_UNTAG = 0, ++ ETAG_CTRL_TAG = 2, ++ ETAG_CTRL_SWAP = 1, ++ ETAG_CTRL_STACK = 3, ++}; + ++#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8)) ++#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8)) ++#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8)) +enum { + /* Global attributes. */ + MT7530_ATTR_ENABLE_VLAN, +}; + -+struct mt7530_port { ++struct mt7530_port_entry { + u16 pvid; +}; + -+struct mt7530_vlan { -+ u8 ports; ++struct mt7530_vlan_entry { ++ u16 vid; ++ u8 member; ++ u8 etags; +}; + +struct mt7530_priv { @@ -2878,23 +2898,29 @@ Signed-off-by: John Crispin + struct switch_dev swdev; + + boolglobal_vlan_enable; -+ struct mt7530_vlan vlans[MT7530_NUM_VLANS]; -+ struct mt7530_port ports[MT7530_NUM_PORTS]; ++ struct mt7530_vlan_entryvlan_entries[MT7530_NUM_VLANS]; ++ struct mt7530_port_entryport_entries[MT7530_NUM_PORTS]; +}; + +struct mt7530_mapping { + char*name; -+ u8 pvids[6]; -+ u8 vlans[8]; ++ u16 pvids[MT7530_NUM_PORTS]; ++ u8 members[MT7530_NUM_VLANS]; ++ u8 etags[MT7530_NUM_VLANS]; ++ u16 vids[MT7530_NUM_VLANS]; +} mt7530_defaults[] = { + { + .name = "w", -+ .pvids = { 1, 1, 1, 1, 2, 1 }, -+ .vlans = { 0, 0x6f, 0x50 }, ++ .pvids = { 1, 1, 1, 1, 2, 1, 1 }, ++ .members = { 0x6f, 0x50 }, ++ .etags = { 0x40, 0x40 }, ++ .vids = { 1, 2 }, + }, { + .name = "w", -+ .pvids = { 2, 1, 1, 1, 1, 1 }, -+ .vlans = { 0, 0x7e, 0x41 }, ++ .pvids = { 2, 1, 1, 1, 1, 1, 1 }, ++ .members = { 0x7e, 0x41 }, ++ .etags = { 0x40, 0x40 }, ++ .vids = { 1, 2 }, + }, +}; + @@ -2921,10 +2947,14 @@ Signed-off-by: John Crispin + + mt7530->global_vlan_enable = 1; + -+ for (i = 0; i < 6; i++) -+ mt7530->ports[i].pvid = map->pvids[i]; -+ for (i = 0; i < 8; i++) -+ mt7530->vlans[i].ports = map->vlans[i]; ++ for (i = 0; i < MT7530_NUM_PORTS; i++) ++ mt7530->port_entries[i].pvid = map->pvids[i]; ++ ++ for (i = 0; i < MT7530_NUM_VLANS; i++) { ++ mt7530->vlan_entries[i].member = map->members[i]; ++ mt7530->vlan_entries[i].etags = map->etags[i]; ++ mt7530->vlan_entries[i].vid = map->vids[i]; ++ } +} + +static int @@ -2932,8 +2962,8 @@ Signed-off-by: John Crispin +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + -+ memset(priv->ports, 0, sizeof(priv->ports)); -+ memset(priv->vlans, 0, sizeof(priv->vlans)); ++ memset(priv->port_entries, 0, sizeof(priv->port_entries)); ++ memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); + + return 0; +} @@ -2965,6 +2995,7 @@ Signed-off-by: John Crispin +static u32 +mt7530_r32(struct mt7530_priv *priv,
[OpenWrt-Devel] [PATCH 1/5] Fix stack overflow bug of uloop lua binding.
The static variable `state` in `lua/uloop.c` should be clean after every callback. Signed-off-by: Xiongfei(Alex) Guo --- lua/uloop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/uloop.c b/lua/uloop.c index 51f53c2..5922e04 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -43,6 +43,7 @@ static void ul_timer_cb(struct uloop_timeout *t) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); + lua_remove(state, -2); lua_call(state, 0, 0); } @@ -133,6 +134,7 @@ static void ul_process_cb(struct uloop_process *p, int ret) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, proc->r); luaL_unref(state, -2, proc->r); + lua_remove(state, -2); lua_pushinteger(state, ret >> 8); lua_call(state, 1, 0); } -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH 2/5] Added fd_add method for uloop lua binding.
Use uloop.fd_add like this: local socket = require "socket" udp = socket.udp() uloop.fd_add( udp, -- socket function( -- callback function ufd,-- socket object when register the fd events -- uloop events. eg. uloop.ULOOP_READ . ) local words, msg_or_ip, port_or_nil = ufd:receivefrom() print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) end, uloop.ULOOP_READ -- event you want to listen ) The `examples/uloop-example.lua` show an example of this work. Signed-off-by: Xiongfei(Alex) Guo --- examples/uloop-example.lua | 23 ++ lua/uloop.c| 111 + 2 files changed, 134 insertions(+) diff --git a/examples/uloop-example.lua b/examples/uloop-example.lua index 2da6ebd..ba34ec5 100755 --- a/examples/uloop-example.lua +++ b/examples/uloop-example.lua @@ -1,8 +1,14 @@ #!/usr/bin/env lua +local socket = require "socket" + local uloop = require("uloop") uloop.init() +local udp = socket.udp() +udp:settimeout(0) +udp:setsockname('*', 8080) + -- timer example 1 local timer function t() @@ -40,5 +46,22 @@ uloop.timer( end, 2000 ) +uloop.fd_add(udp, function(ufd, events) + local words, msg_or_ip, port_or_nil = ufd:receivefrom() + print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) +end, uloop.ULOOP_READ) + +udp_send_timer = uloop.timer( + function() + local s = socket.udp() + local words = 'Hello!' + print('Send UDP packet to 127.0.0.1:8080 :'..words) + s:sendto(words, '127.0.0.1', 8080) + s:close() + + udp_send_timer:set(1000) + end, 3000 +) + uloop.run() diff --git a/lua/uloop.c b/lua/uloop.c index 5922e04..c71d537 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -25,6 +25,12 @@ #include "../uloop.h" #include "../list.h" +struct lua_uloop_fd { + struct uloop_fd fd; + int r; + int fd_r; +}; + struct lua_uloop_timeout { struct uloop_timeout t; int r; @@ -44,7 +50,9 @@ static void ul_timer_cb(struct uloop_timeout *t) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); lua_remove(state, -2); + lua_call(state, 0, 0); + } static int ul_timer_set(lua_State *L) @@ -127,12 +135,95 @@ static int ul_timer(lua_State *L) return 1; } +static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) +{ + struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, ufd->r); + lua_remove(state, -2); + + /* push fd object */ + lua_getglobal(state, "__uloop_fds"); + lua_rawgeti(state, -1, ufd->fd_r); + lua_remove(state, -2); + + /* push events */ + lua_pushinteger(state, events); + + lua_call(state, 2, 0); +} + + +static int get_sock_fd(lua_State* L, int idx) { + int fd; + if(lua_isnumber(L, idx)) { + fd = lua_tonumber(L, idx); + } else { + luaL_checktype(L, idx, LUA_TUSERDATA); + lua_getfield(L, idx, "getfd"); + if(lua_isnil(L, -1)) + return luaL_error(L, "socket type missing 'getfd' method"); + lua_pushvalue(L, idx - 1); + lua_call(L, 1, 1); + fd = lua_tointeger(L, -1); + lua_pop(L, 1); + } + return fd; +} + +static int ul_ufd_add(lua_State *L) +{ + struct lua_uloop_fd *ufd; + int fd = 0; + unsigned int flags = 0; + int ref; + int fd_ref; + + if (lua_isnumber(L, -1)) { + flags = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + fd = get_sock_fd(L, -2); + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + lua_pop(L, 1); + + lua_getglobal(L, "__uloop_fds"); + lua_pushvalue(L, -3); + fd_ref = luaL_ref(L, -2); + lua_pop(L, 1); + + ufd = lua_newuserdata(L, sizeof(*ufd)); + memset(ufd, 0, sizeof(*ufd)); + + ufd->r = ref; + ufd->fd.fd = fd; + ufd->fd_r = fd_ref; + ufd->fd.cb = ul_ufd_cb; + if (flags) + uloop_fd_add(&ufd->fd, flags); + + return 1; +} + static void ul_process_cb(struct uloop_process *p, int ret) { struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p); lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, proc->r); + luaL_unref(state, -2, proc->r); lua_remove(state, -2); lua_pushinteger(state, ret >> 8); @@ -225,6 +316,7 @@ stati
[OpenWrt-Devel] [PATCH 3/5] Support delete a fd event.
When you call the fd_add, it will return an object with `delete` method. So you can delete that event if you want. Signed-off-by: Xiongfei(Alex) Guo --- examples/uloop-example.lua | 17 ++--- lua/uloop.c| 30 ++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/examples/uloop-example.lua b/examples/uloop-example.lua index ba34ec5..9b0684e 100755 --- a/examples/uloop-example.lua +++ b/examples/uloop-example.lua @@ -46,20 +46,31 @@ uloop.timer( end, 2000 ) -uloop.fd_add(udp, function(ufd, events) +udp_ev = uloop.fd_add(udp, function(ufd, events) local words, msg_or_ip, port_or_nil = ufd:receivefrom() print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) + if words == "Stop!" then + udp_ev:delete() + end end, uloop.ULOOP_READ) +udp_count = 0 udp_send_timer = uloop.timer( function() local s = socket.udp() - local words = 'Hello!' + local words + if udp_count > 3 then + words = "Stop!" + udp_send_timer:cancel() + else + words = 'Hello!' + udp_send_timer:set(1000) + end print('Send UDP packet to 127.0.0.1:8080 :'..words) s:sendto(words, '127.0.0.1', 8080) s:close() - udp_send_timer:set(1000) + udp_count = udp_count + 1 end, 3000 ) diff --git a/lua/uloop.c b/lua/uloop.c index c71d537..df57b8a 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -172,6 +172,24 @@ static int get_sock_fd(lua_State* L, int idx) { return fd; } +static int ul_ufd_delete(lua_State *L) +{ + struct lua_uloop_fd *ufd = lua_touserdata(L, 1); + + uloop_fd_delete(&ufd->fd); + lua_getglobal(state, "__uloop_cb"); + luaL_unref(L, -1, ufd->r); + lua_getglobal(state, "__uloop_fds"); + luaL_unref(L, -1, ufd->fd_r); + + return 1; +} + +static const luaL_Reg ufd_m[] = { + { "delete", ul_ufd_delete }, + { NULL, NULL } +}; + static int ul_ufd_add(lua_State *L) { struct lua_uloop_fd *ufd; @@ -205,6 +223,18 @@ static int ul_ufd_add(lua_State *L) lua_pop(L, 1); ufd = lua_newuserdata(L, sizeof(*ufd)); + + lua_createtable(L, 0, 2); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, ul_ufd_delete); + lua_setfield(L, -2, "__gc"); + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + lua_pushvalue(L, -2); + luaI_openlib(L, NULL, ufd_m, 1); + lua_pushvalue(L, -2); + memset(ufd, 0, sizeof(*ufd)); ufd->r = ref; -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH 4/5] Fix bug of unref resources in Lua binding; fd method delete -> cancel.
Signed-off-by: Xiongfei(Alex) Guo --- examples/uloop-example.lua | 2 +- lua/uloop.c| 12 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/uloop-example.lua b/examples/uloop-example.lua index 9b0684e..ab85a5d 100755 --- a/examples/uloop-example.lua +++ b/examples/uloop-example.lua @@ -50,7 +50,7 @@ udp_ev = uloop.fd_add(udp, function(ufd, events) local words, msg_or_ip, port_or_nil = ufd:receivefrom() print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) if words == "Stop!" then - udp_ev:delete() + udp_ev:cancel() end end, uloop.ULOOP_READ) diff --git a/lua/uloop.c b/lua/uloop.c index df57b8a..319942c 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -80,7 +80,7 @@ static int ul_timer_free(lua_State *L) uloop_timeout_cancel(&tout->t); lua_getglobal(state, "__uloop_cb"); - luaL_unref(L, -1, tout->r); + luaL_unref(state, -1, tout->r); return 1; } @@ -177,16 +177,20 @@ static int ul_ufd_delete(lua_State *L) struct lua_uloop_fd *ufd = lua_touserdata(L, 1); uloop_fd_delete(&ufd->fd); + lua_getglobal(state, "__uloop_cb"); - luaL_unref(L, -1, ufd->r); + luaL_unref(state, -1, ufd->r); + lua_remove(state, -1); + lua_getglobal(state, "__uloop_fds"); - luaL_unref(L, -1, ufd->fd_r); + luaL_unref(state, -1, ufd->fd_r); + lua_remove(state, -1); return 1; } static const luaL_Reg ufd_m[] = { - { "delete", ul_ufd_delete }, + { "cancel", ul_ufd_delete }, { NULL, NULL } }; -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH 5/5] Fix bug of GC in fd and timeout objects for lua binding.
fd and timeout lua object has a __gc method in its metatable. After the object is freed and the another new object use the same reference in __uloop_cb and __uloop_fds, the new object will be freed by the old __gc of the old object when garbag collecting. Signed-off-by: Xiongfei(Alex) Guo --- lua/uloop.c | 25 ++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/lua/uloop.c b/lua/uloop.c index 319942c..e806599 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -77,8 +77,15 @@ static int ul_timer_set(lua_State *L) static int ul_timer_free(lua_State *L) { struct lua_uloop_timeout *tout = lua_touserdata(L, 1); - + uloop_timeout_cancel(&tout->t); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + lua_getglobal(state, "__uloop_cb"); luaL_unref(state, -1, tout->r); @@ -150,7 +157,6 @@ static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) /* push events */ lua_pushinteger(state, events); - lua_call(state, 2, 0); } @@ -175,9 +181,15 @@ static int get_sock_fd(lua_State* L, int idx) { static int ul_ufd_delete(lua_State *L) { struct lua_uloop_fd *ufd = lua_touserdata(L, 1); - + uloop_fd_delete(&ufd->fd); + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + lua_getglobal(state, "__uloop_cb"); luaL_unref(state, -1, ufd->r); lua_remove(state, -1); @@ -345,12 +357,19 @@ static int ul_run(lua_State *L) return 1; } +static int ul_cancel(lua_State *L) +{ + uloop_end(); + return 1; +} + static luaL_reg uloop_func[] = { {"init", ul_init}, {"run", ul_run}, {"timer", ul_timer}, {"process", ul_process}, {"fd_add", ul_ufd_add}, + {"cancel", ul_cancel}, {NULL, NULL}, }; -- 1.9.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
[OpenWrt-Devel] [PATCH] uloop lua binding: Added fd_add method; Fix bug of GC and stack overflow.
From: "Xiongfei(Alex) Guo" Added fd_add method for uloop lua binding. Use uloop.fd_add like this: local socket = require "socket" udp = socket.udp() udp_read_ev = uloop.fd_add( udp, -- socket function( -- callback function ufd,-- socket object when register the fd events -- uloop events. eg. uloop.ULOOP_READ . ) local words, msg_or_ip, port_or_nil = ufd:receivefrom() print( 'Recv UDP packet from '.. msg_or_ip ..':'..port_or_nil.. ' : '..words ) end, uloop.ULOOP_READ -- event you want to listen ) udp_read_ev:cancel() -- cancel it The `examples/uloop-example.lua` show an example of this work. Fix stack overflow bug. The static variable `state` in `lua/uloop.c` should be clean after every callback. Fix bug of GC fd and timeout lua object has a __gc method in its metatable. After the object is freed and if another new object use the same reference number in __uloop_cb and __uloop_fds, the new object will be freed by the old __gc of the old object when garbag collecting. Signed-off-by: Xiongfei(Alex) Guo --- examples/uloop-example.lua | 34 + lua/uloop.c| 168 +++- 2 files changed, 201 insertions(+), 1 deletion(-) diff --git a/examples/uloop-example.lua b/examples/uloop-example.lua index 2da6ebd..ab85a5d 100755 --- a/examples/uloop-example.lua +++ b/examples/uloop-example.lua @@ -1,8 +1,14 @@ #!/usr/bin/env lua +local socket = require "socket" + local uloop = require("uloop") uloop.init() +local udp = socket.udp() +udp:settimeout(0) +udp:setsockname('*', 8080) + -- timer example 1 local timer function t() @@ -40,5 +46,33 @@ uloop.timer( end, 2000 ) +udp_ev = uloop.fd_add(udp, function(ufd, events) + local words, msg_or_ip, port_or_nil = ufd:receivefrom() + print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) + if words == "Stop!" then + udp_ev:cancel() + end +end, uloop.ULOOP_READ) + +udp_count = 0 +udp_send_timer = uloop.timer( + function() + local s = socket.udp() + local words + if udp_count > 3 then + words = "Stop!" + udp_send_timer:cancel() + else + words = 'Hello!' + udp_send_timer:set(1000) + end + print('Send UDP packet to 127.0.0.1:8080 :'..words) + s:sendto(words, '127.0.0.1', 8080) + s:close() + + udp_count = udp_count + 1 + end, 3000 +) + uloop.run() diff --git a/lua/uloop.c b/lua/uloop.c index 51f53c2..5bc0e6c 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -25,6 +25,12 @@ #include "../uloop.h" #include "../list.h" +struct lua_uloop_fd { + struct uloop_fd fd; + int r; + int fd_r; +}; + struct lua_uloop_timeout { struct uloop_timeout t; int r; @@ -43,7 +49,10 @@ static void ul_timer_cb(struct uloop_timeout *t) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); + lua_remove(state, -2); + lua_call(state, 0, 0); + } static int ul_timer_set(lua_State *L) @@ -70,8 +79,15 @@ static int ul_timer_free(lua_State *L) struct lua_uloop_timeout *tout = lua_touserdata(L, 1); uloop_timeout_cancel(&tout->t); + + /* obj.__index.__gc = nil , make sure executing only once*/ + lua_getfield(L, -1, "__index"); + lua_pushstring(L, "__gc"); + lua_pushnil(L); + lua_settable(L, -3); + lua_getglobal(state, "__uloop_cb"); - luaL_unref(L, -1, tout->r); + luaL_unref(state, -1, tout->r); return 1; } @@ -126,13 +142,136 @@ static int ul_timer(lua_State *L) return 1; } +static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) +{ + struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, ufd->r); + lua_remove(state, -2); + + /* push fd object */ + lua_getglobal(state, "__uloop_fds"); + lua_rawgeti(state, -1, ufd->fd_r); + lua_remove(state, -2); + + /* push events */ + lua_pushinteger(state, events); + lua_call(state, 2, 0); +} + + +static int get_sock_fd(lua_State* L, int idx) { + int fd; + if(lua_isnumber(L, idx)) { + fd = lua_tonumber(L, idx); + } else { + luaL_checktype(L, idx, LUA_TUSERDATA); + lua_getfield(L, idx, "getfd"); + if(lua_isnil(L, -1)) + return luaL_error(L, "socket type missing 'getfd' method"); + lua_pushvalue(L, idx - 1); + lua_call(L, 1, 1); + fd = lua_tointeger(L, -1); + lua_pop(L, 1); + } + return fd;
[OpenWrt-Devel] [PATCH 2/2] uloop: Added fd_add method for uloop lua binding.
Use uloop.fd_add like this: local socket = require "socket" udp = socket.udp() uloop.fd_add( udp, -- socket function( -- callback function ufd,-- socket object when register the fd events -- uloop events. eg. uloop.ULOOP_READ . ) local words, msg_or_ip, port_or_nil = ufd:receivefrom() print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) end, uloop.ULOOP_READ -- event you want to listen ) The `examples/uloop-example.lua` show an example of this work. Signed-off-by: Xiongfei(Alex) Guo --- examples/uloop-example.lua | 23 + lua/uloop.c| 111 2 files changed, 134 insertions(+), 0 deletions(-) diff --git a/examples/uloop-example.lua b/examples/uloop-example.lua index 2da6ebd..ba34ec5 100755 --- a/examples/uloop-example.lua +++ b/examples/uloop-example.lua @@ -1,8 +1,14 @@ #!/usr/bin/env lua +local socket = require "socket" + local uloop = require("uloop") uloop.init() +local udp = socket.udp() +udp:settimeout(0) +udp:setsockname('*', 8080) + -- timer example 1 local timer function t() @@ -40,5 +46,22 @@ uloop.timer( end, 2000 ) +uloop.fd_add(udp, function(ufd, events) + local words, msg_or_ip, port_or_nil = ufd:receivefrom() + print('Recv UDP packet from '..msg_or_ip..':'..port_or_nil..' : '..words) +end, uloop.ULOOP_READ) + +udp_send_timer = uloop.timer( + function() + local s = socket.udp() + local words = 'Hello!' + print('Send UDP packet to 127.0.0.1:8080 :'..words) + s:sendto(words, '127.0.0.1', 8080) + s:close() + + udp_send_timer:set(1000) + end, 3000 +) + uloop.run() diff --git a/lua/uloop.c b/lua/uloop.c index 5922e04..c71d537 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -25,6 +25,12 @@ #include "../uloop.h" #include "../list.h" +struct lua_uloop_fd { + struct uloop_fd fd; + int r; + int fd_r; +}; + struct lua_uloop_timeout { struct uloop_timeout t; int r; @@ -44,7 +50,9 @@ static void ul_timer_cb(struct uloop_timeout *t) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); lua_remove(state, -2); + lua_call(state, 0, 0); + } static int ul_timer_set(lua_State *L) @@ -127,12 +135,95 @@ static int ul_timer(lua_State *L) return 1; } +static void ul_ufd_cb(struct uloop_fd *fd, unsigned int events) +{ + struct lua_uloop_fd *ufd = container_of(fd, struct lua_uloop_fd, fd); + + lua_getglobal(state, "__uloop_cb"); + lua_rawgeti(state, -1, ufd->r); + lua_remove(state, -2); + + /* push fd object */ + lua_getglobal(state, "__uloop_fds"); + lua_rawgeti(state, -1, ufd->fd_r); + lua_remove(state, -2); + + /* push events */ + lua_pushinteger(state, events); + + lua_call(state, 2, 0); +} + + +static int get_sock_fd(lua_State* L, int idx) { + int fd; + if(lua_isnumber(L, idx)) { + fd = lua_tonumber(L, idx); + } else { + luaL_checktype(L, idx, LUA_TUSERDATA); + lua_getfield(L, idx, "getfd"); + if(lua_isnil(L, -1)) + return luaL_error(L, "socket type missing 'getfd' method"); + lua_pushvalue(L, idx - 1); + lua_call(L, 1, 1); + fd = lua_tointeger(L, -1); + lua_pop(L, 1); + } + return fd; +} + +static int ul_ufd_add(lua_State *L) +{ + struct lua_uloop_fd *ufd; + int fd = 0; + unsigned int flags = 0; + int ref; + int fd_ref; + + if (lua_isnumber(L, -1)) { + flags = lua_tointeger(L, -1); + lua_pop(L, 1); + } + + if (!lua_isfunction(L, -1)) { + lua_pushstring(L, "invalid arg list"); + lua_error(L); + + return 0; + } + + fd = get_sock_fd(L, -2); + + lua_getglobal(L, "__uloop_cb"); + lua_pushvalue(L, -2); + ref = luaL_ref(L, -2); + lua_pop(L, 1); + + lua_getglobal(L, "__uloop_fds"); + lua_pushvalue(L, -3); + fd_ref = luaL_ref(L, -2); + lua_pop(L, 1); + + ufd = lua_newuserdata(L, sizeof(*ufd)); + memset(ufd, 0, sizeof(*ufd)); + + ufd->r = ref; + ufd->fd.fd = fd; + ufd->fd_r = fd_ref; + ufd->fd.cb = ul_ufd_cb; + if (flags) + uloop_fd_add(&ufd->fd, flags); + + return 1; +} + static void ul_process_cb(struct uloop_process *p, int ret) { struct lua_uloop_process *proc = container_of(p, struct lua_uloop_process, p); lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, proc->r); + luaL_unref(state, -2, proc->r); lua_remove(state, -2); lua_pushinteger(state, ret >> 8); @@ -225,6 +316,7 @@
[OpenWrt-Devel] [PATCH 1/2] uloop: Fix stack overflow bug of uloop lua binding.
The static variable `state` in `lua/uloop.c` should be clean after every callback. Signed-off-by: Xiongfei(Alex) Guo --- lua/uloop.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/lua/uloop.c b/lua/uloop.c index 51f53c2..5922e04 100644 --- a/lua/uloop.c +++ b/lua/uloop.c @@ -43,6 +43,7 @@ static void ul_timer_cb(struct uloop_timeout *t) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, tout->r); + lua_remove(state, -2); lua_call(state, 0, 0); } @@ -133,6 +134,7 @@ static void ul_process_cb(struct uloop_process *p, int ret) lua_getglobal(state, "__uloop_cb"); lua_rawgeti(state, -1, proc->r); luaL_unref(state, -2, proc->r); + lua_remove(state, -2); lua_pushinteger(state, ret >> 8); lua_call(state, 1, 0); } -- 1.7.1 ___ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel