From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ed Swierk Subject: Re: [PATCH v2] openvswitch: Trim off padding before L3+ netfilter processing Date: Mon, 8 Jan 2018 19:02:56 -0800 Message-ID: References: <1513095439-128864-1-git-send-email-eswierk@skyportsystems.com> <1513869437-20059-1-git-send-email-eswierk@skyportsystems.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Cc: ovs-dev , netdev , Benjamin Warren , Keith Holleman To: Pravin Shelar Return-path: Received: from mail-pg0-f66.google.com ([74.125.83.66]:33439 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751790AbeAIDC7 (ORCPT ); Mon, 8 Jan 2018 22:02:59 -0500 Received: by mail-pg0-f66.google.com with SMTP id i196so7036532pgd.0 for ; Mon, 08 Jan 2018 19:02:58 -0800 (PST) In-Reply-To: Content-Language: en-US Sender: netdev-owner@vger.kernel.org List-ID: On 1/6/18 10:57, Pravin Shelar wrote: > On Fri, Jan 5, 2018 at 10:59 PM, Ed Swierk wrote: >> >> >> On Jan 5, 2018 22:17, "Pravin Shelar" wrote: >> >> On Fri, Jan 5, 2018 at 3:20 PM, Ed Swierk >> wrote: >>> On Fri, Jan 5, 2018 at 10:14 AM, Ed Swierk >>> wrote: >>>> On Thu, Jan 4, 2018 at 7:36 PM, Pravin Shelar wrote: >>>>> OVS already pull all required headers in skb linear data, so no need >>>>> to redo all of it. only check required is the ip-checksum validation. >>>>> I think we could avoid it in most of cases by checking skb length to >>>>> ipheader length before verifying the ip header-checksum. >>>> >>>> Shouldn't the IP header checksum be verified even earlier, like in >>>> key_extract(), before actually using any of the fields in the IP >>>> header? >>> >>> Something like this for verifying the IP header checksum (not tested): >>> >> AFAIU openflow does not need this verification, so it is not required >> in flow extract. >> >> >> Okay. How about my proposed trimming implementation, caching the pad length >> in the ovs cb? >> > Caching the length is not that simple, OVS actions can change the > length. Keeping it consistent with packet would be more work, so lets > calculate it in ovs-ct function. > Something like this? diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a38c80e..282325d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -4084,6 +4084,8 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, unsigned int transport_len, __sum16(*skb_chkf)(struct sk_buff *skb)); +int skb_network_trim(struct sk_buff *skb); + /** * skb_head_is_locked - Determine if the skb->head is locked down * @skb: skb to check diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 08f5740..c68e927 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4740,6 +4740,41 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb, } EXPORT_SYMBOL(skb_checksum_trimmed); +/** + * skb_network_trim - trim skb to length specified by the network header + * @skb: the skb to trim + * + * Trims the skb to the length specified by the network header, + * removing any trailing padding. Leaves the skb alone if the protocol + * is not IP or IPv6. Frees the skb on error. + * + * Caller needs to pull the skb to the network header. + */ +int skb_network_trim(struct sk_buff *skb) +{ + unsigned int len; + int err; + + switch (skb->protocol) { + case htons(ETH_P_IP): + len = ntohs(ip_hdr(skb)->tot_len); + break; + case htons(ETH_P_IPV6): + len = sizeof(struct ipv6hdr) + + ntohs(ipv6_hdr(skb)->payload_len); + break; + default: + len = skb->len; + } + + err = pskb_trim_rcsum(skb, len); + if (unlikely(err)) + kfree_skb(skb); + + return err; +} +EXPORT_SYMBOL(skb_network_trim); + void __skb_warn_lro_forwarding(const struct sk_buff *skb) { net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n", diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index b27c5c6..73418d3 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1112,6 +1112,10 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb, nh_ofs = skb_network_offset(skb); skb_pull_rcsum(skb, nh_ofs); + err = skb_network_trim(skb); + if (err) + return err; + if (key->ip.frag != OVS_FRAG_TYPE_NONE) { err = handle_fragments(net, key, info->zone.id, skb); if (err)