/* Forwarding output path.
* Based on net/bridge/br_forward.c. */
-/* Don't forward packets to originating port or with flooding disabled */
+/* Don't forward packets to originating port. If we're flooding,
+ * then don't send out ports with flooding disabled.
+ */
static inline int should_deliver(const struct net_bridge_port *p,
- const struct sk_buff *skb)
+ const struct sk_buff *skb, int flood)
{
- if ((skb->dev == p->dev) || (p->flags & BRIDGE_PORT_NO_FLOOD)) {
+ if (skb->dev == p->dev)
+ return 0;
+
+ if (flood && (p->flags & BRIDGE_PORT_NO_FLOOD))
return 0;
- }
return 1;
}
return length;
}
+/* Send packets out all the ports except the originating one. If the
+ * "flood" argument is set, only send along the minimum spanning tree.
+ */
static int
-flood(struct datapath *dp, struct sk_buff *skb)
+output_all(struct datapath *dp, struct sk_buff *skb, int flood)
{
struct net_bridge_port *p;
int prev_port;
prev_port = -1;
list_for_each_entry_rcu (p, &dp->port_list, node) {
- if (!should_deliver(p, skb))
+ if (!should_deliver(p, skb, flood))
continue;
if (prev_port != -1) {
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
BUG_ON(!skb);
if (out_port == OFPP_FLOOD)
- return flood(dp, skb);
+ return output_all(dp, skb, 1);
+ else if (out_port == OFPP_ALL)
+ return output_all(dp, skb, 0);
else if (out_port == OFPP_CONTROLLER)
return dp_output_control(dp, skb, fwd_save_skb(skb), 0,
OFPR_ACTION);
free(dp);
}
+/* Send packets out all the ports except the originating one. If the
+ * "flood" argument is set, don't send out ports with flooding disabled.
+ */
static int
-flood(struct datapath *dp, struct buffer *buffer, int in_port)
+output_all(struct datapath *dp, struct buffer *buffer, int in_port, int flood)
{
struct sw_port *p;
int prev_port;
prev_port = -1;
LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
- if (port_no(dp, p) == in_port || p->flags & BRIDGE_PORT_NO_FLOOD) {
+ if (port_no(dp, p) == in_port) {
+ continue;
+ }
+ if (flood && p->flags & BRIDGE_PORT_NO_FLOOD) {
continue;
}
if (prev_port != -1) {
assert(buffer);
if (out_port == OFPP_FLOOD) {
- flood(dp, buffer, in_port);
+ output_all(dp, buffer, in_port, 1);
+ } else if (out_port == OFPP_ALL) {
+ output_all(dp, buffer, in_port, 0);
} else if (out_port == OFPP_CONTROLLER) {
dp_output_control(dp, buffer, in_port, 0, OFPR_ACTION);
} else if (out_port == OFPP_TABLE) {