aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFischer, Anna <anna.fischer@hp.com>2009-08-13 02:55:16 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 19:26:11 -0400
commit3982d3d28b02bed5312015762fe2112ccbaf9051 (patch)
tree783332d9c3983924dfc102b8a2f8147ad5bd078c
parent8dd07086a1f8048428d33a1917b6209978750cb1 (diff)
net/bridge: Add 'hairpin' port forwarding mode
This patch adds a 'hairpin' (also called 'reflective relay') mode port configuration to the Linux Ethernet bridge kernel module. A bridge supporting hairpin forwarding mode can send frames back out through the port the frame was received on. Hairpin mode is required to support basic VEPA (Virtual Ethernet Port Aggregator) capabilities. You can find additional information on VEPA here: http://tech.groups.yahoo.com/group/evb/ http://www.ieee802.org/1/files/public/docs2009/new-hudson-vepa_seminar-20090514d.pdf http://www.internet2.edu/presentations/jt2009jul/20090719-congdon.pdf An additional patch 'bridge-utils: Add 'hairpin' port forwarding mode' is provided to allow configuring hairpin mode from userspace tools. Signed-off-by: Paul Congdon <paul.congdon@hp.com> Signed-off-by: Anna Fischer <anna.fischer@hp.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/bridge/br_sysfs_if.c17
4 files changed, 23 insertions, 1 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c808d3b..bc1704ac6cd9 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -22,7 +22,8 @@
22static inline int should_deliver(const struct net_bridge_port *p, 22static inline int should_deliver(const struct net_bridge_port *p,
23 const struct sk_buff *skb) 23 const struct sk_buff *skb)
24{ 24{
25 return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING); 25 return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
26 p->state == BR_STATE_FORWARDING);
26} 27}
27 28
28static inline unsigned packet_length(const struct sk_buff *skb) 29static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index eb404dc3ed6e..e486f1fc3632 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -256,6 +256,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
256 p->path_cost = port_cost(dev); 256 p->path_cost = port_cost(dev);
257 p->priority = 0x8000 >> BR_PORT_BITS; 257 p->priority = 0x8000 >> BR_PORT_BITS;
258 p->port_no = index; 258 p->port_no = index;
259 p->flags = 0;
259 br_init_port(p); 260 br_init_port(p);
260 p->state = BR_STATE_DISABLED; 261 p->state = BR_STATE_DISABLED;
261 br_stp_port_timer_init(p); 262 br_stp_port_timer_init(p);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d5b5537272b4..8319247dad5d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -81,6 +81,9 @@ struct net_bridge_port
81 struct timer_list message_age_timer; 81 struct timer_list message_age_timer;
82 struct kobject kobj; 82 struct kobject kobj;
83 struct rcu_head rcu; 83 struct rcu_head rcu;
84
85 unsigned long flags;
86#define BR_HAIRPIN_MODE 0x00000001
84}; 87};
85 88
86struct net_bridge 89struct net_bridge
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 4a3cdf8f3813..820643a3ba9c 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,22 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
143} 143}
144static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); 144static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
145 145
146static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
147{
148 int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
149 return sprintf(buf, "%d\n", hairpin_mode);
150}
151static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
152{
153 if (v)
154 p->flags |= BR_HAIRPIN_MODE;
155 else
156 p->flags &= ~BR_HAIRPIN_MODE;
157 return 0;
158}
159static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
160 show_hairpin_mode, store_hairpin_mode);
161
146static struct brport_attribute *brport_attrs[] = { 162static struct brport_attribute *brport_attrs[] = {
147 &brport_attr_path_cost, 163 &brport_attr_path_cost,
148 &brport_attr_priority, 164 &brport_attr_priority,
@@ -159,6 +175,7 @@ static struct brport_attribute *brport_attrs[] = {
159 &brport_attr_forward_delay_timer, 175 &brport_attr_forward_delay_timer,
160 &brport_attr_hold_timer, 176 &brport_attr_hold_timer,
161 &brport_attr_flush, 177 &brport_attr_flush,
178 &brport_attr_hairpin_mode,
162 NULL 179 NULL
163}; 180};
164 181