From patchwork Fri Apr 24 15:51:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 464249 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 00A3A14011B for ; Sat, 25 Apr 2015 01:55:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756202AbbDXPwt (ORCPT ); Fri, 24 Apr 2015 11:52:49 -0400 Received: from mail-wg0-f51.google.com ([74.125.82.51]:35521 "EHLO mail-wg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031301AbbDXPwA (ORCPT ); Fri, 24 Apr 2015 11:52:00 -0400 Received: by wgyo15 with SMTP id o15so55181347wgy.2 for ; Fri, 24 Apr 2015 08:51:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=f98PKDrRWvWjbUlnL+i6pFBkkqC7yhqteiqujFpUlEE=; b=X8d2MFjT74J8Bzv09pM4PQ9/XOuRZuNcpzZHAMZf28TZJ9EMpJYB8r5dAH0PHRdr8O lgoYXTJkGCIbQM/n0sKL3ROXREIcTOjVDo32dbEVcNT86GtmdUc+PLnYknX+1cehbYCd mxqJLW9EFvRZAxmAqui66M3qdmGE5nuCcV290MukECyd76vSn0NlZm8iuOzOw8QdiZP3 wO9zuIhWJLrcN3GrdqL3+049M0V/ux4ahQclfmzKwn0u3Z9YiRn78UiU/eUz8y2gHXg3 GbUKnlfZS1Vh+241fyxddoUOtUQsySwoO3u4YHj7tGJhiWG+r+XUiTbZA+lyWiTMKf32 rRXw== X-Gm-Message-State: ALoCoQl5EHBbbsJifKwoc+I9rhxqLpLYteE3Rx8SrcSeynwmFVQcGAG37L3I3E8KzpV4xhlBXw08 X-Received: by 10.180.84.67 with SMTP id w3mr2665473wiy.68.1429890719163; Fri, 24 Apr 2015 08:51:59 -0700 (PDT) Received: from localhost (jirka.pirko.cz. [84.16.102.26]) by mx.google.com with ESMTPSA id df1sm4127372wib.12.2015.04.24.08.51.58 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 24 Apr 2015 08:51:58 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, jhs@mojatatu.com, tgraf@suug.ch, jesse@nicira.com, kaber@trash.net, therbert@google.com, edumazet@google.com, alexander.h.duyck@redhat.com, hannes@stressinduktion.org, ast@plumgrid.com, daniel@iogearbox.net, herbert@gondor.apana.org.au, cwang@twopensource.com, john.fastabend@gmail.com Subject: [patch net-next v4 RFC 09/15] flow_dissector: introduce programable flow_dissector Date: Fri, 24 Apr 2015 17:51:35 +0200 Message-Id: <1429890701-30052-10-git-send-email-jiri@resnulli.us> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1429890701-30052-1-git-send-email-jiri@resnulli.us> References: <1429890701-30052-1-git-send-email-jiri@resnulli.us> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Introduce dissector infrastructure which allows user to specify which parts of skb he wants to dissect. Signed-off-by: Jiri Pirko --- include/net/flow_dissector.h | 61 ++++++++++++++++++++++++++++++++++++++++++++ net/core/flow_dissector.c | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h index 8a5bf48..3bdf6a1 100644 --- a/include/net/flow_dissector.h +++ b/include/net/flow_dissector.h @@ -1,6 +1,64 @@ #ifndef _NET_FLOW_DISSECTOR_H #define _NET_FLOW_DISSECTOR_H +/** + * struct flow_dissector_key_basic: + * @thoff: Transport header offset + * @n_proto: Network header protocol (eg. IPv4/IPv6) + * @ip_proto: Transport header protocol (eg. TCP/UDP) + */ +struct flow_dissector_key_basic { + u16 thoff; + __be16 n_proto; + u8 ip_proto; +}; + +/** + * struct flow_dissector_key_addrs: + * @src: source ip address in case of IPv4 + * For IPv6 it contains 32bit hash of src address + * @dst: destination ip address in case of IPv4 + * For IPv6 it contains 32bit hash of dst address + */ +struct flow_dissector_key_addrs { + /* (src,dst) must be grouped, in the same way than in IP header */ + __be32 src; + __be32 dst; +}; + +/** + * flow_dissector_key_tp_ports: + * @ports: port numbers of Transport header + * port16[0]: src port number + * port16[1]: dst port number + */ +struct flow_dissector_key_ports { + union { + __be32 ports; + __be16 port16[2]; + }; +}; + +enum flow_dissector_key_id { + FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */ + FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_addrs */ + FLOW_DISSECTOR_KEY_IPV6_HASH_ADDRS, /* struct flow_dissector_key_addrs */ + FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */ + + FLOW_DISSECTOR_KEY_MAX, +}; + +struct flow_dissector_key { + enum flow_dissector_key_id key_id; + size_t offset; /* offset of struct flow_dissector_key_* + in target the struct */ +}; + +struct flow_dissector { + unsigned int used_keys; /* each bit repesents presence of one key id */ + unsigned short int offset[FLOW_DISSECTOR_KEY_MAX]; +}; + /* struct flow_keys: * @src: source ip address in case of IPv4 * For IPv6 it contains 32bit hash of src address @@ -27,6 +85,9 @@ struct flow_keys { u8 ip_proto; }; +void skb_flow_dissector_init(struct flow_dissector *flow_dissector, + const struct flow_dissector_key *key, + unsigned int key_count); bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow, void *data, __be16 proto, int nhoff, int hlen); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 5213d73..1566768 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -15,6 +16,53 @@ #include #include +static bool skb_flow_dissector_uses_key(struct flow_dissector *flow_dissector, + enum flow_dissector_key_id key_id) +{ + return flow_dissector->used_keys & (1 << key_id); +} + +static void skb_flow_dissector_set_key(struct flow_dissector *flow_dissector, + enum flow_dissector_key_id key_id) +{ + flow_dissector->used_keys |= (1 << key_id); +} + +static void *skb_flow_dissector_target(struct flow_dissector *flow_dissector, + enum flow_dissector_key_id key_id, + void *target_container) +{ + return ((char *) target_container) + flow_dissector->offset[key_id]; +} + +void skb_flow_dissector_init(struct flow_dissector *flow_dissector, + const struct flow_dissector_key *key, + unsigned int key_count) +{ + unsigned int i; + + memset(flow_dissector, 0, sizeof(*flow_dissector)); + + for (i = 0; i < key_count; i++, key++) { + /* User should make sure that every key target offset is withing + * boundaries of unsigned short. + */ + BUG_ON(key->offset > USHRT_MAX); + BUG_ON(skb_flow_dissector_uses_key(flow_dissector, + key->key_id)); + + skb_flow_dissector_set_key(flow_dissector, key->key_id); + flow_dissector->offset[key->key_id] = key->offset; + } + + /* Ensure that the dissector always includes basic key. That way + * we are able to avoid handling lack of it in fast path. + */ + BUG_ON(!skb_flow_dissector_uses_key(flow_dissector, + FLOW_DISSECTOR_KEY_BASIC)); +} +EXPORT_SYMBOL(skb_flow_dissector_init); + /* copy saddr & daddr, possibly using 64bit load/store * Equivalent to : flow->src = iph->saddr; * flow->dst = iph->daddr;