Reduce redundancy in datapath code.
authorBen Pfaff <blp@nicira.com>
Tue, 5 Aug 2008 20:58:12 +0000 (13:58 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 7 Aug 2008 17:34:37 +0000 (10:34 -0700)
datapath/datapath.c
datapath/forward.c
datapath/forward.h
switch/datapath.c

index 28da3bb..b320f2e 100644 (file)
@@ -544,18 +544,12 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port)
                                                  OFPR_ACTION);
        else if (out_port == OFPP_TABLE) {
                struct net_bridge_port *p = skb->dev->br_port;
-               struct sw_flow_key key;
-               struct sw_flow *flow;
-
-               flow_extract(skb, p ? p->port_no : OFPP_LOCAL, &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;
-               }
-               kfree_skb(skb);
-               return -ESRCH;
+               int retval;
+               retval = run_flow_through_tables(dp->chain, skb,
+                                                p ? p->port_no : OFPP_LOCAL);
+               if (retval)
+                       kfree_skb(skb);
+               return retval;
        } else if (out_port == OFPP_LOCAL) {
                struct net_device *dev = dp->netdev;
                return dev ? dp_dev_recv(dev, skb) : -ESRCH;
index c8df1a0..8e2bc11 100644 (file)
@@ -27,8 +27,11 @@ static struct sk_buff *retrieve_skb(uint32_t id);
 static void discard_skb(uint32_t id);
 
 /* 'skb' was received on 'in_port', a physical switch port between 0 and
- * OFPP_MAX.  Process it according to 'chain'. */
-void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb, int in_port)
+ * OFPP_MAX.  Process it according to 'chain'.  Returns 0 if successful, in
+ * which case 'skb' is destroyed, or -ESRCH if there is no matching flow, in
+ * which case 'skb' still belongs to the caller. */
+int run_flow_through_tables(struct sw_chain *chain, struct sk_buff *skb,
+                           int in_port)
 {
        struct sw_flow_key key;
        struct sw_flow *flow;
@@ -39,11 +42,21 @@ void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb, int in_port)
                flow_used(flow, skb);
                execute_actions(chain->dp, skb, &key,
                                flow->actions, flow->n_actions);
+               return 0;
        } else {
+               return -ESRCH;
+       }
+}
+
+/* 'skb' was received on 'in_port', a physical switch port between 0 and
+ * OFPP_MAX.  Process it according to 'chain', sending it up to the controller
+ * if no flow matches.  Takes ownership of 'skb'. */
+void fwd_port_input(struct sw_chain *chain, struct sk_buff *skb, int in_port)
+{
+       if (run_flow_through_tables(chain, skb, in_port))
                dp_output_control(chain->dp, skb, fwd_save_skb(skb), 
                                  chain->dp->miss_send_len,
                                  OFPR_NO_MATCH);
-       }
 }
 
 static int do_output(struct datapath *dp, struct sk_buff *skb, size_t max_len,
index 05e5ac9..90288d0 100644 (file)
@@ -23,6 +23,7 @@ struct sender;
 
 
 void fwd_port_input(struct sw_chain *, struct sk_buff *, int in_port);
+int run_flow_through_tables(struct sw_chain *, struct sk_buff *, int in_port);
 int fwd_control_input(struct sw_chain *, const struct sender *,
                      const void *, size_t);
 
index 11b9f4e..15cca50 100644 (file)
@@ -156,6 +156,7 @@ static void modify_th(struct buffer *buffer, uint16_t eth_proto,
 
 #define PKT_COOKIE_BITS (32 - PKT_BUFFER_BITS)
 
+int run_flow_through_tables(struct datapath *, struct buffer *, int in_port);
 void fwd_port_input(struct datapath *, struct buffer *, int in_port);
 int fwd_control_input(struct datapath *, const struct sender *,
                       const void *, size_t);
@@ -548,18 +549,8 @@ dp_output_port(struct datapath *dp, struct buffer *buffer,
     } else if (out_port == OFPP_CONTROLLER) {
         dp_output_control(dp, buffer, in_port, 0, OFPR_ACTION); 
     } else if (out_port == OFPP_TABLE) {
-        struct sw_flow_key key;
-        struct sw_flow *flow;
-
-        key.wildcards = 0;
-        flow_extract(buffer, in_port, &key.flow);
-        flow = chain_lookup(dp->chain, &key);
-        if (flow != NULL) {
-            flow_used(flow, buffer);
-            execute_actions(dp, buffer, in_port, &key, 
-                            flow->actions, flow->n_actions);
-        } else {
-            buffer_delete(buffer);
+               if (run_flow_through_tables(dp, buffer, in_port)) {
+                       buffer_delete(buffer);
         }
     } else {
         output_packet(dp, buffer, out_port);
@@ -756,8 +747,11 @@ fill_flow_stats(struct buffer *buffer, struct sw_flow *flow,
 
 \f
 /* 'buffer' was received on 'in_port', a physical switch port between 0 and
- * OFPP_MAX.  Process it according to 'chain'. */
-void fwd_port_input(struct datapath *dp, struct buffer *buffer, int in_port)
+ * OFPP_MAX.  Process it according to 'dp''s flow table.  Returns 0 if
+ * successful, in which case 'buffer' is destroyed, or -ESRCH if there is no
+ * matching flow, in which case 'buffer' still belongs to the caller. */
+int run_flow_through_tables(struct datapath *dp, struct buffer *buffer,
+                            int in_port)
 {
     struct sw_flow_key key;
     struct sw_flow *flow;
@@ -769,7 +763,18 @@ void fwd_port_input(struct datapath *dp, struct buffer *buffer, int in_port)
         flow_used(flow, buffer);
         execute_actions(dp, buffer, in_port, &key,
                         flow->actions, flow->n_actions);
+        return 0;
     } else {
+        return -ESRCH;
+    }
+}
+
+/* 'buffer' was received on 'in_port', a physical switch port between 0 and
+ * OFPP_MAX.  Process it according to 'dp''s flow table, sending it up to the
+ * controller if no flow matches.  Takes ownership of 'buffer'. */
+void fwd_port_input(struct datapath *dp, struct buffer *buffer, int in_port) 
+{
+    if (run_flow_through_tables(dp, buffer, in_port)) {
         dp_output_control(dp, buffer, in_port, dp->miss_send_len,
                           OFPR_NO_MATCH);
     }