Add support for OFPP_TABLE virtual port.
authorJustin Pettit <jpettit@nicira.com>
Sat, 12 Apr 2008 00:40:05 +0000 (17:40 -0700)
committerJustin Pettit <jpettit@nicira.com>
Sat, 12 Apr 2008 00:40:05 +0000 (17:40 -0700)
datapath/datapath.c
datapath/forward.c
datapath/forward.h
include/openflow.h

index b80c7b20da48b370f02bd78341d7945a9328bc46..0929b7047aea9dacc6e5ba0b05d9d36327c6b181 100644 (file)
@@ -6,6 +6,7 @@
 
 /* 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>
@@ -465,7 +466,19 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port)
        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];
index a154393c044db339da71b27f2ce707e09435dd68..65a98aebc4eb3b10a3022892084bbfcad283f027 100644 (file)
@@ -21,9 +21,6 @@
 
 /* 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);
@@ -59,7 +56,7 @@ static int do_output(struct datapath *dp, struct sk_buff *skb, size_t max_len,
                                         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)
 {
@@ -338,6 +335,7 @@ static int
 add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm)
 {
        int error = -ENOMEM;
+       int i;
        int n_acts;
        struct sw_flow *flow;
 
@@ -349,6 +347,19 @@ add_flow(struct sw_chain *chain, const struct ofp_flow_mod *ofm)
                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)
index 8e92330ff7242159db544093553bec3b9ba3abb4..f061d2da19569026be397c3db19a07273e1b9c28 100644 (file)
@@ -2,6 +2,7 @@
 #define FORWARD_H 1
 
 #include <linux/types.h>
+#include "datapath.h"
 #include "flow.h"
 
 struct sk_buff;
@@ -27,6 +28,9 @@ uint32_t fwd_save_skb(struct sk_buff *skb);
 
 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 *);
 
index 96a60c255902e226c13bedfa1031774a43b8b05c..9c4690668386d31fc30684225b46a29aec85cd43 100644 (file)
@@ -61,7 +61,11 @@ enum ofp_port {
     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. */