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.14 * No change v2.13 * No change v2.12 * 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 f30513b..36b8b54 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) @@ -916,7 +916,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 1c78aae..7b5b51c 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -1383,10 +1383,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)) @@ -1436,7 +1438,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_label = swkey->mpls.top_label; + 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)); @@ -1449,7 +1464,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)); @@ -1465,8 +1480,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)); @@ -1479,19 +1494,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_label = swkey->mpls.top_label; } - 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) { @@ -1501,10 +1506,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; } @@ -1515,14 +1520,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; @@ -1532,7 +1537,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 14112d6..43accab 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -210,7 +210,8 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); */ #define FLOW_BUFSIZE 192 -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