Actions may provide information that allows further decoding of
a packet to provide a richer match. In such cases use the richer
match to look for a more specific flow. If this fails, make
an upcall to request a most specific facet.

For example:

In the case of MPLS, L3 and L4 information may not initially be decoded
from the frame as the ethernet type of the frame is an MPLS type and no
information is known about the type of the inner frame.

However, the type of the inner frame may be provided by an mpls_pop action
in which case L3 and L4 information may be decoded providing a finer
grained match than is otherwise possible.

Signed-off-by: Simon Horman <ho...@verge.net.au>

---

v2.12
* No change

v2.11
* First post
---
 datapath/actions.c  |   14 ++++++++++++++
 datapath/datapath.c |   23 +++++++++++++++++++++--
 datapath/datapath.h |    1 +
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 3278e37..f1066fa 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -629,6 +629,20 @@ static int do_execute_actions(struct datapath *dp, struct 
sk_buff *skb,
        return 0;
 }
 
+__be16 ovs_actions_allow_l3_extraction(struct sw_flow *flow)
+{
+       struct sw_flow_actions *acts = rcu_dereference(flow->sf_acts);
+       const struct nlattr *a;
+       int rem;
+
+       for (a = acts->actions, rem = acts->actions_len; rem > 0;
+            a = nla_next(a, &rem))
+               if (nla_type(a) == OVS_ACTION_ATTR_POP_MPLS)
+                       return *(__be16 *)nla_data(a);
+
+       return 0;
+}
+
 /* We limit the number of times that we pass into execute_actions()
  * to avoid blowing out the stack in the event that we have a loop. */
 #define MAX_LOOPS 5
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 747dbb6..4a15079 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -351,6 +351,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
        if (!OVS_CB(skb)->flow) {
                struct sw_flow_key key;
                int key_len;
+               struct flow_table *table = rcu_dereference(dp->table);
 
                /* Extract flow from 'skb' into 'key'. */
                error = ovs_flow_extract(skb, p->port_no, &key, &key_len);
@@ -360,8 +361,26 @@ void ovs_dp_process_received_packet(struct vport *p, 
struct sk_buff *skb)
                }
 
                /* Look up flow. */
-               flow = ovs_flow_tbl_lookup(rcu_dereference(dp->table),
-                                          &key, key_len);
+               flow = ovs_flow_tbl_lookup(table, &key, key_len);
+
+               /* We have a flow? Superb.
+                * See if the actions in the flow supply information to
+                * allow more information to be included in the flow's match
+                */
+               if (likely(flow)) {
+                       __be16 eth_type;
+                       eth_type = ovs_actions_allow_l3_extraction(flow);
+                       if (unlikely(eth_type)) {
+                               error = ovs_flow_extract_l3_onwards(skb, &key, 
&key_len,
+                                                                   eth_type);
+                               if (unlikely(error)) {
+                                       kfree_skb(skb);
+                                       return;
+                               }
+                               flow = ovs_flow_tbl_lookup(table, &key, 
key_len);
+                       }
+               }
+
                if (unlikely(!flow)) {
                        struct dp_upcall_info upcall;
 
diff --git a/datapath/datapath.h b/datapath/datapath.h
index e44d053..96e98a4 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -196,6 +196,7 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *, 
u32 portid, u32 seq,
                                         u8 cmd);
 
 int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
+__be16 ovs_actions_allow_l3_extraction(struct sw_flow *flow);
 
 void skb_cb_set_mpls_bos(struct sk_buff *skb);
 unsigned char *skb_cb_mpls_bos(const struct sk_buff *skb);
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to