From patchwork Fri Apr 21 07:21:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gao Zhenyu X-Patchwork-Id: 753164 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3w8Rv32cF3z9s73 for ; Fri, 21 Apr 2017 17:19:26 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="cwGYwNm+"; dkim-atps=neutral Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 32F39AB9; Fri, 21 Apr 2017 07:19:23 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D92E06C for ; Fri, 21 Apr 2017 07:19:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-io0-f195.google.com (mail-io0-f195.google.com [209.85.223.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 399E1141 for ; Fri, 21 Apr 2017 07:19:21 +0000 (UTC) Received: by mail-io0-f195.google.com with SMTP id h41so27157453ioi.1 for ; Fri, 21 Apr 2017 00:19:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=BXxuCU4QL8y+pfGwr9nTPRn9Ry0LIY9y5KHOv0FWm+Q=; b=cwGYwNm+oXcCiSQwZmIF1nwTweKoV4xt8g3MhFZJbeCxsI+soQsL5cSsLXln9rAcc8 wzd+ZT94ltJPQ1oB4UeP41CoLkpC74fVApiowZhHibB3vy623e8mnG5FPjy79uOw/KjJ iQ6KxXSI/xDNq9Sq7s/prHwbDdPgjN8cfYq9U+E5GBE9ix1j5bQPwK+bXkEKqVJU+lye Gi+M/l/0PMU+fDuyzxi5kBwnYNghn6+IfkkBkD55/MfRbNPxFeas31Kt0XyCcoAcqxlh ypRaky4SFbHLTfun9G/N8iyEm5ZdrgQDK/Cv/gwX2yNlyLooA+u6JgkQPVzSnOvA8UK9 fpPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=BXxuCU4QL8y+pfGwr9nTPRn9Ry0LIY9y5KHOv0FWm+Q=; b=EIYAXnLlHX1HQ37iI+lgdKm8occUo+esBEvKmcetyxmmg/pa6PYJqZNbx8v/ku3R8e vp40oHfPGKdI0joZ4d+3URSzbrPgrkdxkAUhIs8ftYBsWwFuZiBSNGS89H8YS5YIrPz4 PDCZtIG/+T17IaC8s4i/+b9ph9/AhHdlIwj+y9mLeeo6NlmGf8X3Oeo2InIa5NPCyudp 7qCoW8Hw4BO6yrJJH7coTF6F1JLtWSPjLH9FWb6j3B6L3lvjqqrPW5CeeF+6iFl8X3fK YZmYnDWij/hDVxKdUHEt2aumOyqRTYBjGzBCK/+Vwqng11OS/Ym/tqKuEYWxpU9mcPbM NxLA== X-Gm-Message-State: AN3rC/7iHqcOnFBk8PeHwraeACagO9f8xd48jxUiJDW5n1gdZ5ZNM1aE pWrtPxldJjM8x0hpov0= X-Received: by 10.98.137.5 with SMTP id v5mr11165713pfd.183.1492759160444; Fri, 21 Apr 2017 00:19:20 -0700 (PDT) Received: from dev.nicira.eng.vmware.com ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id b185sm14127432pfa.61.2017.04.21.00.19.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 21 Apr 2017 00:19:19 -0700 (PDT) From: Zhenyu Gao To: blp@ovn.com, blp@nicira.com, u9012063@gmail.com, pshelar@ovn.org, dev@openvswitch.org Date: Fri, 21 Apr 2017 00:21:32 -0700 Message-Id: <1492759292-31031-1-git-send-email-sysugaozhenyu@gmail.com> X-Mailer: git-send-email 1.9.1 X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v1] flow.c: Refactor the key_extract function in parsing frame. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org 1. Consume switch/case to judge type of frame instead of using if/else. 2. Add parse_ipv4hdr for ipv4 frame header parsing. Signed-off-by: Zhenyu Gao --- datapath/flow.c | 230 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 117 insertions(+), 113 deletions(-) diff --git a/datapath/flow.c b/datapath/flow.c index 2bc1ad0..0b35de6 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -250,6 +250,46 @@ static bool icmphdr_ok(struct sk_buff *skb) sizeof(struct icmphdr)); } +/** + * Parse ipv4 header from an Ethernet frame. + * Return ipv4 header length if successful, otherwise a negative errno value. + */ +static int parse_ipv4hdr(struct sk_buff *skb, struct sw_flow_key *key) +{ + int err; + struct iphdr *nh; + __be16 offset; + + err = check_iphdr(skb); + if (unlikely(err)) + return err; + + nh = ip_hdr(skb); + key->ipv4.addr.src = nh->saddr; + key->ipv4.addr.dst = nh->daddr; + + key->ip.proto = nh->protocol; + key->ip.tos = nh->tos; + key->ip.ttl = nh->ttl; + + offset = nh->frag_off & htons(IP_OFFSET); + if (offset) { + key->ip.frag = OVS_FRAG_TYPE_LATER; + } else { + if (nh->frag_off & htons(IP_MF) || + skb_shinfo(skb)->gso_type & SKB_GSO_UDP) { + key->ip.frag = OVS_FRAG_TYPE_FIRST; + } else { + key->ip.frag = OVS_FRAG_TYPE_NONE; + } + } + return ip_hdrlen(skb); +} + +/** + * Parse ipv6 header from an Ethernet frame. + * Return ipv6 header length if successful, otherwise a negative errno value. + */ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key) { unsigned int nh_ofs = skb_network_offset(skb); @@ -283,7 +323,10 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key) else key->ip.frag = OVS_FRAG_TYPE_FIRST; } else { - key->ip.frag = OVS_FRAG_TYPE_NONE; + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) + key->ip.frag = OVS_FRAG_TYPE_FIRST; + else + key->ip.frag = OVS_FRAG_TYPE_NONE; } /* Delayed handling of error in ipv6_skip_exthdr() as it @@ -561,42 +604,43 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) key->eth.type = skb->protocol; /* Network layer. */ - if (key->eth.type == htons(ETH_P_IP)) { - struct iphdr *nh; - __be16 offset; + switch(key->eth.type) { + case htons(ETH_P_IP): + case htons(ETH_P_IPV6): { + int nh_len; + if (key->eth.type == htons(ETH_P_IP)) { + nh_len = parse_ipv4hdr(skb, key); + } else { + nh_len = parse_ipv6hdr(skb, key); + } - error = check_iphdr(skb); - if (unlikely(error)) { - memset(&key->ip, 0, sizeof(key->ip)); - memset(&key->ipv4, 0, sizeof(key->ipv4)); - if (error == -EINVAL) { + if (unlikely(nh_len < 0)) { + switch (nh_len) { + case -EINVAL: + memset(&key->ip, 0, sizeof(key->ip)); + if (key->eth.type == htons(ETH_P_IP)) { + memset(&key->ipv4.addr, 0, sizeof(key->ipv4.addr)); + } else { + memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr)); + } + /* fall-through */ + case -EPROTO: skb->transport_header = skb->network_header; error = 0; + break; + default: + error = nh_len; } return error; } - nh = ip_hdr(skb); - key->ipv4.addr.src = nh->saddr; - key->ipv4.addr.dst = nh->daddr; - - key->ip.proto = nh->protocol; - key->ip.tos = nh->tos; - key->ip.ttl = nh->ttl; - - offset = nh->frag_off & htons(IP_OFFSET); - if (offset) { - key->ip.frag = OVS_FRAG_TYPE_LATER; + if (key->ip.frag == OVS_FRAG_TYPE_LATER) { return 0; } - if (nh->frag_off & htons(IP_MF) || - skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - key->ip.frag = OVS_FRAG_TYPE_FIRST; - else - key->ip.frag = OVS_FRAG_TYPE_NONE; /* Transport layer. */ - if (key->ip.proto == IPPROTO_TCP) { + switch(key->ip.proto) { + case IPPROTO_TCP: if (tcphdr_ok(skb)) { struct tcphdr *tcp = tcp_hdr(skb); key->tp.src = tcp->source; @@ -605,8 +649,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) } else { memset(&key->tp, 0, sizeof(key->tp)); } - - } else if (key->ip.proto == IPPROTO_UDP) { + break; + case IPPROTO_UDP: if (udphdr_ok(skb)) { struct udphdr *udp = udp_hdr(skb); key->tp.src = udp->source; @@ -614,7 +658,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) } else { memset(&key->tp, 0, sizeof(key->tp)); } - } else if (key->ip.proto == IPPROTO_SCTP) { + break; + case IPPROTO_SCTP: if (sctphdr_ok(skb)) { struct sctphdr *sctp = sctp_hdr(skb); key->tp.src = sctp->source; @@ -622,7 +667,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) } else { memset(&key->tp, 0, sizeof(key->tp)); } - } else if (key->ip.proto == IPPROTO_ICMP) { + break; + case IPPROTO_ICMP: if (icmphdr_ok(skb)) { struct icmphdr *icmp = icmp_hdr(skb); /* The ICMP type and code fields use the 16-bit @@ -634,10 +680,23 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) } else { memset(&key->tp, 0, sizeof(key->tp)); } + break; + case NEXTHDR_ICMP: + if (icmp6hdr_ok(skb)) { + error = parse_icmpv6(skb, key, nh_len); + if (error) + return error; + } else { + memset(&key->tp, 0, sizeof(key->tp)); + } + break; + default: + break; } - - } else if (key->eth.type == htons(ETH_P_ARP) || - key->eth.type == htons(ETH_P_RARP)) { + break; + } + case htons(ETH_P_ARP): + case htons(ETH_P_RARP): { struct arp_eth_header *arp; bool arp_available = arphdr_ok(skb); @@ -663,94 +722,39 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) memset(&key->ip, 0, sizeof(key->ip)); memset(&key->ipv4, 0, sizeof(key->ipv4)); } - } else if (eth_p_mpls(key->eth.type)) { - size_t stack_len = MPLS_HLEN; - - /* In the presence of an MPLS label stack the end of the L2 - * header and the beginning of the L3 header differ. - * - * Advance network_header to the beginning of the L3 - * header. mac_len corresponds to the end of the L2 header. - */ - while (1) { - __be32 lse; + break; + } + default: + if (eth_p_mpls(key->eth.type)) { + size_t stack_len = MPLS_HLEN; + + /* In the presence of an MPLS label stack the end of the L2 + * header and the beginning of the L3 header differ. + * + * Advance network_header to the beginning of the L3 + * header. mac_len corresponds to the end of the L2 header. + */ + while (1) { + __be32 lse; - error = check_header(skb, skb->mac_len + stack_len); - if (unlikely(error)) - return 0; + error = check_header(skb, skb->mac_len + stack_len); + if (unlikely(error)) + return 0; - memcpy(&lse, skb_network_header(skb), MPLS_HLEN); + memcpy(&lse, skb_network_header(skb), MPLS_HLEN); - if (stack_len == MPLS_HLEN) - memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN); + if (stack_len == MPLS_HLEN) + memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN); - skb_set_network_header(skb, skb->mac_len + stack_len); - if (lse & htonl(MPLS_LS_S_MASK)) - break; + skb_set_network_header(skb, skb->mac_len + stack_len); + if (lse & htonl(MPLS_LS_S_MASK)) + break; - stack_len += MPLS_HLEN; - } - } else if (key->eth.type == htons(ETH_P_IPV6)) { - int nh_len; /* IPv6 Header + Extensions */ - - nh_len = parse_ipv6hdr(skb, key); - if (unlikely(nh_len < 0)) { - 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; - break; - default: - error = nh_len; - } - return error; - } - - if (key->ip.frag == OVS_FRAG_TYPE_LATER) - return 0; - if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - key->ip.frag = OVS_FRAG_TYPE_FIRST; - - /* Transport layer. */ - if (key->ip.proto == NEXTHDR_TCP) { - if (tcphdr_ok(skb)) { - struct tcphdr *tcp = tcp_hdr(skb); - key->tp.src = tcp->source; - key->tp.dst = tcp->dest; - key->tp.flags = TCP_FLAGS_BE16(tcp); - } else { - memset(&key->tp, 0, sizeof(key->tp)); - } - } else if (key->ip.proto == NEXTHDR_UDP) { - if (udphdr_ok(skb)) { - struct udphdr *udp = udp_hdr(skb); - key->tp.src = udp->source; - key->tp.dst = udp->dest; - } else { - memset(&key->tp, 0, sizeof(key->tp)); - } - } else if (key->ip.proto == NEXTHDR_SCTP) { - if (sctphdr_ok(skb)) { - struct sctphdr *sctp = sctp_hdr(skb); - key->tp.src = sctp->source; - key->tp.dst = sctp->dest; - } else { - memset(&key->tp, 0, sizeof(key->tp)); - } - } else if (key->ip.proto == NEXTHDR_ICMP) { - if (icmp6hdr_ok(skb)) { - error = parse_icmpv6(skb, key, nh_len); - if (error) - return error; - } else { - memset(&key->tp, 0, sizeof(key->tp)); + stack_len += MPLS_HLEN; } } } + return 0; }