From patchwork Mon Dec 11 20:38:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847211 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="PWdF+PS0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZYp4fHlz9sRm for ; Tue, 12 Dec 2017 07:39:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752506AbdLKUjI (ORCPT ); Mon, 11 Dec 2017 15:39:08 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:42425 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752479AbdLKUjE (ORCPT ); Mon, 11 Dec 2017 15:39:04 -0500 Received: by mail-pg0-f68.google.com with SMTP id e14so11752541pgr.9 for ; Mon, 11 Dec 2017 12:39:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jo8jIUE/tFvyqeE43NOJWn0uMeIXkTrwbYkczfk/I4k=; b=PWdF+PS03ffk8jI19oJG2qz6jnycQokLUWl7kCKZhPcPsvVanXsjyT1I720FIjfeRL BpHL928MddQ0LIyM2vvn5XlQ3X7BgkxxW4qtwFzkFxGRRifkPa+cKVhkyYsqHLqVPBsK hUP0nWV1MTJQlpgV+XyeTD7Qw0k5aSjedwPuSiyPtfrqzm1wnHzOWtgDOYblNRfuYQxB 7AZzgW5ojmotRgC752JSBSdpvkGNrg9aH6lL+7+NUAv7tpO69QhnxGqYXqfS0oBwSpPt Jn8ZIf15Bcjstl9ImjNMxmSUa5iCLgC5/bRsVJWF1wsCnWSfEdtyVj1Nv/QtCiaHeW6m MDJA== 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:in-reply-to :references; bh=jo8jIUE/tFvyqeE43NOJWn0uMeIXkTrwbYkczfk/I4k=; b=dI8UIJkI4XpmMPkzr3E+S+/Oln+bdkO1SaXOsCPukiQvmHsDMpJaCa0Z7F+I18GObW JcBlkh2L+9Qs8iZrQNQjcvlx7fBTs468/ekdWXoAPNJDtmeeYDsBnaHY9Kb4e6nWD4D2 GmtmEMLNS38pINdEORoIrJy+nKryHX8SOIPS+sU9UPvPhljP5YBUO7MXOHYhAGwqKtCa Hkq5xLP5cwIcMua/AwgRdCXqWSIxAYFJKhPGxRzxpeS7G7Em3eCr14dqWWc4soi1b33p j/qeTFYXEmEr1C/3AFFGL9A7o7njQhvrymVm0ctiYe3tTQJkV+jBmUJIHanlJQGUSK0b u6YA== X-Gm-Message-State: AKGB3mJDwSTzo+x3Yb3JRxaLw8t8hbyDnPpktkcjp1hd0D3kfecogMeV 35NV8J2czgnGWOjhxtlsyDsecQ== X-Google-Smtp-Source: ACJfBovUBXPorOXdnpwPBvk0Yv9SJh9IKxrcvrUwkz3aNowkhTzI1kv7DgTX7TkhBB5nh7I4oQJxxQ== X-Received: by 10.99.3.146 with SMTP id 140mr1373956pgd.275.1513024743213; Mon, 11 Dec 2017 12:39:03 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:02 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 1/9] lwt: Add net to build_state argument Date: Mon, 11 Dec 2017 12:38:29 -0800 Message-Id: <20171211203837.2540-2-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Users of LWT need to know net if they want to have per net operations in LWT. Signed-off-by: Tom Herbert --- include/net/lwtunnel.h | 6 +++--- net/core/lwt_bpf.c | 2 +- net/core/lwtunnel.c | 4 ++-- net/ipv4/fib_semantics.c | 13 ++++++++----- net/ipv4/ip_tunnel_core.c | 4 ++-- net/ipv6/ila/ila_lwt.c | 2 +- net/ipv6/route.c | 2 +- net/ipv6/seg6_iptunnel.c | 2 +- net/ipv6/seg6_local.c | 5 +++-- net/mpls/mpls_iptunnel.c | 2 +- 10 files changed, 23 insertions(+), 19 deletions(-) diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index d747ef975cd8..da5e51e0d122 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -34,7 +34,7 @@ struct lwtunnel_state { }; struct lwtunnel_encap_ops { - int (*build_state)(struct nlattr *encap, + int (*build_state)(struct net *net, struct nlattr *encap, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack); @@ -113,7 +113,7 @@ int lwtunnel_valid_encap_type(u16 encap_type, struct netlink_ext_ack *extack); int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, struct netlink_ext_ack *extack); -int lwtunnel_build_state(u16 encap_type, +int lwtunnel_build_state(struct net *net, u16 encap_type, struct nlattr *encap, unsigned int family, const void *cfg, struct lwtunnel_state **lws, @@ -192,7 +192,7 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len, return 0; } -static inline int lwtunnel_build_state(u16 encap_type, +static inline int lwtunnel_build_state(struct net *net, u16 encap_type, struct nlattr *encap, unsigned int family, const void *cfg, struct lwtunnel_state **lws, diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index e7e626fb87bb..3a3ac13fcf06 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -238,7 +238,7 @@ static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = { [LWT_BPF_XMIT_HEADROOM] = { .type = NLA_U32 }, }; -static int bpf_build_state(struct nlattr *nla, +static int bpf_build_state(struct net *net, struct nlattr *nla, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index 0b171756453c..b3f2f77dfe72 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -103,7 +103,7 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops, } EXPORT_SYMBOL_GPL(lwtunnel_encap_del_ops); -int lwtunnel_build_state(u16 encap_type, +int lwtunnel_build_state(struct net *net, u16 encap_type, struct nlattr *encap, unsigned int family, const void *cfg, struct lwtunnel_state **lws, struct netlink_ext_ack *extack) @@ -124,7 +124,7 @@ int lwtunnel_build_state(u16 encap_type, ops = rcu_dereference(lwtun_encaps[encap_type]); if (likely(ops && ops->build_state && try_module_get(ops->owner))) { found = true; - ret = ops->build_state(encap, family, cfg, lws, extack); + ret = ops->build_state(net, encap, family, cfg, lws, extack); if (ret) module_put(ops->owner); } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index f04d944f8abe..4979e5c6b9b8 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -523,6 +523,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, if (nla) { struct lwtunnel_state *lwtstate; struct nlattr *nla_entype; + struct net *net = cfg->fc_nlinfo.nl_net; nla_entype = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); @@ -533,7 +534,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, goto err_inval; } - ret = lwtunnel_build_state(nla_get_u16( + ret = lwtunnel_build_state(net, nla_get_u16( nla_entype), nla, AF_INET, cfg, &lwtstate, extack); @@ -607,7 +608,7 @@ static void fib_rebalance(struct fib_info *fi) #endif /* CONFIG_IP_ROUTE_MULTIPATH */ -static int fib_encap_match(u16 encap_type, +static int fib_encap_match(struct net *net, u16 encap_type, struct nlattr *encap, const struct fib_nh *nh, const struct fib_config *cfg, @@ -619,7 +620,7 @@ static int fib_encap_match(u16 encap_type, if (encap_type == LWTUNNEL_ENCAP_NONE) return 0; - ret = lwtunnel_build_state(encap_type, encap, AF_INET, + ret = lwtunnel_build_state(net, encap_type, encap, AF_INET, cfg, &lwtstate, extack); if (!ret) { result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); @@ -632,6 +633,7 @@ static int fib_encap_match(u16 encap_type, int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, struct netlink_ext_ack *extack) { + struct net *net = cfg->fc_nlinfo.nl_net; #ifdef CONFIG_IP_ROUTE_MULTIPATH struct rtnexthop *rtnh; int remaining; @@ -642,7 +644,8 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, if (cfg->fc_oif || cfg->fc_gw) { if (cfg->fc_encap) { - if (fib_encap_match(cfg->fc_encap_type, cfg->fc_encap, + if (fib_encap_match(net, cfg->fc_encap_type, + cfg->fc_encap, fi->fib_nh, cfg, extack)) return 1; } @@ -1180,7 +1183,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg, "LWT encap type not specified"); goto err_inval; } - err = lwtunnel_build_state(cfg->fc_encap_type, + err = lwtunnel_build_state(net, cfg->fc_encap_type, cfg->fc_encap, AF_INET, cfg, &lwtstate, extack); if (err) diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 2f39479be92f..32e05aa6117d 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -228,7 +228,7 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = { [LWTUNNEL_IP_FLAGS] = { .type = NLA_U16 }, }; -static int ip_tun_build_state(struct nlattr *attr, +static int ip_tun_build_state(struct net *net, struct nlattr *attr, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) @@ -327,7 +327,7 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = { [LWTUNNEL_IP6_FLAGS] = { .type = NLA_U16 }, }; -static int ip6_tun_build_state(struct nlattr *attr, +static int ip6_tun_build_state(struct net *net, struct nlattr *attr, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index 3d56a2fb6f86..9f1e46a1468e 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -125,7 +125,7 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { [ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, }, }; -static int ila_build_state(struct nlattr *nla, +static int ila_build_state(struct net *net, struct nlattr *nla, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b3f4d19b3ca5..0e0cc97e8f42 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2565,7 +2565,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, if (cfg->fc_encap) { struct lwtunnel_state *lwtstate; - err = lwtunnel_build_state(cfg->fc_encap_type, + err = lwtunnel_build_state(net, cfg->fc_encap_type, cfg->fc_encap, AF_INET6, cfg, &lwtstate, extack); if (err) diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index bd6cc688bd19..a6cf2fba15f3 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -359,7 +359,7 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) return err; } -static int seg6_build_state(struct nlattr *nla, +static int seg6_build_state(struct net *net, struct nlattr *nla, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c index 825b8e01f947..45dc670c5a93 100644 --- a/net/ipv6/seg6_local.c +++ b/net/ipv6/seg6_local.c @@ -779,8 +779,9 @@ static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt) return 0; } -static int seg6_local_build_state(struct nlattr *nla, unsigned int family, - const void *cfg, struct lwtunnel_state **ts, +static int seg6_local_build_state(struct net *net, struct nlattr *nla, + unsigned int family, const void *cfg, + struct lwtunnel_state **ts, struct netlink_ext_ack *extack) { struct nlattr *tb[SEG6_LOCAL_MAX + 1]; diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c index 6e558a419f60..c947310cc04f 100644 --- a/net/mpls/mpls_iptunnel.c +++ b/net/mpls/mpls_iptunnel.c @@ -157,7 +157,7 @@ static int mpls_xmit(struct sk_buff *skb) return -EINVAL; } -static int mpls_build_state(struct nlattr *nla, +static int mpls_build_state(struct net *net, struct nlattr *nla, unsigned int family, const void *cfg, struct lwtunnel_state **ts, struct netlink_ext_ack *extack) From patchwork Mon Dec 11 20:38:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847212 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="tx+kAO8+"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZYs6WNZz9sRm for ; Tue, 12 Dec 2017 07:39:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752523AbdLKUjK (ORCPT ); Mon, 11 Dec 2017 15:39:10 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:42425 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752486AbdLKUjG (ORCPT ); Mon, 11 Dec 2017 15:39:06 -0500 Received: by mail-pg0-f65.google.com with SMTP id e14so11752601pgr.9 for ; Mon, 11 Dec 2017 12:39:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MdSMg6wf/qqmk1ij2DZfJmFZFwIKVZ3R/K55gFoVw+o=; b=tx+kAO8+w5hQsWYnGyBwa9oFhNs8mpQcZgRQ/zESxPU29/KMgRhXz9yd0tlGnRFPHl XkMRD3osVIXP5D3vC94kLsjCYNXy2Ox8rrm5v7UkBW9E/RA77Guk6/8GWB075XfTaq2O M6gdTTmsmOWe6WO7jGnKUN8X+t+fCnKyb0myZS3vwcrS0+ICFYXnhu7aXTcAil8Sklet Co4zpX9cAgXV49ynLKka9oWtMuhDnMQzF3wbeoy7ChmfCnAQhiQDtgk4kjtopobAXl1g +bHcFSRWkomAehkfeHAo0FdidBy+Zy3Ll8IIIy2hcs73NG1lTGtgKPgqn+mAPYNqjI1M mewQ== 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:in-reply-to :references; bh=MdSMg6wf/qqmk1ij2DZfJmFZFwIKVZ3R/K55gFoVw+o=; b=Rv0X6l+Ocy49RNJYmm6FT4aAUT1LMzoiAKLgkwIVOyii0r4cORUeynRF53MzMj8kEC LVpgzC1Ch7vUW5qZWQCvJaVJKxKLY2qxOy3q8O0djWeMcnaHTZ7TmVugPv8uz+Ldspvz nKxQ/S3ZWLPMb1gpHqOysL0WM99BXY0hg/Jsh6VUtOJ8HmIwONWGV22qrtVCIOD9EIEB fxlPfjRWZiQJ9rs26qUSbuyGnDu5UXXVpVieF9Xcu9GV0/AnwJ2BHhmyqUMQOSKe78MN QSm/2aoTlBBb6g2DefBY5ha9EuOUofoo76Cy/Dn3Vh5aqQ2x//DxAC+Mew0EVDdy6S8S ZqFQ== X-Gm-Message-State: AKGB3mKCqVssFZNwh2TjC/0eUQCij8i/XjJ77xXjFqKRWRNz2w+hL2y5 /xEzp1g4lEKVERFieKTh9q3H2A== X-Google-Smtp-Source: ACJfBosiowGRODZ8aB4chxbZHfjISqxEV9aMJpkNxJgtFuVZ9z8I27gExa0f//mt2B3bfyb+K9fjgQ== X-Received: by 10.84.238.136 with SMTP id v8mr1505271plk.381.1513024745495; Mon, 11 Dec 2017 12:39:05 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:04 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 2/9] ila: Fix use of rhashtable walk in ila_xlat.c Date: Mon, 11 Dec 2017 12:38:30 -0800 Message-Id: <20171211203837.2540-3-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Perform better EAGAIN handling, handle case where ila_dump_info fails and we miss mis objects in the dump, and add a skip index to skip over ila entires in a list on a rhashtable node that have already been visited (by a previous call to ila_nl_dump). Signed-off-by: Tom Herbert --- net/ipv6/ila/ila_xlat.c | 60 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 44c39c5f0638..9fca75b9cab3 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -474,24 +474,31 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) struct ila_dump_iter { struct rhashtable_iter rhiter; + int skip; }; static int ila_nl_dump_start(struct netlink_callback *cb) { struct net *net = sock_net(cb->skb->sk); struct ila_net *ilan = net_generic(net, ila_net_id); - struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0]; + struct ila_dump_iter *iter; + int ret; - if (!iter) { - iter = kmalloc(sizeof(*iter), GFP_KERNEL); - if (!iter) - return -ENOMEM; + iter = kmalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + return -ENOMEM; - cb->args[0] = (long)iter; + ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter, + GFP_KERNEL); + if (ret) { + kfree(iter); + return ret; } - return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter, - GFP_KERNEL); + iter->skip = 0; + cb->args[0] = (long)iter; + + return ret; } static int ila_nl_dump_done(struct netlink_callback *cb) @@ -509,37 +516,58 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0]; struct rhashtable_iter *rhiter = &iter->rhiter; + int skip = iter->skip; struct ila_map *ila; int ret; rhashtable_walk_start(rhiter); - for (;;) { - ila = rhashtable_walk_next(rhiter); + /* Get first entty */ + ila = rhashtable_walk_peek(rhiter); + for (;;) { if (IS_ERR(ila)) { - if (PTR_ERR(ila) == -EAGAIN) - continue; ret = PTR_ERR(ila); - goto done; + if (ret == -EAGAIN) { + /* Table has changed and iter has reset. Return + * -EAGAIN to the application even if we have + * written data to the skb. The application + * needs to deal with this. + */ + + goto out_ret; + } else { + break; + } } else if (!ila) { + ret = 0; break; } + while (ila && skip) { + /* Skip over any ila entries in this list that we + * have already dumped. + */ + ila = rcu_access_pointer(ila->next); + skip--; + } while (ila) { ret = ila_dump_info(ila, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, skb, ILA_CMD_GET); if (ret) - goto done; + goto out; ila = rcu_access_pointer(ila->next); } + ila = rhashtable_walk_next(rhiter); } - ret = skb->len; +out: + iter->skip = skip; + ret = (skb->len ? : ret); -done: +out_ret: rhashtable_walk_stop(rhiter); return ret; } From patchwork Mon Dec 11 20:38:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847215 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="DyzRYf+C"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZ50Y0dz9sRm for ; Tue, 12 Dec 2017 07:39:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752570AbdLKUjW (ORCPT ); Mon, 11 Dec 2017 15:39:22 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:44913 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752498AbdLKUjI (ORCPT ); Mon, 11 Dec 2017 15:39:08 -0500 Received: by mail-pf0-f193.google.com with SMTP id m26so12429880pfj.11 for ; Mon, 11 Dec 2017 12:39:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=e489jEXl2Z+OVxmDmqVJoJykEDqddOfNQJRN+jzQIJU=; b=DyzRYf+CRvR2nVa5dNf1cFh45MzL1179nZV++m6940AQjDitzcdVug2bFApCe/PtJk h36oJotdqXLxI9viImTQc+pSbnUU3z/QxOH5Bu14iL4ZmaRfiSKfL23uyB3mQESBr7et vtWWRfIRKFb3ImA2ySXBks7haYvnTO/LRaoNp7Yk9yf6gad+FJPxErKzKOsrxqN3dmSU vIFhLgiyxCBC2ShmcmEi5lKThD70yUafd4V/W9GXCFCDTYOFnWVD89O0YFOZ3Tnu2U5B rZ+Q0lIePkCmX+JlN841dfJwfWok3V4A2M5g/XFnA7/JjLoWtfJoDJmz+Y/SE6SWcSHh gJUg== 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:in-reply-to :references; bh=e489jEXl2Z+OVxmDmqVJoJykEDqddOfNQJRN+jzQIJU=; b=ENSrndaaT7BJKWAuiBB51WiSSJ7xL2YOEJat3ReRyyxT2ud4CfBT88Ti+dNVDgx+PL gyV56Y3uFM1OPTiGA2fQFZSl05/VGF7IIXQ4ehCIcqJpoUdF6ulODJYrliuMgHqXfTG8 7+z80wTXmVe5mQ6y/oTfxj5w0wMSXj5Gh8ywFdusW96BcfvBaWT8xDGDjrq/Dbe6zBy+ 8PcHfRDcAATXsBuTO/qvfGKAYOb/shD1ou53nWSh5iE0e/M+Dw0m465kzWS1UdRnZA6+ soNmR3ZiouVHJ83eIwxsxw5KcgEebJ4OJGoDAIW9WMRDy0bVzPZazAT4nxuQAPtoZbyz JEpg== X-Gm-Message-State: AKGB3mJ+UcJXEsnDN9rdek0q48cjdHdbIDiBVu+EVg2+p0t7pteXuVLE mzjyLl4JrTYdL6tBCe8zpanZ9/2D X-Google-Smtp-Source: ACJfBov6AvqPg95mvKCGY/5/SBbx3zymnftYjTIf9zHR7v5gRMLBTdj+x2W0pco3iQwzBJFVdXDWKw== X-Received: by 10.159.214.137 with SMTP id n9mr1563642plp.126.1513024748182; Mon, 11 Dec 2017 12:39:08 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:07 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 3/9] ila: Call library function alloc_bucket_locks Date: Mon, 11 Dec 2017 12:38:31 -0800 Message-Id: <20171211203837.2540-4-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org To allocate the array of bucket locks for the hash table we now call library function alloc_bucket_spinlocks. Signed-off-by: Tom Herbert --- net/ipv6/ila/ila_xlat.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 9fca75b9cab3..402193ef74c2 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -31,26 +31,14 @@ struct ila_net { bool hooks_registered; }; +#define MAX_LOCKS 1024 #define LOCKS_PER_CPU 10 static int alloc_ila_locks(struct ila_net *ilan) { - unsigned int i, size; - unsigned int nr_pcpus = num_possible_cpus(); - - nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL); - size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); - - if (sizeof(spinlock_t) != 0) { - ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL); - if (!ilan->locks) - return -ENOMEM; - for (i = 0; i < size; i++) - spin_lock_init(&ilan->locks[i]); - } - ilan->locks_mask = size - 1; - - return 0; + return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask, + MAX_LOCKS, LOCKS_PER_CPU, + GFP_KERNEL); } static u32 hashrnd __read_mostly; @@ -629,7 +617,7 @@ static __net_exit void ila_exit_net(struct net *net) rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL); - kvfree(ilan->locks); + free_bucket_spinlocks(ilan->xlat.locks); if (ilan->hooks_registered) nf_unregister_net_hooks(net, ila_nf_hook_ops, From patchwork Mon Dec 11 20:38:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847214 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="MKGgC9Ie"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZ1009dz9sRm for ; Tue, 12 Dec 2017 07:39:20 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752562AbdLKUjT (ORCPT ); Mon, 11 Dec 2017 15:39:19 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:37884 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752525AbdLKUjL (ORCPT ); Mon, 11 Dec 2017 15:39:11 -0500 Received: by mail-pf0-f196.google.com with SMTP id n6so12445299pfa.4 for ; Mon, 11 Dec 2017 12:39:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=B7QB2ratjGkBYSecT3gzn95pnLt2Wc7DT+ZyPTlQwXE=; b=MKGgC9IexqGwYWC/39c2OQcK/tNMsPkXLx/dy/pFaazKemGP5RQXtUtPV6J/6m4MBn Neuuu2/I6VRdNRFxVTT7ZHrQDtR/YkscW/c90KI8HAFrNPasv+IqlSvHFNjwqnjn/GAn w4zhdJmU9J9sVrZqv0yHYWs4cGcF4nHROlu+ADXVLOk97QjjzXhCKhm3AzdNWpmB/h4b YgWjnr8fYdDJyVfAtLM2w40twkZnRTsEpsnVro4PXds4EJKPgQeKIYaiLHXSOCKHKzH3 4T6sCa/Yh472IFnwy/vUAL2ZoPqGhsxSbLNj7FaOUkvTgxBTPJ0ab5iwQz5V+GzBu+mh ViOw== 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:in-reply-to :references; bh=B7QB2ratjGkBYSecT3gzn95pnLt2Wc7DT+ZyPTlQwXE=; b=jwCqZ2JC8ftmd5Y3J97es+sCi3VFsSwxpJOtbDS7bfTYIDkEodjYbS6K3SXC5KLNRA dgcXqAa4up2rFfrgHqyDthEY5zqr0PNsVE2w5njhXNyANAb/i5BfKfLktYlMYuavJ2m8 pFdX4SDWbSxrfB4lym0gBQIK0mpHCzFZ7lHYrfpFT604aJ7XU9j3fisEl/VmciCK+g48 YmcOtIzp0x/T3OKmghZX0CPtf5bB88ZNnmE92uGDc7/PtLUbUsbMR3bd8ztTW4Ze89SS GinYWF3rs/eZtLR5A9Iq7jEjGDAePHtojPVWbbruI5Kld9utAcYBz7mUXqwVXEIVgcxC W3uQ== X-Gm-Message-State: AKGB3mK0buj/Jsq8uIy0PrKCyQ5tRw/3rLxHMtYaP5bQE3qz+EgcBoN7 09cv4hN4xe73hy6u8C695DEI+6pG X-Google-Smtp-Source: ACJfBosavEJgyea3mTzUlmwGELcF8t10UqfQRnXrNPNi00/U7py490mi7lQVSmtKMaWFcOFkWRQt7A== X-Received: by 10.99.124.88 with SMTP id l24mr1402052pgn.355.1513024750309; Mon, 11 Dec 2017 12:39:10 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:09 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 4/9] ila: create main ila source file Date: Mon, 11 Dec 2017 12:38:32 -0800 Message-Id: <20171211203837.2540-5-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Create a main ila file that contains the module intialization functions as well as netlink definitions. Previously these were defined in ila_xlat and ila_common. This approach allows better extensibility. Signed-off-by: Tom Herbert --- net/ipv6/ila/Makefile | 2 +- net/ipv6/ila/ila.h | 26 ++++++++- net/ipv6/ila/ila_common.c | 30 ---------- net/ipv6/ila/ila_main.c | 115 ++++++++++++++++++++++++++++++++++++++ net/ipv6/ila/ila_xlat.c | 138 +++++++++------------------------------------- 5 files changed, 166 insertions(+), 145 deletions(-) create mode 100644 net/ipv6/ila/ila_main.c diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile index 4b32e5921e5c..b7739aba6e68 100644 --- a/net/ipv6/ila/Makefile +++ b/net/ipv6/ila/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_IPV6_ILA) += ila.o -ila-objs := ila_common.o ila_lwt.o ila_xlat.o +ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index 3c7a11b62334..faba7824ea56 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -104,9 +105,30 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p, void ila_init_saved_csum(struct ila_params *p); +struct ila_net { + struct { + struct rhashtable rhash_table; + spinlock_t *locks; /* Bucket locks for entry manipulation */ + unsigned int locks_mask; + bool hooks_registered; + } xlat; +}; + int ila_lwt_init(void); void ila_lwt_fini(void); -int ila_xlat_init(void); -void ila_xlat_fini(void); + +int ila_xlat_init_net(struct net *net); +void ila_xlat_exit_net(struct net *net); + +int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info); +int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info); +int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info); +int ila_xlat_nl_dump_start(struct netlink_callback *cb); +int ila_xlat_nl_dump_done(struct netlink_callback *cb); +int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb); + +extern unsigned int ila_net_id; + +extern struct genl_family ila_nl_family; #endif /* __ILA_H */ diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c index 8c88ecf29b93..579310466eac 100644 --- a/net/ipv6/ila/ila_common.c +++ b/net/ipv6/ila/ila_common.c @@ -154,33 +154,3 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p, iaddr->loc = p->locator; } -static int __init ila_init(void) -{ - int ret; - - ret = ila_lwt_init(); - - if (ret) - goto fail_lwt; - - ret = ila_xlat_init(); - if (ret) - goto fail_xlat; - - return 0; -fail_xlat: - ila_lwt_fini(); -fail_lwt: - return ret; -} - -static void __exit ila_fini(void) -{ - ila_xlat_fini(); - ila_lwt_fini(); -} - -module_init(ila_init); -module_exit(ila_fini); -MODULE_AUTHOR("Tom Herbert "); -MODULE_LICENSE("GPL"); diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c new file mode 100644 index 000000000000..f6ac6b14577e --- /dev/null +++ b/net/ipv6/ila/ila_main.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "ila.h" + +static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { + [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, + [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, + [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, + [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, + [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, }, +}; + +static const struct genl_ops ila_nl_ops[] = { + { + .cmd = ILA_CMD_ADD, + .doit = ila_xlat_nl_cmd_add_mapping, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = ILA_CMD_DEL, + .doit = ila_xlat_nl_cmd_del_mapping, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = ILA_CMD_GET, + .doit = ila_xlat_nl_cmd_get_mapping, + .start = ila_xlat_nl_dump_start, + .dumpit = ila_xlat_nl_dump, + .done = ila_xlat_nl_dump_done, + .policy = ila_nl_policy, + }, +}; + +unsigned int ila_net_id; + +struct genl_family ila_nl_family __ro_after_init = { + .hdrsize = 0, + .name = ILA_GENL_NAME, + .version = ILA_GENL_VERSION, + .maxattr = ILA_ATTR_MAX, + .netnsok = true, + .parallel_ops = true, + .module = THIS_MODULE, + .ops = ila_nl_ops, + .n_ops = ARRAY_SIZE(ila_nl_ops), +}; + +static __net_init int ila_init_net(struct net *net) +{ + int err; + + err = ila_xlat_init_net(net); + if (err) + goto ila_xlat_init_fail; + + return 0; + +ila_xlat_init_fail: + return err; +} + +static __net_exit void ila_exit_net(struct net *net) +{ + ila_xlat_exit_net(net); +} + +static struct pernet_operations ila_net_ops = { + .init = ila_init_net, + .exit = ila_exit_net, + .id = &ila_net_id, + .size = sizeof(struct ila_net), +}; + +static int __init ila_init(void) +{ + int ret; + + ret = register_pernet_device(&ila_net_ops); + if (ret) + goto register_device_fail; + + ret = genl_register_family(&ila_nl_family); + if (ret) + goto register_family_fail; + + ret = ila_lwt_init(); + if (ret) + goto fail_lwt; + + return 0; + +fail_lwt: + genl_unregister_family(&ila_nl_family); +register_family_fail: + unregister_pernet_device(&ila_net_ops); +register_device_fail: + return ret; +} + +static void __exit ila_fini(void) +{ + ila_lwt_fini(); + genl_unregister_family(&ila_nl_family); + unregister_pernet_device(&ila_net_ops); +} + +module_init(ila_init); +module_exit(ila_fini); +MODULE_AUTHOR("Tom Herbert "); +MODULE_LICENSE("GPL"); diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 402193ef74c2..610852b3dfa7 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -22,15 +22,6 @@ struct ila_map { struct rcu_head rcu; }; -static unsigned int ila_net_id; - -struct ila_net { - struct rhashtable rhash_table; - spinlock_t *locks; /* Bucket locks for entry manipulation */ - unsigned int locks_mask; - bool hooks_registered; -}; - #define MAX_LOCKS 1024 #define LOCKS_PER_CPU 10 @@ -58,7 +49,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc) static inline spinlock_t *ila_get_lock(struct ila_net *ilan, struct ila_locator loc) { - return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask]; + return &ilan->xlat.locks[ila_locator_hash(loc) & ilan->xlat.locks_mask]; } static inline int ila_cmp_wildcards(struct ila_map *ila, @@ -102,16 +93,6 @@ static const struct rhashtable_params rht_params = { .obj_cmpfn = ila_cmpfn, }; -static struct genl_family ila_nl_family; - -static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { - [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, - [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, - [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, - [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, - [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, }, -}; - static int parse_nl_config(struct genl_info *info, struct ila_xlat_params *xp) { @@ -149,7 +130,7 @@ static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr, { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc, + ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &iaddr->loc, rht_params); while (ila) { if (!ila_cmp_wildcards(ila, iaddr, ifindex)) @@ -166,7 +147,7 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp, { struct ila_map *ila; - ila = rhashtable_lookup_fast(&ilan->rhash_table, + ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &xp->ip.locator_match, rht_params); while (ila) { @@ -222,7 +203,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); int err = 0, order; - if (!ilan->hooks_registered) { + if (!ilan->xlat.hooks_registered) { /* We defer registering net hooks in the namespace until the * first mapping is added. */ @@ -231,7 +212,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) if (err) return err; - ilan->hooks_registered = true; + ilan->xlat.hooks_registered = true; } ila = kzalloc(sizeof(*ila), GFP_KERNEL); @@ -246,12 +227,12 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) spin_lock(lock); - head = rhashtable_lookup_fast(&ilan->rhash_table, + head = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &xp->ip.locator_match, rht_params); if (!head) { /* New entry for the rhash_table */ - err = rhashtable_lookup_insert_fast(&ilan->rhash_table, + err = rhashtable_lookup_insert_fast(&ilan->xlat.rhash_table, &ila->node, rht_params); } else { struct ila_map *tila = head, *prev = NULL; @@ -277,7 +258,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) } else { /* Make this ila new head */ RCU_INIT_POINTER(ila->next, head); - err = rhashtable_replace_fast(&ilan->rhash_table, + err = rhashtable_replace_fast(&ilan->xlat.rhash_table, &head->node, &ila->node, rht_params); if (err) @@ -303,7 +284,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) spin_lock(lock); - head = rhashtable_lookup_fast(&ilan->rhash_table, + head = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &xp->ip.locator_match, rht_params); ila = head; @@ -333,15 +314,15 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) * table */ err = rhashtable_replace_fast( - &ilan->rhash_table, &ila->node, + &ilan->xlat.rhash_table, &ila->node, &head->node, rht_params); if (err) goto out; } else { /* Entry no longer used */ - err = rhashtable_remove_fast(&ilan->rhash_table, - &ila->node, - rht_params); + err = rhashtable_remove_fast( + &ilan->xlat.rhash_table, + &ila->node, rht_params); } } @@ -356,7 +337,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) return err; } -static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) +int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); struct ila_xlat_params p; @@ -369,7 +350,7 @@ static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) return ila_add_mapping(net, &p); } -static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) +int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); struct ila_xlat_params xp; @@ -421,7 +402,7 @@ static int ila_dump_info(struct ila_map *ila, return -EMSGSIZE; } -static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) +int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); struct ila_net *ilan = net_generic(net, ila_net_id); @@ -465,7 +446,7 @@ struct ila_dump_iter { int skip; }; -static int ila_nl_dump_start(struct netlink_callback *cb) +int ila_xlat_nl_dump_start(struct netlink_callback *cb) { struct net *net = sock_net(cb->skb->sk); struct ila_net *ilan = net_generic(net, ila_net_id); @@ -476,7 +457,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb) if (!iter) return -ENOMEM; - ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter, + ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter->rhiter, GFP_KERNEL); if (ret) { kfree(iter); @@ -489,7 +470,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb) return ret; } -static int ila_nl_dump_done(struct netlink_callback *cb) +int ila_xlat_nl_dump_done(struct netlink_callback *cb) { struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0]; @@ -500,7 +481,7 @@ static int ila_nl_dump_done(struct netlink_callback *cb) return 0; } -static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) +int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0]; struct rhashtable_iter *rhiter = &iter->rhiter; @@ -560,77 +541,35 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) return ret; } -static const struct genl_ops ila_nl_ops[] = { - { - .cmd = ILA_CMD_ADD, - .doit = ila_nl_cmd_add_mapping, - .policy = ila_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = ILA_CMD_DEL, - .doit = ila_nl_cmd_del_mapping, - .policy = ila_nl_policy, - .flags = GENL_ADMIN_PERM, - }, - { - .cmd = ILA_CMD_GET, - .doit = ila_nl_cmd_get_mapping, - .start = ila_nl_dump_start, - .dumpit = ila_nl_dump, - .done = ila_nl_dump_done, - .policy = ila_nl_policy, - }, -}; - -static struct genl_family ila_nl_family __ro_after_init = { - .hdrsize = 0, - .name = ILA_GENL_NAME, - .version = ILA_GENL_VERSION, - .maxattr = ILA_ATTR_MAX, - .netnsok = true, - .parallel_ops = true, - .module = THIS_MODULE, - .ops = ila_nl_ops, - .n_ops = ARRAY_SIZE(ila_nl_ops), -}; - #define ILA_HASH_TABLE_SIZE 1024 -static __net_init int ila_init_net(struct net *net) +int ila_xlat_init_net(struct net *net) { - int err; struct ila_net *ilan = net_generic(net, ila_net_id); + int err; err = alloc_ila_locks(ilan); if (err) return err; - rhashtable_init(&ilan->rhash_table, &rht_params); + rhashtable_init(&ilan->xlat.rhash_table, &rht_params); return 0; } -static __net_exit void ila_exit_net(struct net *net) +void ila_xlat_exit_net(struct net *net) { struct ila_net *ilan = net_generic(net, ila_net_id); - rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL); + rhashtable_free_and_destroy(&ilan->xlat.rhash_table, ila_free_cb, NULL); free_bucket_spinlocks(ilan->xlat.locks); - if (ilan->hooks_registered) + if (ilan->xlat.hooks_registered) nf_unregister_net_hooks(net, ila_nf_hook_ops, ARRAY_SIZE(ila_nf_hook_ops)); } -static struct pernet_operations ila_net_ops = { - .init = ila_init_net, - .exit = ila_exit_net, - .id = &ila_net_id, - .size = sizeof(struct ila_net), -}; - static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila) { struct ila_map *ila; @@ -657,28 +596,3 @@ static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila) return 0; } -int __init ila_xlat_init(void) -{ - int ret; - - ret = register_pernet_device(&ila_net_ops); - if (ret) - goto exit; - - ret = genl_register_family(&ila_nl_family); - if (ret < 0) - goto unregister; - - return 0; - -unregister: - unregister_pernet_device(&ila_net_ops); -exit: - return ret; -} - -void ila_xlat_fini(void) -{ - genl_unregister_family(&ila_nl_family); - unregister_pernet_device(&ila_net_ops); -} From patchwork Mon Dec 11 20:38:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847213 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="rNXWQlBd"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZYy5RLJz9sRm for ; Tue, 12 Dec 2017 07:39:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752547AbdLKUjR (ORCPT ); Mon, 11 Dec 2017 15:39:17 -0500 Received: from mail-pg0-f67.google.com ([74.125.83.67]:44457 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752486AbdLKUjN (ORCPT ); Mon, 11 Dec 2017 15:39:13 -0500 Received: by mail-pg0-f67.google.com with SMTP id j9so11743422pgc.11 for ; Mon, 11 Dec 2017 12:39:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gdlQpfxDOuxJExuarVZFOgH/F3s72k/2acfvVZbTt2A=; b=rNXWQlBd7Vb3T3w9W5THnR7n2SXf4z2GAB7EgVPO676EKKp+vr6uPYI/nXzjAG0MNy 6WtZSwktvavnzVUKeM/1Ekd4qvFKpFE+LrE22p+KnernZleIfAwXgpl4BWD9Vs5ZrjEu YkIzT/p6VFUqtQoZMnr/wF081hCGDFHY3KI2+ZxHHvyvLx+7l4iqle/bkOVAbvXyxydb v3CY0vPwIUcWp76jqBoLNtUeCqwwHGUSmsXl9xYdAfPhsTGYXZydb1N7uTQAhojwLlAW KAc/xwgdEyXKSAa1l/U13c+3FDBlkNqub9UGAJw96EU5ScYMOm11ZCvNOxuJdkh+GACj ioiA== 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:in-reply-to :references; bh=gdlQpfxDOuxJExuarVZFOgH/F3s72k/2acfvVZbTt2A=; b=bF7mIQ0jJEtZ044jJ71gt/0OL8a+cXVj1GUEraj52crYlQpjN7t38aXCQfeTfHdl/Y /Fm9FOe9+VJ0lXrr6eZZ1tci1avrGAaGgcBNxudXfPpsn+P3ThZI5I6YEnFGdLVqqjyF hxvIWx8WNjK/gbrKk6XBI413DSLBwQvSlr4fzDehmFSEUUXv/c+37XfZob7J5b4K5W/7 jb2sdDMBSkC8JkkBp/rSmUqyj0jc0ICERChbsr2PIee304kon2sBo/MGNmkYZF19fVw9 eeAqx4yOdizHQkLWVocA9imTjuuZBup0vV27ZdfGJbPvkK2gFvRNvnpHs7zxag2yXgbC 9Kzg== X-Gm-Message-State: AKGB3mInmCp3w5v8pnMHQB5Z6OSHC3WH2qKRBO2aPl0fNRsAzy2Lzit6 sPnIFjVWkgG9sOb+K/4wSmH+B4Iv X-Google-Smtp-Source: ACJfBovUaJElsTFY1H1mVVrmRhUH02EQQ3XuNZpv/YVCLTvH4T8oM1JWZUATy5mwJVdgSHNmZe7RkQ== X-Received: by 10.99.127.14 with SMTP id a14mr1419678pgd.315.1513024752315; Mon, 11 Dec 2017 12:39:12 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:11 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 5/9] ila: Flush netlink command to clear xlat table Date: Mon, 11 Dec 2017 12:38:33 -0800 Message-Id: <20171211203837.2540-6-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add ILA_CMD_FLUSH netlink command to clear the ILA translation table. Signed-off-by: Tom Herbert --- include/uapi/linux/ila.h | 1 + net/ipv6/ila/ila.h | 1 + net/ipv6/ila/ila_main.c | 6 +++++ net/ipv6/ila/ila_xlat.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h index 483b77af4eb8..db45d3e49a12 100644 --- a/include/uapi/linux/ila.h +++ b/include/uapi/linux/ila.h @@ -30,6 +30,7 @@ enum { ILA_CMD_ADD, ILA_CMD_DEL, ILA_CMD_GET, + ILA_CMD_FLUSH, __ILA_CMD_MAX, }; diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index faba7824ea56..1f747bcbec29 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -123,6 +123,7 @@ void ila_xlat_exit_net(struct net *net); int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info); int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info); int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info); +int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info); int ila_xlat_nl_dump_start(struct netlink_callback *cb); int ila_xlat_nl_dump_done(struct netlink_callback *cb); int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb); diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c index f6ac6b14577e..18fac76b9520 100644 --- a/net/ipv6/ila/ila_main.c +++ b/net/ipv6/ila/ila_main.c @@ -27,6 +27,12 @@ static const struct genl_ops ila_nl_ops[] = { .flags = GENL_ADMIN_PERM, }, { + .cmd = ILA_CMD_FLUSH, + .doit = ila_xlat_nl_cmd_flush, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { .cmd = ILA_CMD_GET, .doit = ila_xlat_nl_cmd_get_mapping, .start = ila_xlat_nl_dump_start, diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c index 610852b3dfa7..6bb1a081ff04 100644 --- a/net/ipv6/ila/ila_xlat.c +++ b/net/ipv6/ila/ila_xlat.c @@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila) kfree_rcu(ila, rcu); } -static void ila_free_cb(void *ptr, void *arg) +static void ila_free_node(struct ila_map *ila) { - struct ila_map *ila = (struct ila_map *)ptr, *next; + struct ila_map *next; /* Assume rcu_readlock held */ while (ila) { @@ -176,6 +176,11 @@ static void ila_free_cb(void *ptr, void *arg) } } +static void ila_free_cb(void *ptr, void *arg) +{ + ila_free_node((struct ila_map *)ptr); +} + static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila); static unsigned int @@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) return 0; } +static inline spinlock_t *lock_from_ila_map(struct ila_net *ilan, + struct ila_map *ila) +{ + return ila_get_lock(ilan, ila->xp.ip.locator_match); +} + +int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net = genl_info_net(info); + struct ila_net *ilan = net_generic(net, ila_net_id); + struct rhashtable_iter iter; + struct ila_map *ila; + spinlock_t *lock; + int ret; + + ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter, GFP_KERNEL); + if (ret) + goto done; + + rhashtable_walk_start(&iter); + + for (;;) { + ila = rhashtable_walk_next(&iter); + + if (IS_ERR(ila)) { + if (PTR_ERR(ila) == -EAGAIN) + continue; + ret = PTR_ERR(ila); + goto done; + } else if (!ila) { + break; + } + + lock = lock_from_ila_map(ilan, ila); + + spin_lock(lock); + + ret = rhashtable_remove_fast(&ilan->xlat.rhash_table, + &ila->node, rht_params); + if (!ret) + ila_free_node(ila); + + spin_unlock(lock); + + if (ret) + break; + } + +done: + rhashtable_walk_stop(&iter); + return ret; +} + static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) { if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, From patchwork Mon Dec 11 20:38:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847219 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="cC+0LLqq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZV29vJz9t2M for ; Tue, 12 Dec 2017 07:39:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752585AbdLKUjo (ORCPT ); Mon, 11 Dec 2017 15:39:44 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:39783 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751347AbdLKUjP (ORCPT ); Mon, 11 Dec 2017 15:39:15 -0500 Received: by mail-pf0-f196.google.com with SMTP id l24so12441002pfj.6 for ; Mon, 11 Dec 2017 12:39:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Rf7cnOG6qXh7jXryV7MgaH9v31cHGc7Yvl5tR5Kh+pU=; b=cC+0LLqqb5wj1rf30hGjStZZFkkF+lhHPfr7bt2LA0Rluo3Rdqqu0uHiqh6W23PBiD l5hS7L4eG0JGHm9UejhV7TN8w+DwASWfEpzVQE2X/SMjc5SxDco1OvREm3pRkzey+OMi 59jbPcqy6J+QRYAMajV1EcGUmXOiOT6UhqHq7LfvdfzyATMZdGAQdEnkHpm16YwLjN0F acmGAvEVo7NtiFjKa6OuBO8QvmA+A3gv1a0xwCo5j2T1gTRVlIqGJmu8Mko7KAR7kd+N Vfmp3FqQAUmXIOsNTY7ez/aPi0mTqo3Ddz06R2a/OrjyQFAqf07w9Lv3uBxKLhTCPm5g m4oA== 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:in-reply-to :references; bh=Rf7cnOG6qXh7jXryV7MgaH9v31cHGc7Yvl5tR5Kh+pU=; b=dR7cEnk9Vkqksbl9ekswIfZlWw0rOA67Wdg3hX/ZHvOdkc4V0B15aHRns1vsyWcyjg 1k7mKdBdzUV4UM6j05ikPJ5i31iuRwZQHYYTjn/LMQ3Mo+yhU54L2KUAuUVE1XJhStRX VKoIoeUoTVLt+3XoqZN3YM7dRFOgiLAzm2cegx55+URoqg1xK6vtOYUgoNCrhO8XvGb3 YaAYQ8onUDSR0r0CfBmwPzeEwYt/2Bdwc/iViR6sFMuyONmXoTw69sAnPlUgf5xxDfXP 5OhsC+YTXdazLm8QFmt9cg2U3kaVhNKxbI1Nc2WXFGYbHe13J9zVZHLgVY9Odil5wMy4 cmtQ== X-Gm-Message-State: AKGB3mJwJWRzNM53BloppBOoCwJ8rLsPddz3tu+ftGgVoAXtYz/cSJEZ 6BmR6TrYjvejLerrRQ6PxCI1HA== X-Google-Smtp-Source: ACJfBotMNxV2UJ6rProdgnjPbt/vXi1o8MnIwdi49rqbu4wEBDmYiQFDiO2EuLoQSDpGoF8WOnDCTQ== X-Received: by 10.99.115.79 with SMTP id d15mr1431606pgn.340.1513024754539; Mon, 11 Dec 2017 12:39:14 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:13 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 6/9] net: Generic resolver backend Date: Mon, 11 Dec 2017 12:38:34 -0800 Message-Id: <20171211203837.2540-7-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch implements the backend of a resolver, specifically it provides a means to track unresolved addresses and expire entries based on timeout. The resolver is mostly a frontend to an rhashtable where the key of the table is whatever address type or object is tracked. A resolver instance is created by net_rslv_create. A resolver is destroyed by net_rslv_destroy. There are two functions that are used to manipulate entries in the table: net_rslv_lookup_and_create and net_rslv_resolved. net_rslv_lookup_and_create is called with an unresolved address as the argument. It returns zero on success and an error on failure. When called a lookup is performed to see if an entry for the address is already in the table, if it is then the -EEXISTS is returned. If an entry is not found, one is created and zero is returned. It is expected that when an entry is new the address resolution protocol is initiated (for instance a RTM_ADDR_RESOLVE message may be sent to a userspace daemon as we will do in ILA). If net_rslv_lookup_and_create returns an error other than -EEXIST then presumably the hash table has reached the limit of number of outstanding unresolved addresses, the caller should take appropriate actions to avoid spamming the resolution protocol. net_rslv_resolved is called when resolution is completely (e.g. ILA locator mapping was instantiated for a locator. The entry is removed for the hash table. An argument to net_rslv_create indicates a time for the pending resolution in milliseconds. If the timer fires before resolution then the entry is removed from the table. Subsequently, another attempt to resolve the same address will result in a new entry in the table. There is one callback functions that can be set as arugments in net_rslv_create: - cmp_fn: Compare function for hash table. Arguments are the key and an object in the table. If this is NULL then the default memcmp of rhashtable is used. DOS mitigation is done by limiting the number of entries in the resolver table (the max_size which argument of net_rslv_create) and setting a timeout. If the timeout is set then the maximum rate of new resolution requests is max_table_size / timeout. For instance, with a maximum size of 1000 entries and a timeout of 100 msecs the maximum rate of resolutions requests is 10000/s. Signed-off-by: Tom Herbert --- include/net/resolver.h | 43 ++++++++ net/Kconfig | 1 + net/Makefile | 1 + net/resolver/Kconfig | 7 ++ net/resolver/Makefile | 8 ++ net/resolver/resolver.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 343 insertions(+) create mode 100644 include/net/resolver.h create mode 100644 net/resolver/Kconfig create mode 100644 net/resolver/Makefile create mode 100644 net/resolver/resolver.c diff --git a/include/net/resolver.h b/include/net/resolver.h new file mode 100644 index 000000000000..f38c7e9f1205 --- /dev/null +++ b/include/net/resolver.h @@ -0,0 +1,43 @@ +/* + * Generic network address resovler backend + * + * Copyright (c) 2017 Tom Herbert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __NET_RESOLVER_H +#define __NET_RESOLVER_H + +#include +#include + +struct net_rslv; + +typedef int (*net_rslv_cmpfn)(struct net_rslv *nrslv, const void *key, + const void *object); + +struct net_rslv { + struct rhashtable rhash_table; + struct rhashtable_params params; + net_rslv_cmpfn rslv_cmp; + size_t obj_size; + spinlock_t *locks; + unsigned int locks_mask; + unsigned int hash_rnd; +}; + +struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len, + size_t max_size, net_rslv_cmpfn cmp_fn); + +void net_rslv_destroy(struct net_rslv *nrslv); + +int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key, + unsigned int timeout); + +void net_rslv_resolved(struct net_rslv *nrslv, void *key); + +#endif /* __NET_RESOLVER_H */ diff --git a/net/Kconfig b/net/Kconfig index 9dba2715919d..b1e73325de6a 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -399,6 +399,7 @@ source "net/ceph/Kconfig" source "net/nfc/Kconfig" source "net/psample/Kconfig" source "net/ife/Kconfig" +source "net/resolver/Kconfig" config LWTUNNEL bool "Network light weight tunnels" diff --git a/net/Makefile b/net/Makefile index 14fede520840..6b3b0c5e676a 100644 --- a/net/Makefile +++ b/net/Makefile @@ -86,3 +86,4 @@ obj-y += l3mdev/ endif obj-$(CONFIG_QRTR) += qrtr/ obj-$(CONFIG_NET_NCSI) += ncsi/ +obj-$(CONFIG_NET_RESOLVER) += resolver/ diff --git a/net/resolver/Kconfig b/net/resolver/Kconfig new file mode 100644 index 000000000000..99eff276e0b7 --- /dev/null +++ b/net/resolver/Kconfig @@ -0,0 +1,7 @@ +# +# Net resolver configuration +# + +menuconfig NET_RESOLVER + tristate + default n diff --git a/net/resolver/Makefile b/net/resolver/Makefile new file mode 100644 index 000000000000..fc15e6e5f19f --- /dev/null +++ b/net/resolver/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the generic network resolver +# + +obj-$(CONFIG_NET_RESOLVER) += net_resolver.o + +net_resolver-objs := resolver.o + diff --git a/net/resolver/resolver.c b/net/resolver/resolver.c new file mode 100644 index 000000000000..32a915ed8f93 --- /dev/null +++ b/net/resolver/resolver.c @@ -0,0 +1,283 @@ +/* + * net/core/resolver.c - Generic network address resolver backend + * + * Copyright (c) 2017 Tom Herbert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct net_rslv_ent { + struct rhash_head node; + struct delayed_work timeout_work; + struct net_rslv *nrslv; + + struct rcu_head rcu; + + char object[]; +}; + +static void net_rslv_destroy_rcu(struct rcu_head *head) +{ + struct net_rslv_ent *nrent = container_of(head, struct net_rslv_ent, + rcu); + kfree(nrent); +} + +static void net_rslv_destroy_entry(struct net_rslv *nrslv, + struct net_rslv_ent *nrent) +{ + call_rcu(&nrent->rcu, net_rslv_destroy_rcu); +} + +static inline spinlock_t *net_rslv_get_lock(struct net_rslv *nrslv, void *key) +{ + unsigned int hash; + + /* Use the rhashtable hash function */ + hash = rht_key_get_hash(&nrslv->rhash_table, key, nrslv->params, + nrslv->hash_rnd); + + return &nrslv->locks[hash & nrslv->locks_mask]; +} + +static void net_rslv_delayed_work(struct work_struct *w) +{ + struct delayed_work *delayed_work = to_delayed_work(w); + struct net_rslv_ent *nrent = container_of(delayed_work, + struct net_rslv_ent, + timeout_work); + struct net_rslv *nrslv = nrent->nrslv; + spinlock_t *lock = net_rslv_get_lock(nrslv, nrent->object); + + spin_lock(lock); + rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node, + nrslv->params); + spin_unlock(lock); + + net_rslv_destroy_entry(nrslv, nrent); +} + +static void net_rslv_ent_free_cb(void *ptr, void *arg) +{ + struct net_rslv_ent *nrent = (struct net_rslv_ent *)ptr; + struct net_rslv *nrslv = nrent->nrslv; + + net_rslv_destroy_entry(nrslv, nrent); +} + +void net_rslv_resolved(struct net_rslv *nrslv, void *key) +{ + spinlock_t *lock = net_rslv_get_lock(nrslv, key); + struct net_rslv_ent *nrent; + + rcu_read_lock(); + + nrent = rhashtable_lookup_fast(&nrslv->rhash_table, key, + nrslv->params); + if (!nrent) + goto out; + + /* Cancel timer first */ + cancel_delayed_work_sync(&nrent->timeout_work); + + spin_lock(lock); + + /* Lookup again just in case someone already removed */ + nrent = rhashtable_lookup_fast(&nrslv->rhash_table, key, + nrslv->params); + if (unlikely(!nrent)) { + spin_unlock(lock); + goto out; + } + + rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node, + nrslv->params); + spin_unlock(lock); + + net_rslv_destroy_entry(nrslv, nrent); + +out: + rcu_read_unlock(); +} +EXPORT_SYMBOL_GPL(net_rslv_resolved); + +/* Called with hash bucket lock held */ +static int net_rslv_new_ent(struct net_rslv *nrslv, void *key, + unsigned int timeout) +{ + struct net_rslv_ent *nrent; + int err; + + nrent = kzalloc(sizeof(*nrent) + nrslv->obj_size, GFP_KERNEL); + if (!nrent) + return -ENOMEM; + + /* Key is always at beginning of object data */ + memcpy(nrent->object, key, nrslv->params.key_len); + + nrent->nrslv = nrslv; + + /* Put in hash table */ + err = rhashtable_lookup_insert_fast(&nrslv->rhash_table, + &nrent->node, nrslv->params); + if (err) { + kfree(nrent); + return err; + } + + if (timeout) { + /* Schedule timeout for resolver */ + INIT_DELAYED_WORK(&nrent->timeout_work, net_rslv_delayed_work); + schedule_delayed_work(&nrent->timeout_work, + msecs_to_jiffies(timeout)); + } + + return 0; +} + +int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key, + unsigned int timeout) +{ + spinlock_t *lock = net_rslv_get_lock(nrslv, key); + int ret; + + if (rhashtable_lookup_fast(&nrslv->rhash_table, key, nrslv->params)) + return -EEXIST; + + spin_lock(lock); + + /* Check if someone beat us to the punch */ + if (rhashtable_lookup_fast(&nrslv->rhash_table, key, nrslv->params)) { + spin_unlock(lock); + return -EEXIST; + } + + ret = net_rslv_new_ent(nrslv, key, timeout); + + spin_unlock(lock); + + return ret; +} +EXPORT_SYMBOL_GPL(net_rslv_lookup_and_create); + +static int net_rslv_cmp(struct rhashtable_compare_arg *arg, + const void *obj) +{ + struct net_rslv *nrslv = container_of(arg->ht, struct net_rslv, + rhash_table); + + return nrslv->rslv_cmp(nrslv, arg->key, obj); +} + +#define LOCKS_PER_CPU 10 +#define MAX_LOCKS 1024 + +struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len, + size_t max_size, + net_rslv_cmpfn cmp_fn) +{ + struct net_rslv *nrslv; + int err; + + if (key_len < obj_size) + return ERR_PTR(-EINVAL); + + nrslv = kzalloc(sizeof(*nrslv), GFP_KERNEL); + if (!nrslv) + return ERR_PTR(-ENOMEM); + + err = alloc_bucket_spinlocks(&nrslv->locks, &nrslv->locks_mask, + MAX_LOCKS, LOCKS_PER_CPU, GFP_KERNEL); + if (err) + return ERR_PTR(err); + + nrslv->obj_size = obj_size; + nrslv->rslv_cmp = cmp_fn; + get_random_bytes(&nrslv->hash_rnd, sizeof(nrslv->hash_rnd)); + + nrslv->params.head_offset = offsetof(struct net_rslv_ent, node); + nrslv->params.key_offset = offsetof(struct net_rslv_ent, object); + nrslv->params.key_len = key_len; + nrslv->params.max_size = max_size; + nrslv->params.min_size = 256; + nrslv->params.automatic_shrinking = true; + nrslv->params.obj_cmpfn = cmp_fn ? net_rslv_cmp : NULL; + + rhashtable_init(&nrslv->rhash_table, &nrslv->params); + + return nrslv; +} +EXPORT_SYMBOL_GPL(net_rslv_create); + +static void net_rslv_cancel_all_delayed_work(struct net_rslv *nrslv) +{ + struct rhashtable_iter iter; + struct net_rslv_ent *nrent; + int ret; + + ret = rhashtable_walk_init(&nrslv->rhash_table, &iter, GFP_ATOMIC); + if (WARN_ON(ret)) + return; + + rhashtable_walk_start(&iter); + + for (;;) { + nrent = rhashtable_walk_next(&iter); + + if (IS_ERR(nrent)) { + if (PTR_ERR(nrent) == -EAGAIN) { + /* New table, we're okay to continue */ + continue; + } + ret = PTR_ERR(nrent); + break; + } else if (!nrent) { + break; + } + + cancel_delayed_work_sync(&nrent->timeout_work); + } + + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); +} + +void net_rslv_destroy(struct net_rslv *nrslv) +{ + /* First cancel delayed work in all the nodes. We don't want + * delayed work trying to remove nodes from the table while + * rhashtable_free_and_destroy is walking. + */ + net_rslv_cancel_all_delayed_work(nrslv); + + rhashtable_free_and_destroy(&nrslv->rhash_table, + net_rslv_ent_free_cb, NULL); + + free_bucket_spinlocks(nrslv->locks); + + kfree(nrslv); +} +EXPORT_SYMBOL_GPL(net_rslv_destroy); + +MODULE_AUTHOR("Tom Herbert "); +MODULE_LICENSE("GPL"); + From patchwork Mon Dec 11 20:38:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847216 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="Ke0pct/m"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZ96t1fz9sRm for ; Tue, 12 Dec 2017 07:39:29 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752576AbdLKUj2 (ORCPT ); Mon, 11 Dec 2017 15:39:28 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:39188 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752486AbdLKUjR (ORCPT ); Mon, 11 Dec 2017 15:39:17 -0500 Received: by mail-pg0-f65.google.com with SMTP id w7so11745277pgv.6 for ; Mon, 11 Dec 2017 12:39:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MLYGr/snRyv96mDHSHrynFkIpRK/zKiFZWsImNI3xas=; b=Ke0pct/mcem69vKXkc+7MIbugezLH96XgLM/MjcubwTDYvdxmOLweD89fv5kQka7Xf aINZPveADYyMw8IgrZX/+7GPCAnFNbciqIUViqdqMgijJ9qKyKF6wNET2Luoyad8rwjv qCDdvA0kimPSnstwbTBcO+fiHY6DwCPbqy7mhU91PrqzVFASeXl940i4vs9BO4S/JjQq AWHEx7v7pNyH6+VFuzUFaXjSjMGqg1CCBaHzUF40SKvrPC4bpwE7brJ0OpwCSpx/qjyP yc3zHPVpHyEdBUxn/7aW2llN2drKVovv9mmzpv/ljXR4egSomdlAt6xfcIDRHeeUYaaH tUIA== 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:in-reply-to :references; bh=MLYGr/snRyv96mDHSHrynFkIpRK/zKiFZWsImNI3xas=; b=WjluQkTi2Mr0Rgldm7p7nG2QcBOzQWsdMaAPYcHqg8irkk4TI7eeoIf+2vtAeA4nds 1vE+Sh3oc5SL+XHYxdsQYrYYP0rr95G1HMvuqGlvMmaa0DV4HgGxOvUkvbafYFLu2Qm9 J4L6YYbu+F6lgjLNPvo8DIcH3HhBI+e7uD8yWfADTpPSz9OdMEgNEGj8qloqKMAV6Q+2 lI27XPSZcVC2DpaHe0VvelUM8QZ2YcA8xx5Yfm2PGiZbBTWzs3aNvavtWiIi8ZHtJISu Fqj6eZNG3wHAe0ByZW5Din+yf635CIPAelCi30j0IhPj4H74hhqSJ2qS9bKyhbTxqARt npmQ== X-Gm-Message-State: AKGB3mJwPcr0aBd8121poMdW5eSUaHzs50zVB+yKBapUxkbwt5pKaL7N +54VGoJ384vVWQ0aA7BJbiwcfw== X-Google-Smtp-Source: ACJfBovTggC1kOZ0t2n1q7i+N2n8e/X2Ko5X6wnnpdRDhDTD59ltpewul9Vu+roOnKm/2zQDzPe9ow== X-Received: by 10.84.213.8 with SMTP id f8mr1489473pli.76.1513024757077; Mon, 11 Dec 2017 12:39:17 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:16 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 7/9] ila: Resolver mechanism Date: Mon, 11 Dec 2017 12:38:35 -0800 Message-Id: <20171211203837.2540-8-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement an ILA resolver. This uses LWT to implement the hook to a userspace resolver and tracks pending unresolved address using the backend net resolver. The idea is that the kernel sets an ILA resolver route to the SIR prefix, something like: ip route add 3333::/64 encap ila-resolve \ via 2401:db00:20:911a::27:0 dev eth0 When a packet hits the route the address is looked up in a resolver table. If the entry is created (no entry with the address already exists) then an rtnl message is generated with group RTNLGRP_ILA_NOTIFY and type RTM_ADDR_RESOLVE. A userspace daemon can listen for such messages and perform an ILA resolution protocol to determine the ILA mapping. If the mapping is resolved then a /128 ila encap router is set so that host can perform ILA translation and send directly to destination. Signed-off-by: Tom Herbert --- include/uapi/linux/ila.h | 9 ++ include/uapi/linux/lwtunnel.h | 1 + include/uapi/linux/rtnetlink.h | 8 +- net/core/lwtunnel.c | 2 + net/ipv6/Kconfig | 1 + net/ipv6/ila/Makefile | 2 +- net/ipv6/ila/ila.h | 11 ++ net/ipv6/ila/ila_lwt.c | 8 ++ net/ipv6/ila/ila_main.c | 14 +++ net/ipv6/ila/ila_resolver.c | 244 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 298 insertions(+), 2 deletions(-) create mode 100644 net/ipv6/ila/ila_resolver.c diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h index db45d3e49a12..66557265bf5b 100644 --- a/include/uapi/linux/ila.h +++ b/include/uapi/linux/ila.h @@ -65,4 +65,13 @@ enum { ILA_HOOK_ROUTE_INPUT, }; +enum { + ILA_NOTIFY_ATTR_UNSPEC, + ILA_NOTIFY_ATTR_TIMEOUT, /* u32 */ + + __ILA_NOTIFY_ATTR_MAX, +}; + +#define ILA_NOTIFY_ATTR_MAX (__ILA_NOTIFY_ATTR_MAX - 1) + #endif /* _UAPI_LINUX_ILA_H */ diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h index de696ca12f2c..2eac16f8323f 100644 --- a/include/uapi/linux/lwtunnel.h +++ b/include/uapi/linux/lwtunnel.h @@ -13,6 +13,7 @@ enum lwtunnel_encap_types { LWTUNNEL_ENCAP_SEG6, LWTUNNEL_ENCAP_BPF, LWTUNNEL_ENCAP_SEG6_LOCAL, + LWTUNNEL_ENCAP_ILA_NOTIFY, __LWTUNNEL_ENCAP_MAX, }; diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index d8b5f80c2ea6..8d358a300d8a 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -13,7 +13,8 @@ */ #define RTNL_FAMILY_IPMR 128 #define RTNL_FAMILY_IP6MR 129 -#define RTNL_FAMILY_MAX 129 +#define RTNL_FAMILY_ILA 130 +#define RTNL_FAMILY_MAX 130 /**** * Routing/neighbour discovery messages. @@ -150,6 +151,9 @@ enum { RTM_NEWCACHEREPORT = 96, #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT + RTM_ADDR_RESOLVE = 98, +#define RTM_ADDR_RESOLVE RTM_ADDR_RESOLVE + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -676,6 +680,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV6_MROUTE_R, #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R + RTNLGRP_ILA_NOTIFY, +#define RTNLGRP_ILA_NOTIFY RTNLGRP_ILA_NOTIFY __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index b3f2f77dfe72..16b04d05e9b9 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -46,6 +46,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type) return "BPF"; case LWTUNNEL_ENCAP_SEG6_LOCAL: return "SEG6LOCAL"; + case LWTUNNEL_ENCAP_ILA_NOTIFY: + return "ILA-NOTIFY"; case LWTUNNEL_ENCAP_IP6: case LWTUNNEL_ENCAP_IP: case LWTUNNEL_ENCAP_NONE: diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index ea71e4b0ab7a..5b0a6e1bd7cc 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -110,6 +110,7 @@ config IPV6_ILA tristate "IPv6: Identifier Locator Addressing (ILA)" depends on NETFILTER select LWTUNNEL + select NET_RESOLVER ---help--- Support for IPv6 Identifier Locator Addressing (ILA). diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile index b7739aba6e68..3ec2d65ceee2 100644 --- a/net/ipv6/ila/Makefile +++ b/net/ipv6/ila/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_IPV6_ILA) += ila.o -ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o +ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o ila_resolver.o diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index 1f747bcbec29..02a800c71796 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -112,6 +113,9 @@ struct ila_net { unsigned int locks_mask; bool hooks_registered; } xlat; + struct { + struct net_rslv *nrslv; + } rslv; }; int ila_lwt_init(void); @@ -120,6 +124,11 @@ void ila_lwt_fini(void); int ila_xlat_init_net(struct net *net); void ila_xlat_exit_net(struct net *net); +int ila_rslv_init(void); +void ila_rslv_fini(void); +int ila_rslv_init_net(struct net *net); +void ila_rslv_exit_net(struct net *net); + int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info); int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info); int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info); @@ -132,4 +141,6 @@ extern unsigned int ila_net_id; extern struct genl_family ila_nl_family; +void ila_rslv_resolved(struct ila_net *ilan, struct ila_addr *iaddr); + #endif /* __ILA_H */ diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index 9f1e46a1468e..20dddc7ea8d0 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "ila.h" @@ -250,6 +251,13 @@ static int ila_build_state(struct net *net, struct nlattr *nla, *ts = newts; + if (cfg6->fc_dst_len >= sizeof(struct ila_addr)) { + struct ila_net *ilan = net_generic(net, ila_net_id); + + /* Cancel any pending resolution on this address */ + ila_rslv_resolved(ilan, iaddr); + } + return 0; } diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c index 18fac76b9520..411d3d112157 100644 --- a/net/ipv6/ila/ila_main.c +++ b/net/ipv6/ila/ila_main.c @@ -64,14 +64,21 @@ static __net_init int ila_init_net(struct net *net) if (err) goto ila_xlat_init_fail; + err = ila_rslv_init_net(net); + if (err) + goto resolver_init_fail; + return 0; ila_xlat_init_fail: + ila_xlat_exit_net(net); +resolver_init_fail: return err; } static __net_exit void ila_exit_net(struct net *net) { + ila_rslv_exit_net(net); ila_xlat_exit_net(net); } @@ -98,8 +105,14 @@ static int __init ila_init(void) if (ret) goto fail_lwt; + ret = ila_rslv_init(); + if (ret) + goto fail_rslv; + return 0; +fail_rslv: + ila_lwt_fini(); fail_lwt: genl_unregister_family(&ila_nl_family); register_family_fail: @@ -110,6 +123,7 @@ static int __init ila_init(void) static void __exit ila_fini(void) { + ila_rslv_fini(); ila_lwt_fini(); genl_unregister_family(&ila_nl_family); unregister_pernet_device(&ila_net_ops); diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c new file mode 100644 index 000000000000..8b9a3c5305a4 --- /dev/null +++ b/net/ipv6/ila/ila_resolver.c @@ -0,0 +1,244 @@ +/* + * net/core/ila_resolver.c - ILA address resolver + * + * Copyright (c) 2017 Tom Herbert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ila.h" + +struct ila_notify_params { + unsigned int timeout; +}; + +static inline struct ila_notify_params *ila_notify_params_lwtunnel( + struct lwtunnel_state *lwstate) +{ + return (struct ila_notify_params *)lwstate->data; +} + +static int ila_fill_notify(struct sk_buff *skb, struct in6_addr *addr, + u32 pid, u32 seq, int event, int flags) +{ + struct nlmsghdr *nlh; + struct rtmsg *rtm; + + nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags); + if (!nlh) + return -EMSGSIZE; + + rtm = nlmsg_data(nlh); + rtm->rtm_family = AF_INET6; + rtm->rtm_dst_len = 128; + rtm->rtm_src_len = 0; + rtm->rtm_tos = 0; + rtm->rtm_table = RT6_TABLE_UNSPEC; + rtm->rtm_type = RTN_UNICAST; + rtm->rtm_scope = RT_SCOPE_UNIVERSE; + + if (nla_put_in6_addr(skb, RTA_DST, addr)) { + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; + } + + nlmsg_end(skb, nlh); + return 0; +} + +static size_t ila_rslv_msgsize(void) +{ + size_t len = + NLMSG_ALIGN(sizeof(struct rtmsg)) + + nla_total_size(16) /* RTA_DST */ + ; + + return len; +} + +void ila_rslv_notify(struct net *net, struct sk_buff *skb) +{ + struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct sk_buff *nlskb; + int err = 0; + + /* Send ILA notification to user */ + nlskb = nlmsg_new(ila_rslv_msgsize(), GFP_KERNEL); + if (!nlskb) + goto errout; + + err = ila_fill_notify(nlskb, &ip6h->daddr, 0, 0, RTM_ADDR_RESOLVE, + NLM_F_MULTI); + if (err < 0) { + WARN_ON(err == -EMSGSIZE); + kfree_skb(nlskb); + goto errout; + } + rtnl_notify(nlskb, net, 0, RTNLGRP_ILA_NOTIFY, NULL, GFP_ATOMIC); + return; + +errout: + if (err < 0) + rtnl_set_sk_err(net, RTNLGRP_ILA_NOTIFY, err); +} + +static int ila_rslv_output(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + struct ila_net *ilan = net_generic(net, ila_net_id); + struct dst_entry *dst = skb_dst(skb); + struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct ila_notify_params *p; + + p = ila_notify_params_lwtunnel(dst->lwtstate); + + /* Net resolver create function returns zero only when a new + * entry is create (returns -EEXIST is entry already in table).. + */ + if (!net_rslv_lookup_and_create(ilan->rslv.nrslv, &ip6h->daddr, + p->timeout)) + ila_rslv_notify(net, skb); + + return dst->lwtstate->orig_output(net, sk, skb); +} + +void ila_rslv_resolved(struct ila_net *ilan, struct ila_addr *iaddr) +{ + if (ilan->rslv.nrslv) + net_rslv_resolved(ilan->rslv.nrslv, iaddr); +} + +static int ila_rslv_input(struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + return dst->lwtstate->orig_input(skb); +} + +static const struct nla_policy ila_notify_nl_policy[ILA_NOTIFY_ATTR_MAX + 1] = { + [ILA_NOTIFY_ATTR_TIMEOUT] = { .type = NLA_U32, }, +}; + +static int ila_rslv_build_state(struct net *net, struct nlattr *nla, + unsigned int family, const void *cfg, + struct lwtunnel_state **ts, + struct netlink_ext_ack *extack) +{ + struct ila_notify_params *p; + struct nlattr *tb[ILA_NOTIFY_ATTR_MAX + 1]; + struct lwtunnel_state *newts; + size_t encap_len = sizeof(*p); + int ret; + + if (family != AF_INET6) + return -EINVAL; + + ret = nla_parse_nested(tb, ILA_NOTIFY_ATTR_MAX, nla, + ila_notify_nl_policy, extack); + + if (ret < 0) + return ret; + + newts = lwtunnel_state_alloc(encap_len); + if (!newts) + return -ENOMEM; + + newts->type = LWTUNNEL_ENCAP_ILA_NOTIFY; + newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT | + LWTUNNEL_STATE_INPUT_REDIRECT; + + p = ila_notify_params_lwtunnel(newts); + + if (tb[ILA_NOTIFY_ATTR_TIMEOUT]) + p->timeout = msecs_to_jiffies(nla_get_u32( + tb[ILA_NOTIFY_ATTR_TIMEOUT])); + + *ts = newts; + + return 0; +} + +static int ila_rslv_fill_encap_info(struct sk_buff *skb, + struct lwtunnel_state *lwtstate) +{ + struct ila_notify_params *p = ila_notify_params_lwtunnel(lwtstate); + + if (nla_put_u32(skb, ILA_NOTIFY_ATTR_TIMEOUT, + (__force u32)jiffies_to_msecs(p->timeout))) + goto nla_put_failure; + + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + +static int ila_rslv_nlsize(struct lwtunnel_state *lwtstate) +{ + return nla_total_size(sizeof(u32)) + /* ILA_NOTIFY_ATTR_TIMEOUT */ + 0; +} + +static int ila_rslv_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) +{ + return 0; +} + +static const struct lwtunnel_encap_ops ila_rslv_ops = { + .build_state = ila_rslv_build_state, + .output = ila_rslv_output, + .input = ila_rslv_input, + .fill_encap = ila_rslv_fill_encap_info, + .get_encap_size = ila_rslv_nlsize, + .cmp_encap = ila_rslv_cmp, +}; + +#define ILA_MAX_SIZE 8192 + +int ila_rslv_init_net(struct net *net) +{ + struct ila_net *ilan = net_generic(net, ila_net_id); + struct net_rslv *nrslv; + + nrslv = net_rslv_create(sizeof(struct ila_addr), + sizeof(struct ila_addr), ILA_MAX_SIZE, NULL); + + if (IS_ERR(nrslv)) + return PTR_ERR(nrslv); + + ilan->rslv.nrslv = nrslv; + + return 0; +} + +void ila_rslv_exit_net(struct net *net) +{ + struct ila_net *ilan = net_generic(net, ila_net_id); + + if (ilan->rslv.nrslv) + net_rslv_destroy(ilan->rslv.nrslv); +} + +int ila_rslv_init(void) +{ + return lwtunnel_encap_add_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY); +} + +void ila_rslv_fini(void) +{ + lwtunnel_encap_del_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY); +} From patchwork Mon Dec 11 20:38:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847218 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="Ydp3F3/0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZN5H8lz9t2M for ; Tue, 12 Dec 2017 07:39:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752582AbdLKUjj (ORCPT ); Mon, 11 Dec 2017 15:39:39 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:34339 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752525AbdLKUjU (ORCPT ); Mon, 11 Dec 2017 15:39:20 -0500 Received: by mail-pf0-f193.google.com with SMTP id a90so12445273pfk.1 for ; Mon, 11 Dec 2017 12:39:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mVNpAdTpPd+Tws3/SM+yeEqvVKbvongI0b781kbDaB4=; b=Ydp3F3/0+5t+ERIS2BKXL/KxN2OsSVA+roeOW5vLRyPS0+nOB2GR22IQ3yt/Hwmobf 21nUaw6xgozNzi8t7V15n0RiDAktV9kztkGY3eykKw1sWXPZ31oE0aLDzpU4A3BQahDA sOJ2cSbwpQ0r3eA48pr9U56iN1OWXnNUBpgyZ9HINQ068e0eCy9aKgxw+MypR/U8HzHf MSni3my04p/dMka4nYnBAvP8gssm3X+Qh+5FlMlf7UtgSHg3620pklvaW5e7yZ/SgPfQ ue2imnBITlqVxKma2e+NnZQ5VqJYrFEP37J56h2xkGTBqmb70YcUcCmJWUHhkCbKxgvW 8wSA== 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:in-reply-to :references; bh=mVNpAdTpPd+Tws3/SM+yeEqvVKbvongI0b781kbDaB4=; b=g5UZzaT+GrDACgtKZFYTd0hezPzcWwphiqXtXnDKsDgBvBHBLzJLRShkYlP1P1nEEz P5Kk7yRaQOcQ1H31dXYEzK6yI03Ya6Z2IjyLDoDnK1Ft7SvN2OvgFB/EhOUZu0WUba2I ASf8WnEJsTfbG8pY1VEc9j/peU5IGNCZ397DimhmARJ2NZuJMPnjoWMDeC4DC1itmmTr B9VsmORCURfx947aARtNqfUf1l5e6lRHXAf/+6FUY9X1sjMV7TpgUQqmGB2RAkyLipw9 B/X+SyT5K01XlZBQ/md//jGmdxTWBqqiwqpub5hXjritEShUN2ugFX5RcqqZDJw0IgJM yqwQ== X-Gm-Message-State: AKGB3mJffpkn2AD/IhLvVS9NFeE3PAjbWa21nOA+XUpV8jOzQFloDBHa /txiGyk9TsM0LXEGgIAQ0EWQRA== X-Google-Smtp-Source: ACJfBotxx/ZI9m6EoJFiHgt6K0BnipvuZq9MEqvJy+elQXdU6w2iA98SRj9p0npiBmVJLWxIvrFr5g== X-Received: by 10.159.231.24 with SMTP id w24mr1487113plq.272.1513024759789; Mon, 11 Dec 2017 12:39:19 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:18 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 8/9] resolver: add netlink control Date: Mon, 11 Dec 2017 12:38:36 -0800 Message-Id: <20171211203837.2540-9-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add interfaces into resolver backend that can be used to provide netlink. The interface includes fucntions to support the common netlink commands (get, add, list, delete, and flush). The frontend that is using the resolver implements the actual netlink interfaces for its service and calls the backend functions to provide netlink for the resolver. Signed-off-by: Tom Herbert --- include/net/resolver.h | 26 +++- net/ipv6/ila/ila_resolver.c | 3 +- net/resolver/resolver.c | 280 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 305 insertions(+), 4 deletions(-) diff --git a/include/net/resolver.h b/include/net/resolver.h index f38c7e9f1205..307938ad91a6 100644 --- a/include/net/resolver.h +++ b/include/net/resolver.h @@ -14,12 +14,21 @@ #include #include +#include +#include struct net_rslv; typedef int (*net_rslv_cmpfn)(struct net_rslv *nrslv, const void *key, const void *object); +struct net_rslv_netlink_map { + int dst_attr; + int timo_attr; + int get_cmd; + struct genl_family *genl_family; +}; + struct net_rslv { struct rhashtable rhash_table; struct rhashtable_params params; @@ -28,10 +37,12 @@ struct net_rslv { spinlock_t *locks; unsigned int locks_mask; unsigned int hash_rnd; + const struct net_rslv_netlink_map *nlmap; }; struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len, - size_t max_size, net_rslv_cmpfn cmp_fn); + size_t max_size, net_rslv_cmpfn cmp_fn, + const struct net_rslv_netlink_map *nlmap); void net_rslv_destroy(struct net_rslv *nrslv); @@ -40,4 +51,17 @@ int net_rslv_lookup_and_create(struct net_rslv *nrslv, void *key, void net_rslv_resolved(struct net_rslv *nrslv, void *key); +int net_rslv_nl_cmd_add(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info); +int net_rslv_nl_cmd_del(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info); +int net_rslv_nl_cmd_get(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info); +int net_rslv_nl_cmd_flush(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info); +int net_rslv_nl_dump_start(struct net_rslv *nrslv, struct netlink_callback *cb); +int net_rslv_nl_dump_done(struct net_rslv *nrslv, struct netlink_callback *cb); +int net_rslv_nl_dump(struct net_rslv *nrslv, struct sk_buff *skb, + struct netlink_callback *cb); + #endif /* __NET_RESOLVER_H */ diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c index 8b9a3c5305a4..2aebc0526221 100644 --- a/net/ipv6/ila/ila_resolver.c +++ b/net/ipv6/ila/ila_resolver.c @@ -215,7 +215,8 @@ int ila_rslv_init_net(struct net *net) struct net_rslv *nrslv; nrslv = net_rslv_create(sizeof(struct ila_addr), - sizeof(struct ila_addr), ILA_MAX_SIZE, NULL); + sizeof(struct ila_addr), ILA_MAX_SIZE, NULL, + NULL); if (IS_ERR(nrslv)) return PTR_ERR(nrslv); diff --git a/net/resolver/resolver.c b/net/resolver/resolver.c index 32a915ed8f93..e2496b0bf852 100644 --- a/net/resolver/resolver.c +++ b/net/resolver/resolver.c @@ -19,11 +19,13 @@ #include #include #include +#include #include #include #include #include #include +#include struct net_rslv_ent { struct rhash_head node; @@ -192,8 +194,8 @@ static int net_rslv_cmp(struct rhashtable_compare_arg *arg, #define MAX_LOCKS 1024 struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len, - size_t max_size, - net_rslv_cmpfn cmp_fn) + size_t max_size, net_rslv_cmpfn cmp_fn, + const struct net_rslv_netlink_map *nlmap) { struct net_rslv *nrslv; int err; @@ -212,6 +214,7 @@ struct net_rslv *net_rslv_create(size_t obj_size, size_t key_len, nrslv->obj_size = obj_size; nrslv->rslv_cmp = cmp_fn; + nrslv->nlmap = nlmap; get_random_bytes(&nrslv->hash_rnd, sizeof(nrslv->hash_rnd)); nrslv->params.head_offset = offsetof(struct net_rslv_ent, node); @@ -278,6 +281,279 @@ void net_rslv_destroy(struct net_rslv *nrslv) } EXPORT_SYMBOL_GPL(net_rslv_destroy); +/* Netlink access utility functions and structures. */ + +struct net_rslv_params { + unsigned int timeout; + __u8 key[MAX_ADDR_LEN]; + size_t keysize; +}; + +static int parse_nl_config(struct net_rslv *nrslv, struct genl_info *info, + struct net_rslv_params *np) +{ + if (!info->attrs[nrslv->nlmap->dst_attr] || + nla_len(info->attrs[nrslv->nlmap->dst_attr]) != + nrslv->params.key_len) + return -EINVAL; + + memset(np, 0, sizeof(*np)); + + memcpy(np->key, nla_data(info->attrs[nrslv->nlmap->dst_attr]), + nla_len(info->attrs[nrslv->nlmap->dst_attr])); + + if (info->attrs[nrslv->nlmap->timo_attr]) + np->timeout = nla_get_u32(info->attrs[nrslv->nlmap->timo_attr]); + + return 0; +} + +int net_rslv_nl_cmd_add(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info) +{ + struct net_rslv_params p; + int err; + + err = parse_nl_config(nrslv, info, &p); + if (err) + return err; + + return net_rslv_lookup_and_create(nrslv, p.key, p.timeout); +} +EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_add); + +int net_rslv_nl_cmd_del(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info) +{ + struct net_rslv_params p; + int err; + + err = parse_nl_config(nrslv, info, &p); + if (err) + return err; + + /* Treat removal as being resolved */ + net_rslv_resolved(nrslv, p.key); + + return 0; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_del); + +static int net_rslv_fill_info(struct net_rslv *nrslv, + struct net_rslv_ent *nrent, + struct sk_buff *msg) +{ + int from_now = 0; + + if (delayed_work_pending(&nrent->timeout_work)) { + unsigned long expires = nrent->timeout_work.timer.expires; + + from_now = jiffies_to_msecs(expires - jiffies); + + if (from_now < 0) + from_now = 0; + } + + if (nla_put(msg, nrslv->nlmap->dst_attr, nrslv->params.key_len, + nrent->object) || + nla_put_s32(msg, nrslv->nlmap->timo_attr, from_now)) + return -1; + + return 0; +} + +static int net_rslv_dump_info(struct net_rslv *nrslv, + struct net_rslv_ent *nrent, u32 portid, u32 seq, + u32 flags, struct sk_buff *skb, u8 cmd) +{ + void *hdr; + + hdr = genlmsg_put(skb, portid, seq, nrslv->nlmap->genl_family, flags, + cmd); + if (!hdr) + return -ENOMEM; + + if (net_rslv_fill_info(nrslv, nrent, skb) < 0) + goto nla_put_failure; + + genlmsg_end(skb, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return -EMSGSIZE; +} + +int net_rslv_nl_cmd_get(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info) +{ + struct net_rslv_ent *nrent; + struct net_rslv_params p; + struct sk_buff *msg; + int err; + + err = parse_nl_config(nrslv, info, &p); + if (err) + return err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + rcu_read_lock(); + + nrent = rhashtable_lookup_fast(&nrslv->rhash_table, p.key, + nrslv->params); + if (nrent) + err = net_rslv_dump_info(nrslv, nrent, info->snd_portid, + info->snd_seq, 0, msg, + info->genlhdr->cmd); + + rcu_read_unlock(); + + if (err < 0) + goto out_free; + + return genlmsg_reply(msg, info); + +out_free: + nlmsg_free(msg); + return err; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_get); + +int net_rslv_nl_cmd_flush(struct net_rslv *nrslv, struct sk_buff *skb, + struct genl_info *info) +{ + struct rhashtable_iter iter; + struct net_rslv_ent *nrent; + spinlock_t *lock; + int ret; + + ret = rhashtable_walk_init(&nrslv->rhash_table, &iter, GFP_KERNEL); + if (ret) + return ret; + + rhashtable_walk_start(&iter); + + for (;;) { + nrent = rhashtable_walk_next(&iter); + + if (IS_ERR(nrent)) { + if (PTR_ERR(nrent) == -EAGAIN) { + /* New table, we're okay to continue */ + continue; + } + ret = PTR_ERR(nrent); + break; + } else if (!nrent) { + break; + } + + lock = net_rslv_get_lock(nrslv, nrent->object); + + spin_lock(lock); + ret = rhashtable_remove_fast(&nrslv->rhash_table, &nrent->node, + nrslv->params); + spin_unlock(lock); + + if (ret) + break; + } + + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); + + return ret; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_cmd_flush); + +int net_rslv_nl_dump_start(struct net_rslv *nrslv, struct netlink_callback *cb) +{ + struct rhashtable_iter *iter; + int ret; + + iter = kmalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + return -ENOMEM; + + ret = rhashtable_walk_init(&nrslv->rhash_table, iter, GFP_KERNEL); + if (ret) { + kfree(iter); + return ret; + } + + cb->args[0] = (long)iter; + + return 0; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_dump_start); + +int net_rslv_nl_dump_done(struct net_rslv *nrslv, struct netlink_callback *cb) +{ + struct rhashtable_iter *iter = + (struct rhashtable_iter *)cb->args[0]; + + rhashtable_walk_exit(iter); + + kfree(iter); + + return 0; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_dump_done); + +int net_rslv_nl_dump(struct net_rslv *nrslv, struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct rhashtable_iter *iter = + (struct rhashtable_iter *)cb->args[0]; + struct net_rslv_ent *nrent; + int ret; + + ret = rhashtable_walk_start_check(iter); + if (ret) + goto done; + + /* Get first entty */ + nrent = rhashtable_walk_peek(iter); + + for (;;) { + if (IS_ERR(nrent)) { + ret = PTR_ERR(nrent); + if (ret == -EAGAIN) { + /* Table has changed and iter has reset. Return + * -EAGAIN to the application even if we have + * written data to the skb. The application + * needs to deal with this. + */ + + goto done; + } + break; + } else if (!nrent) { + break; + } + + ret = net_rslv_dump_info(nrslv, nrent, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, + NLM_F_MULTI, skb, + nrslv->nlmap->get_cmd); + if (ret) + break; + + /* Get next and advance the iter */ + nrent = rhashtable_walk_next(iter); + } + + ret = (skb->len ? : ret); + +done: + rhashtable_walk_stop(iter); + return ret; +} +EXPORT_SYMBOL_GPL(net_rslv_nl_dump); + MODULE_AUTHOR("Tom Herbert "); MODULE_LICENSE("GPL"); From patchwork Mon Dec 11 20:38:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 847217 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=quantonium-net.20150623.gappssmtp.com header.i=@quantonium-net.20150623.gappssmtp.com header.b="k1qt0Isc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ywZZL1KyRz9t2M for ; Tue, 12 Dec 2017 07:39:38 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752068AbdLKUjf (ORCPT ); Mon, 11 Dec 2017 15:39:35 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:40185 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752572AbdLKUjW (ORCPT ); Mon, 11 Dec 2017 15:39:22 -0500 Received: by mail-pf0-f196.google.com with SMTP id v26so12434419pfl.7 for ; Mon, 11 Dec 2017 12:39:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantonium-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DUAtsytQJxmhKDnbrsuQsKyhFpHcBUbdTzANyJConOQ=; b=k1qt0IscE6Ozb5xCyvozGYRYD7miEMnjRflhuEKJqyNN1zNl34U/1PnXSN0VK4XHii fsyxr9IqwtimDgQB1HOf+F3TygGWABWYTKMxUcrQNLCFZ0/xRo8tLnqnubmJHmDVSmne Mdex0Gpc+W7qQ8hnJrwxkXdZ8iGUAMexBDS+sYS8DhqCRzq20iSmwTha84PZRCNwIuro oGpYE3hHz9XfVv8OQS3Nf61guQeG07afbG1oQGP10Z/ZqgTqYN7GS8mqSC1h/oPNClNx ns2+XW2jPECN7QViNroNcTW2rdvRmRzSid4f6VJdqNKq4lrkzhs5q+EsJfNSeYob18Gh xv7g== 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:in-reply-to :references; bh=DUAtsytQJxmhKDnbrsuQsKyhFpHcBUbdTzANyJConOQ=; b=gWS1koAD4Zx6szmVKFqDger7n6SQPvDjuSaz7okxp7TTVU8rKGdHceyRJ482rb1VtO UiCci8YmuF6aEP0Jo/HKhzukzDfyBmdjjk0B4hAiWvNH+AEPsYKyyqOmVFKX6u+q1qbo qHxF6nhpPRPDRjD8Hpg/rjAwUTjjRWMceAE42Yr3oCy9a8PMuewXHbjNCBTarnOYgAsC KMxU7Z9rJpcqnInMSSrX30K4Q0ndSgWCROO5GDX5v1ZHVtTcopyDNrIeR3ViZex9oilQ Yn5ImCyEBLlw5GdnYayW0cKuydAK4c2nY6VAJXcqk4hghAg+Rxqn3O2nOWXbJ9PFEeur tBCg== X-Gm-Message-State: AKGB3mJGVi/uOw89aUY957sSVzHrirCzRuabtTYHYZ0q3l0hGj2dwsxb bsLERMlmw8B3X+0RHBqLjuSDiCdm X-Google-Smtp-Source: ACJfBosYqheK3ZOSlYRWYchXoskM8XLIwmoEfQGaiz9EXSEjUvf08AAuOBNUSGEUga8x1IIg9iaXmg== X-Received: by 10.84.236.7 with SMTP id q7mr1489585plk.401.1513024762247; Mon, 11 Dec 2017 12:39:22 -0800 (PST) Received: from localhost.localdomain (67-207-98-108.static.wiline.com. [67.207.98.108]) by smtp.gmail.com with ESMTPSA id t6sm26426790pfl.76.2017.12.11.12.39.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 12:39:21 -0800 (PST) From: Tom Herbert To: davem@davemloft.net Cc: netdev@vger.kernel.org, roopa@cumulusnetworks.com, rohit@quantonium.net, Tom Herbert Subject: [PATCH v3 net-next 9/9] ila: add netlink control ILA resolver Date: Mon, 11 Dec 2017 12:38:37 -0800 Message-Id: <20171211203837.2540-10-tom@quantonium.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171211203837.2540-1-tom@quantonium.net> References: <20171211203837.2540-1-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a netlink family to processe netlinkf for the ILA resolver. This calls the net resolver netlink functions. Signed-off-by: Tom Herbert --- include/uapi/linux/ila.h | 11 ++++++++ net/ipv6/ila/ila.h | 8 ++++++ net/ipv6/ila/ila_main.c | 26 ++++++++++++++++++ net/ipv6/ila/ila_resolver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h index 66557265bf5b..2481dab25d57 100644 --- a/include/uapi/linux/ila.h +++ b/include/uapi/linux/ila.h @@ -19,6 +19,8 @@ enum { ILA_ATTR_CSUM_MODE, /* u8 */ ILA_ATTR_IDENT_TYPE, /* u8 */ ILA_ATTR_HOOK_TYPE, /* u8 */ + ILA_RSLV_ATTR_DST, /* IPv6 address */ + ILA_RSLV_ATTR_TIMEOUT, /* u32 */ __ILA_ATTR_MAX, }; @@ -31,6 +33,10 @@ enum { ILA_CMD_DEL, ILA_CMD_GET, ILA_CMD_FLUSH, + ILA_RSLV_CMD_ADD, + ILA_RSLV_CMD_DEL, + ILA_RSLV_CMD_GET, + ILA_RSLV_CMD_FLUSH, __ILA_CMD_MAX, }; @@ -68,10 +74,15 @@ enum { enum { ILA_NOTIFY_ATTR_UNSPEC, ILA_NOTIFY_ATTR_TIMEOUT, /* u32 */ + ILA_NOTIFY_ATTR_DST, /* Binary address */ __ILA_NOTIFY_ATTR_MAX, }; #define ILA_NOTIFY_ATTR_MAX (__ILA_NOTIFY_ATTR_MAX - 1) +/* NETLINK_GENERIC related info */ +#define ILA_RSLV_GENL_NAME "ila-rslv" +#define ILA_RSLV_GENL_VERSION 0x1 + #endif /* _UAPI_LINUX_ILA_H */ diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h index 02a800c71796..0aa99e359a38 100644 --- a/net/ipv6/ila/ila.h +++ b/net/ipv6/ila/ila.h @@ -137,6 +137,14 @@ int ila_xlat_nl_dump_start(struct netlink_callback *cb); int ila_xlat_nl_dump_done(struct netlink_callback *cb); int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb); +int ila_rslv_nl_cmd_add(struct sk_buff *skb, struct genl_info *info); +int ila_rslv_nl_cmd_del(struct sk_buff *skb, struct genl_info *info); +int ila_rslv_nl_cmd_get(struct sk_buff *skb, struct genl_info *info); +int ila_rslv_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info); +int ila_rslv_nl_dump_start(struct netlink_callback *cb); +int ila_rslv_nl_dump_done(struct netlink_callback *cb); +int ila_rslv_nl_dump(struct sk_buff *skb, struct netlink_callback *cb); + extern unsigned int ila_net_id; extern struct genl_family ila_nl_family; diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c index 411d3d112157..8589d422568b 100644 --- a/net/ipv6/ila/ila_main.c +++ b/net/ipv6/ila/ila_main.c @@ -40,6 +40,32 @@ static const struct genl_ops ila_nl_ops[] = { .done = ila_xlat_nl_dump_done, .policy = ila_nl_policy, }, + { + .cmd = ILA_RSLV_CMD_ADD, + .doit = ila_rslv_nl_cmd_add, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = ILA_RSLV_CMD_DEL, + .doit = ila_rslv_nl_cmd_del, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = ILA_RSLV_CMD_FLUSH, + .doit = ila_rslv_nl_cmd_flush, + .policy = ila_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = ILA_RSLV_CMD_GET, + .doit = ila_rslv_nl_cmd_get, + .start = ila_rslv_nl_dump_start, + .dumpit = ila_rslv_nl_dump, + .done = ila_rslv_nl_dump_done, + .policy = ila_nl_policy, + }, }; unsigned int ila_net_id; diff --git a/net/ipv6/ila/ila_resolver.c b/net/ipv6/ila/ila_resolver.c index 2aebc0526221..3278e93bb799 100644 --- a/net/ipv6/ila/ila_resolver.c +++ b/net/ipv6/ila/ila_resolver.c @@ -209,6 +209,13 @@ static const struct lwtunnel_encap_ops ila_rslv_ops = { #define ILA_MAX_SIZE 8192 +static struct net_rslv_netlink_map ila_netlink_map = { + .dst_attr = ILA_RSLV_ATTR_DST, + .timo_attr = ILA_RSLV_ATTR_TIMEOUT, + .get_cmd = ILA_RSLV_CMD_GET, + .genl_family = &ila_nl_family, +}; + int ila_rslv_init_net(struct net *net) { struct ila_net *ilan = net_generic(net, ila_net_id); @@ -216,7 +223,7 @@ int ila_rslv_init_net(struct net *net) nrslv = net_rslv_create(sizeof(struct ila_addr), sizeof(struct ila_addr), ILA_MAX_SIZE, NULL, - NULL); + &ila_netlink_map); if (IS_ERR(nrslv)) return PTR_ERR(nrslv); @@ -234,6 +241,64 @@ void ila_rslv_exit_net(struct net *net) net_rslv_destroy(ilan->rslv.nrslv); } +/* Netlink access */ + +int ila_rslv_nl_cmd_add(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net = sock_net(skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_cmd_add(ilan->rslv.nrslv, skb, info); +} + +int ila_rslv_nl_cmd_del(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net = sock_net(skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_cmd_del(ilan->rslv.nrslv, skb, info); +} + +int ila_rslv_nl_cmd_get(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net = sock_net(skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_cmd_get(ilan->rslv.nrslv, skb, info); +} + +int ila_rslv_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info) +{ + struct net *net = sock_net(skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_cmd_flush(ilan->rslv.nrslv, skb, info); +} + +int ila_rslv_nl_dump_start(struct netlink_callback *cb) +{ + struct net *net = sock_net(cb->skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_dump_start(ilan->rslv.nrslv, cb); +} + +int ila_rslv_nl_dump_done(struct netlink_callback *cb) +{ + struct net *net = sock_net(cb->skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_dump_done(ilan->rslv.nrslv, cb); +} + +int ila_rslv_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net *net = sock_net(cb->skb->sk); + struct ila_net *ilan = net_generic(net, ila_net_id); + + return net_rslv_nl_dump(ilan->rslv.nrslv, skb, cb); +} + int ila_rslv_init(void) { return lwtunnel_encap_add_ops(&ila_rslv_ops, LWTUNNEL_ENCAP_ILA_NOTIFY);