.../linux/generic/files/drivers/net/phy/swconfig.c | 111
++++++++++++++++++++-
target/linux/generic/files/include/linux/switch.h | 2 +
2 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c
b/target/linux/generic/files/drivers/net/phy/swconfig.c
index e772c94..9904a11 100644
--- a/target/linux/generic/files/drivers/net/phy/swconfig.c
+++ b/target/linux/generic/files/drivers/net/phy/swconfig.c
@@ -23,6 +23,12 @@
#include <linux/capability.h>
#include <linux/skbuff.h>
#include <linux/switch.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <net/netlink.h>
+#include <linux/rtnetlink.h>
//#define DEBUG 1
#ifdef DEBUG
@@ -38,6 +44,23 @@
MODULE_AUTHOR("Felix Fietkau <n...@openwrt.org>");
MODULE_LICENSE("GPL");
+static struct hrtimer poll_timer;
+static ktime_t poll_timer_interval;
+static unsigned long base_interval;
+static bool first_poll = 1;
+
+static unsigned long interval = 40;
+module_param(interval, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interval,"Polling interval in ms for port state
scanning.");
+
+static bool poll_enable = 0;
+module_param(poll_enable, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(poll_enable,"Grant port state polling.");
+
+static int port_if_id[] = {8,4,5,6,7};
+module_param_array(port_if_id, int, NULL, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(port_if_id,"Preconfigured one port per vlan interface
indexes.");
+
static int swdev_id = 0;
static struct list_head swdevs;
static DEFINE_SPINLOCK(swdevs_lock);
@@ -955,7 +978,11 @@ register_switch(struct switch_dev *dev, struct
net_device *netdev)
}
BUG_ON(!dev->alias);
+ dev->port_state = NULL;
+
if (dev->ports > 0) {
+ dev->port_state = kzalloc(sizeof(int) * dev->ports, GFP_KERNEL);
+ dev->port_state[dev->ports-1] = 1; /* CPU port */
dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,
GFP_KERNEL);
if (!dev->portbuf)
@@ -1000,6 +1027,7 @@ unregister_switch(struct switch_dev *dev)
{
swconfig_destroy_led_trigger(dev);
kfree(dev->portbuf);
+ kfree(dev->port_state);
mutex_lock(&dev->sw_mutex);
swconfig_lock();
list_del(&dev->dev_list);
@@ -1008,12 +1036,93 @@ unregister_switch(struct switch_dev *dev)
}
EXPORT_SYMBOL_GPL(unregister_switch);
+static int get_link_state(struct switch_dev *dev, int port)
+{
+ struct switch_port_link link;
+ link.link=0;
+
+ if(dev->ops->get_port_link(dev, port, &link))
+ return -EINVAL;
+
+ if(link.link)
+ return 1;
+
+ return 0;
+}
+
+static void modify_if_carrier(int port, int ifidx, int state)
+{
+ struct net_device *dev;
+ list_for_each_entry(dev, &init_net.dev_base_head, dev_list) {
+ if(dev->ifindex == ifidx) {
+ if(state == 1)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
+ }
+ }
+}
+
+static enum hrtimer_restart poll_timer_callback(struct hrtimer *timer)
+{
+ struct switch_dev *dev;
+ int i,cur_port_state;
+
+ if(poll_enable) {
+ dev = list_entry((&swdevs)->next, typeof(*dev),
dev_list);
+ for(i=0; i < dev->ports-1; i++) {
+ cur_port_state = get_link_state(dev,i);
+ if(dev->port_state[i] == 0 && cur_port_state ==
1) {
+ modify_if_carrier(i,port_if_id[i],1);
+ dev->port_state[i] = 1;
+ }
+ else if(dev->port_state[i] == 1 &&
cur_port_state == 0) {
+ modify_if_carrier(i,port_if_id[i],0);
+ dev->port_state[i] = 0;
+ }
+ else if(first_poll) {
+ if(cur_port_state){
+
modify_if_carrier(i,port_if_id[i],1);
+ }
+ else{
+
modify_if_carrier(i,port_if_id[i],0);
+ }
+ }
+ }
+ first_poll = 0;
+ }
+ else {
+ if(base_interval == interval)
+ base_interval = interval+1;
+ first_poll = 1;
+ poll_timer_interval = ktime_set(0, 100*1000000);
+ hrtimer_forward(&poll_timer, ktime_get(), poll_timer_interval);
+ return HRTIMER_RESTART;
+ }
+
+ if(interval != base_interval) {
+ if(interval < 1)
+ interval = 1;
+ poll_timer_interval = ktime_set(0, interval*1000000);
+ base_interval = interval;
+ }
+
+ hrtimer_forward(&poll_timer, ktime_get(), poll_timer_interval);
+ return HRTIMER_RESTART;
+}
static int __init
swconfig_init(void)
{
int i, err;
+ base_interval = interval;
+ poll_timer_interval = ktime_set(0, interval*1000000);
+ hrtimer_init(&poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ poll_timer.function = &poll_timer_callback;
+
+ hrtimer_start(&poll_timer, poll_timer_interval, HRTIMER_MODE_REL);
+
INIT_LIST_HEAD(&swdevs);
err = genl_register_family(&switch_fam);
if (err)
@@ -1036,8 +1145,8 @@ static void __exit
swconfig_exit(void)
{
genl_unregister_family(&switch_fam);
+ hrtimer_cancel(&poll_timer);
}
module_init(swconfig_init);
module_exit(swconfig_exit);
-
diff --git a/target/linux/generic/files/include/linux/switch.h
b/target/linux/generic/files/include/linux/switch.h
index 4f4085e..26ac605 100644
--- a/target/linux/generic/files/include/linux/switch.h
+++ b/target/linux/generic/files/include/linux/switch.h
@@ -194,6 +194,8 @@ struct switch_dev {
struct mutex sw_mutex;
struct switch_port *portbuf;
+ int *port_state;
+
char buf[128];
#ifdef CONFIG_SWCONFIG_LEDS
On 03/01/14 11:49, Florian Fainelli wrote:
Le 2 janv. 2014 13:27, "Lévai Tamás" <levai.ta...@t-online.hu
<mailto:levai.ta...@t-online.hu>> a écrit :
>
>
> Running OpenFlow on OpenWrt is a well known use-case. Of‐
> softswitch is a user space implementation of OF software switch.
> If you want to use fast failover mechanisms with it, you have to
> provide port status information to ofsoftwitch. Polling via
> swconfig and swconfig API could be used in this case, but
> they are bloated, because they use context switch for each port
> status request. Lowering this overhead is important, because
> ofsoftswitch utilizes the whole CPU.
>
> To minimize the context switches I implemented the port status
> polling in kernel mode using the swconfig kernel module. With my
> patch the swconfig kernel module is able to modify the carrier
> state on predefined interfaces from &init_net according to a port
> status change in the switch.
>
> As a consequence, netlink messages notify user space programs
> about status changes of ports / interfaces. This was useful for
> us to test fast failover mechanisms of an OpenFlow switch. We
> believe this patch is generally useful beyond our routing soft‐
> ware use‐case.
>
> More information can be found on this web page:
> http://centaur.sch.bme.hu/~leait/projects/openwrt/
>
> If you are looking only for the patch:
>
http://centaur.sch.bme.hu/~leait/projects/openwrt/patches/swconfig_poll.patch
Can you post the patch as an email such that we can provide inline
responses?
Thanks!
>
> Tamas Levai
>
> Tested by:
> * Tamas Levai <levai.ta...@t-online.hu
<mailto:levai.ta...@t-online.hu>>
> * Felician Nemeth <neme...@tmit.bme.hu <mailto:neme...@tmit.bme.hu>>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org <mailto:openwrt-devel@lists.openwrt.org>
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel