[ovs-dev] [PATCH 10/24] datapath: backport: retain parsed IPv6 header fields in flow on error skipping extension headers

Pravin B Shelar pshelar at ovn.org
Wed Jul 13 05:26:33 UTC 2016


Upstream commit:
    commit c30da497893718abc6cec4f1d34d35875200edee
    Author: Simon Horman <simon.horman at netronome.com>

    openvswitch: retain parsed IPv6 header fields in flow on error skipping extension headers

    When an error occurs skipping IPv6 extension headers retain the already
    parsed IP protocol and IPv6 addresses in the flow. Also assume that the
    packet is not a fragment in the absence of information to the contrary;
    that is always use the frag_off value set by ipv6_skip_exthdr().

    This allows matching on the IP protocol and IPv6 addresses of packets
    with malformed extension headers.

    Signed-off-by: Simon Horman <simon.horman at netronome.com>
    Signed-off-by: David S. Miller <davem at davemloft.net>

Signed-off-by: Pravin B Shelar <pshelar at ovn.org>
---
 datapath/flow.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/datapath/flow.c b/datapath/flow.c
index 8f9d585..4e6dfb2 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -272,8 +272,6 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 	key->ipv6.addr.dst = nh->daddr;
 
 	payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
-	if (unlikely(payload_ofs < 0))
-		return -EINVAL;
 
 	if (frag_off) {
 		if (frag_off & htons(~0x7))
@@ -284,6 +282,13 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 		key->ip.frag = OVS_FRAG_TYPE_NONE;
 	}
 
+	/* Delayed handling of error in ipv6_skip_exthdr() as it
+	 * always sets frag_off to a valid value which may be
+	 * used to set key->ip.frag above.
+	 */
+	if (unlikely(payload_ofs < 0))
+		return -EPROTO;
+
 	nh_len = payload_ofs - nh_ofs;
 	skb_set_transport_header(skb, nh_ofs + nh_len);
 	key->ip.proto = nexthdr;
@@ -624,12 +629,16 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 
 		nh_len = parse_ipv6hdr(skb, key);
 		if (unlikely(nh_len < 0)) {
-			memset(&key->ip, 0, sizeof(key->ip));
-			memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
-			if (nh_len == -EINVAL) {
+			switch (nh_len) {
+			case -EINVAL:
+				memset(&key->ip, 0, sizeof(key->ip));
+				memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
+				/* fall-through */
+			case -EPROTO:
 				skb->transport_header = skb->network_header;
 				error = 0;
-			} else {
+				break;
+			default:
 				error = nh_len;
 			}
 			return error;
-- 
1.9.1




More information about the dev mailing list