/* Functions for managing the dp interface/device. */
+#include <linux/init.h>
#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/if_bridge.h>
else if (out_port == OFPP_CONTROLLER)
return dp_output_control(dp, skb, fwd_save_skb(skb), 0,
OFPR_ACTION);
- else if (out_port >= OFPP_MAX)
+ else if (out_port == OFPP_TABLE) {
+ struct sw_flow_key key;
+ struct sw_flow *flow;
+
+ flow_extract(skb, skb->dev->br_port->port_no, &key);
+ flow = chain_lookup(dp->chain, &key);
+ if (likely(flow != NULL)) {
+ flow_used(flow, skb);
+ execute_actions(dp, skb, &key, flow->actions, flow->n_actions);
+ return 0;
+ }
+ return -ESRCH;
+ } else if (out_port >= OFPP_MAX)
goto bad_port;
p = dp->ports[out_port];
/* FIXME: do we need to use GFP_ATOMIC everywhere here? */
-static void execute_actions(struct datapath *, struct sk_buff *,
- const struct sw_flow_key *,
- const struct ofp_action *, int n_actions);
static int make_writable(struct sk_buff **);
static struct sk_buff *retrieve_skb(uint32_t id);
max_len, OFPR_ACTION));
}
-static void execute_actions(struct datapath *dp, struct sk_buff *skb,
+void execute_actions(struct datapath *dp, struct sk_buff *skb,
const struct sw_flow_key *key,
const struct ofp_action *actions, int n_actions)
{
add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm)
{
int error = -ENOMEM;
+ int i;
int n_acts;
struct sw_flow *flow;
goto error;
}
+ /* To prevent loops, make sure there's no action to send to the
+ * OFP_TABLE virtual port.
+ */
+ for (i=0; i<n_acts; i++) {
+ const struct ofp_action *a = &ofm->actions[i];
+
+ if (a->type == htons(OFPAT_OUTPUT)
+ && a->arg.output.port == htons(OFPP_TABLE)) {
+ /* xxx Send fancy new error message? */
+ goto error;
+ }
+ }
+
/* Allocate memory. */
flow = flow_alloc(n_acts, GFP_ATOMIC);
if (flow == NULL)
#define FORWARD_H 1
#include <linux/types.h>
+#include "datapath.h"
#include "flow.h"
struct sk_buff;
void fwd_exit(void);
+void execute_actions(struct datapath *, struct sk_buff *,
+ const struct sw_flow_key *,
+ const struct ofp_action *, int n_actions);
struct sk_buff *execute_setter(struct sk_buff *, uint16_t,
const struct sw_flow_key *, const struct ofp_action *);
OFPP_MAX = 0x100,
/* Fake output "ports". */
- OFPP_NORMAL = 0xfffa, /* Process with normal L2/L3 switching */
+ OFPP_TABLE = 0xfff9, /* Perform actions in flow table.
+ * NB: This can only be the destination
+ * port for packet-out messages.
+ */
+ OFPP_NORMAL = 0xfffa, /* Process with normal L2/L3 switching. */
OFPP_FLOOD = 0xfffb, /* All physical ports except input port and
those disabled by STP. */
OFPP_ALL = 0xfffc, /* All physical ports except input port. */