From 2a6dc4f3191b2d18b59a1f0085c0f9ae23fb4a41 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 5 Aug 2008 13:58:12 -0700 Subject: [PATCH] Reduce redundancy in datapath code. --- datapath/datapath.c | 18 ++++++------------ datapath/forward.c | 19 ++++++++++++++++--- datapath/forward.h | 1 + switch/datapath.c | 33 +++++++++++++++++++-------------- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 28da3bb7..b320f2e5 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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; diff --git a/datapath/forward.c b/datapath/forward.c index c8df1a0a..8e2bc112 100644 --- a/datapath/forward.c +++ b/datapath/forward.c @@ -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, diff --git a/datapath/forward.h b/datapath/forward.h index 05e5ac98..90288d02 100644 --- a/datapath/forward.h +++ b/datapath/forward.h @@ -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); diff --git a/switch/datapath.c b/switch/datapath.c index 11b9f4e2..15cca50a 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -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, /* '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); } -- 2.30.2