The ethernet type of an encapsulated frame may be obtained from
actions. If so it should be used to allow a richer conversion
of a flow to nlattrs.

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

---

v2.18
* No change

v2.17
* Rebase

v2.12 - v2.16
* No change

v2.11
* First post
---
 datapath/datapath.c |    4 ++--
 datapath/flow.c     |   49 +++++++++++++++++++++++++++----------------------
 datapath/flow.h     |    3 ++-
 3 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index a188d79..960f4b1 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -449,7 +449,7 @@ static int queue_userspace_packet(struct net *net, int 
dp_ifindex,
        upcall->dp_ifindex = dp_ifindex;
 
        nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
-       ovs_flow_to_nlattrs(upcall_info->key, user_skb);
+       ovs_flow_to_nlattrs(upcall_info->key, user_skb, htons(0));
        nla_nest_end(user_skb, nla);
 
        if (upcall_info->userdata)
@@ -1152,7 +1152,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
struct datapath *dp,
        nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY);
        if (!nla)
                goto nla_put_failure;
-       err = ovs_flow_to_nlattrs(&flow->key, skb);
+       err = ovs_flow_to_nlattrs(&flow->key, skb, htons(0));
        if (err)
                goto error;
        nla_nest_end(skb, nla);
diff --git a/datapath/flow.c b/datapath/flow.c
index b59e818..973c871 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -1477,10 +1477,12 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow 
*flow, int key_len, const stru
        return 0;
 }
 
-int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
+int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb,
+                       __be16 encap_eth_type)
 {
        struct ovs_key_ethernet *eth_key;
        struct nlattr *nla, *encap;
+       __be16 eth_type;
 
        if (swkey->phy.priority &&
            nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority))
@@ -1526,7 +1528,20 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, 
struct sk_buff *skb)
        if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, swkey->eth.type))
                goto nla_put_failure;
 
-       if (swkey->eth.type == htons(ETH_P_IP)) {
+       eth_type = swkey->eth.type;
+       if (eth_p_mpls(eth_type)) {
+               struct ovs_key_mpls *mpls_key;
+
+               nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS, sizeof(*mpls_key));
+               if (!nla)
+                       goto nla_put_failure;
+               mpls_key = nla_data(nla);
+               memset(mpls_key, 0, sizeof(struct ovs_key_mpls));
+               mpls_key->mpls_top_lse = swkey->mpls.top_lse;
+               eth_type = encap_eth_type;
+       }
+
+       if (eth_type == htons(ETH_P_IP)) {
                struct ovs_key_ipv4 *ipv4_key;
 
                nla = nla_reserve(skb, OVS_KEY_ATTR_IPV4, sizeof(*ipv4_key));
@@ -1539,7 +1554,7 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, 
struct sk_buff *skb)
                ipv4_key->ipv4_tos = swkey->ip.tos;
                ipv4_key->ipv4_ttl = swkey->ip.ttl;
                ipv4_key->ipv4_frag = swkey->ip.frag;
-       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+       } else if (eth_type == htons(ETH_P_IPV6)) {
                struct ovs_key_ipv6 *ipv6_key;
 
                nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
@@ -1555,8 +1570,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, 
struct sk_buff *skb)
                ipv6_key->ipv6_tclass = swkey->ip.tos;
                ipv6_key->ipv6_hlimit = swkey->ip.ttl;
                ipv6_key->ipv6_frag = swkey->ip.frag;
-       } else if (swkey->eth.type == htons(ETH_P_ARP) ||
-                  swkey->eth.type == htons(ETH_P_RARP)) {
+       } else if (eth_type == htons(ETH_P_ARP) ||
+                  eth_type == htons(ETH_P_RARP)) {
                struct ovs_key_arp *arp_key;
 
                nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
@@ -1569,19 +1584,9 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, 
struct sk_buff *skb)
                arp_key->arp_op = htons(swkey->ip.proto);
                memcpy(arp_key->arp_sha, swkey->ipv4.arp.sha, ETH_ALEN);
                memcpy(arp_key->arp_tha, swkey->ipv4.arp.tha, ETH_ALEN);
-       } else if (eth_p_mpls(swkey->eth.type)) {
-               struct ovs_key_mpls *mpls_key;
-
-               nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS, sizeof(*mpls_key));
-               if (!nla)
-                       goto nla_put_failure;
-               mpls_key = nla_data(nla);
-               memset(mpls_key, 0, sizeof(struct ovs_key_mpls));
-               mpls_key->mpls_top_lse = swkey->mpls.top_lse;
        }
 
-       if ((swkey->eth.type == htons(ETH_P_IP) ||
-            swkey->eth.type == htons(ETH_P_IPV6)) &&
+       if ((eth_type == htons(ETH_P_IP) || eth_type == htons(ETH_P_IPV6)) &&
             swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
 
                if (swkey->ip.proto == IPPROTO_TCP) {
@@ -1591,10 +1596,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key 
*swkey, struct sk_buff *skb)
                        if (!nla)
                                goto nla_put_failure;
                        tcp_key = nla_data(nla);
-                       if (swkey->eth.type == htons(ETH_P_IP)) {
+                       if (eth_type == htons(ETH_P_IP)) {
                                tcp_key->tcp_src = swkey->ipv4.tp.src;
                                tcp_key->tcp_dst = swkey->ipv4.tp.dst;
-                       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+                       } else if (eth_type == htons(ETH_P_IPV6)) {
                                tcp_key->tcp_src = swkey->ipv6.tp.src;
                                tcp_key->tcp_dst = swkey->ipv6.tp.dst;
                        }
@@ -1605,14 +1610,14 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key 
*swkey, struct sk_buff *skb)
                        if (!nla)
                                goto nla_put_failure;
                        udp_key = nla_data(nla);
-                       if (swkey->eth.type == htons(ETH_P_IP)) {
+                       if (eth_type == htons(ETH_P_IP)) {
                                udp_key->udp_src = swkey->ipv4.tp.src;
                                udp_key->udp_dst = swkey->ipv4.tp.dst;
-                       } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
+                       } else if (eth_type == htons(ETH_P_IPV6)) {
                                udp_key->udp_src = swkey->ipv6.tp.src;
                                udp_key->udp_dst = swkey->ipv6.tp.dst;
                        }
-               } else if (swkey->eth.type == htons(ETH_P_IP) &&
+               } else if (eth_type == htons(ETH_P_IP) &&
                           swkey->ip.proto == IPPROTO_ICMP) {
                        struct ovs_key_icmp *icmp_key;
 
@@ -1622,7 +1627,7 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, 
struct sk_buff *skb)
                        icmp_key = nla_data(nla);
                        icmp_key->icmp_type = ntohs(swkey->ipv4.tp.src);
                        icmp_key->icmp_code = ntohs(swkey->ipv4.tp.dst);
-               } else if (swkey->eth.type == htons(ETH_P_IPV6) &&
+               } else if (eth_type == htons(ETH_P_IPV6) &&
                           swkey->ip.proto == IPPROTO_ICMPV6) {
                        struct ovs_key_icmpv6 *icmpv6_key;
 
diff --git a/datapath/flow.h b/datapath/flow.h
index 7061f67..8c08c3a 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -237,7 +237,8 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  */
 #define FLOW_BUFSIZE 220
 
-int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
+int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *,
+                       __be16 encap_eth_type);
 int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
                      const struct nlattr *);
 int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, int key_len,
-- 
1.7.10.4

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

Reply via email to