From patchwork Thu Oct 28 06:18:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 12589371 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7910EC433F5 for ; Thu, 28 Oct 2021 06:18:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5CAFB610D2 for ; Thu, 28 Oct 2021 06:18:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229784AbhJ1GVO (ORCPT ); Thu, 28 Oct 2021 02:21:14 -0400 Received: from pi.codeconstruct.com.au ([203.29.241.158]:42796 "EHLO codeconstruct.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229586AbhJ1GVN (ORCPT ); Thu, 28 Oct 2021 02:21:13 -0400 Received: by codeconstruct.com.au (Postfix, from userid 10000) id C2A562022E; Thu, 28 Oct 2021 14:18:44 +0800 (AWST) From: Jeremy Kerr To: netdev@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Matt Johnston , Andrew Jeffery Subject: [PATCH net-next 1/3] mctp: Return new key from mctp_alloc_local_tag Date: Thu, 28 Oct 2021 14:18:31 +0800 Message-Id: <20211028061833.2390354-1-jk@codeconstruct.com.au> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org In a future change, we will want the key available for future use after allocating a new tag. This change returns the key from mctp_alloc_local_tag, rather than just key->tag. Signed-off-by: Jeremy Kerr --- net/mctp/route.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/net/mctp/route.c b/net/mctp/route.c index c23ab3547ee5..82cc10a2fb0c 100644 --- a/net/mctp/route.c +++ b/net/mctp/route.c @@ -532,14 +532,14 @@ static void mctp_reserve_tag(struct net *net, struct mctp_sk_key *key, /* Allocate a locally-owned tag value for (saddr, daddr), and reserve * it for the socket msk */ -static int mctp_alloc_local_tag(struct mctp_sock *msk, - mctp_eid_t saddr, mctp_eid_t daddr, u8 *tagp) +static struct mctp_sk_key *mctp_alloc_local_tag(struct mctp_sock *msk, + mctp_eid_t saddr, + mctp_eid_t daddr, u8 *tagp) { struct net *net = sock_net(&msk->sk); struct netns_mctp *mns = &net->mctp; struct mctp_sk_key *key, *tmp; unsigned long flags; - int rc = -EAGAIN; u8 tagbits; /* for NULL destination EIDs, we may get a response from any peer */ @@ -549,7 +549,7 @@ static int mctp_alloc_local_tag(struct mctp_sock *msk, /* be optimistic, alloc now */ key = mctp_key_alloc(msk, saddr, daddr, 0, GFP_KERNEL); if (!key) - return -ENOMEM; + return ERR_PTR(-ENOMEM); /* 8 possible tag values */ tagbits = 0xff; @@ -591,18 +591,16 @@ static int mctp_alloc_local_tag(struct mctp_sock *msk, trace_mctp_key_acquire(key); *tagp = key->tag; - /* done with the key in this scope */ - mctp_key_unref(key); - key = NULL; - rc = 0; } spin_unlock_irqrestore(&mns->keys_lock, flags); - if (!tagbits) + if (!tagbits) { kfree(key); + return ERR_PTR(-EBUSY); + } - return rc; + return key; } /* routing lookups */ @@ -740,6 +738,7 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct mctp_skb_cb *cb = mctp_cb(skb); struct mctp_route tmp_rt; + struct mctp_sk_key *key; struct net_device *dev; struct mctp_hdr *hdr; unsigned long flags; @@ -799,11 +798,16 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, goto out_release; if (req_tag & MCTP_HDR_FLAG_TO) { - rc = mctp_alloc_local_tag(msk, saddr, daddr, &tag); - if (rc) + key = mctp_alloc_local_tag(msk, saddr, daddr, &tag); + if (IS_ERR(key)) { + rc = PTR_ERR(key); goto out_release; + } + /* done with the key in this scope */ + mctp_key_unref(key); tag |= MCTP_HDR_FLAG_TO; } else { + key = NULL; tag = req_tag; } From patchwork Thu Oct 28 06:18:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 12589369 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0366AC433EF for ; Thu, 28 Oct 2021 06:18:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D55F0610CA for ; Thu, 28 Oct 2021 06:18:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229762AbhJ1GVO (ORCPT ); Thu, 28 Oct 2021 02:21:14 -0400 Received: from pi.codeconstruct.com.au ([203.29.241.158]:42808 "EHLO codeconstruct.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229694AbhJ1GVN (ORCPT ); Thu, 28 Oct 2021 02:21:13 -0400 Received: by codeconstruct.com.au (Postfix, from userid 10000) id 626772028B; Thu, 28 Oct 2021 14:18:45 +0800 (AWST) From: Jeremy Kerr To: netdev@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Matt Johnston , Andrew Jeffery Subject: [PATCH net-next 2/3] mctp: Add flow extension to skb Date: Thu, 28 Oct 2021 14:18:32 +0800 Message-Id: <20211028061833.2390354-2-jk@codeconstruct.com.au> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211028061833.2390354-1-jk@codeconstruct.com.au> References: <20211028061833.2390354-1-jk@codeconstruct.com.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This change adds a new skb extension for MCTP, to represent a request/response flow. The intention is to use this in a later change to allow i2c controllers to correctly configure a multiplexer over a flow. Since we have a cleanup function in the core path (if an extension is present), we'll need to make CONFIG_MCTP a bool, rather than a tristate. Signed-off-by: Jeremy Kerr Reported-by: kernel test robot Reported-by: kernel test robot --- include/linux/skbuff.h | 3 +++ include/net/mctp.h | 7 +++++++ net/core/skbuff.c | 19 +++++++++++++++++++ net/mctp/Kconfig | 6 +++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cb96f1e6460c..0bd6520329f6 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -4243,6 +4243,9 @@ enum skb_ext_id { #endif #if IS_ENABLED(CONFIG_MPTCP) SKB_EXT_MPTCP, +#endif +#if IS_ENABLED(CONFIG_MCTP_FLOWS) + SKB_EXT_MCTP, #endif SKB_EXT_NUM, /* must be last */ }; diff --git a/include/net/mctp.h b/include/net/mctp.h index 23bec708f4c7..7a5ba801703c 100644 --- a/include/net/mctp.h +++ b/include/net/mctp.h @@ -189,6 +189,13 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb) return (void *)(skb->cb); } +/* If CONFIG_MCTP_FLOWS, we may add one of these as a SKB extension, + * indicating the flow to the device driver. + */ +struct mctp_flow { + struct mctp_sk_key *key; +}; + /* Route definition. * * These are held in the pernet->mctp.routes list, with RCU protection for diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 74601bbc56ac..2505e1845f57 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -4430,6 +4431,9 @@ static const u8 skb_ext_type_len[] = { #if IS_ENABLED(CONFIG_MPTCP) [SKB_EXT_MPTCP] = SKB_EXT_CHUNKSIZEOF(struct mptcp_ext), #endif +#if IS_ENABLED(CONFIG_MCTP) + [SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow), +#endif }; static __always_inline unsigned int skb_ext_total_length(void) @@ -4446,6 +4450,9 @@ static __always_inline unsigned int skb_ext_total_length(void) #endif #if IS_ENABLED(CONFIG_MPTCP) skb_ext_type_len[SKB_EXT_MPTCP] + +#endif +#if IS_ENABLED(CONFIG_MCTP) + skb_ext_type_len[SKB_EXT_MCTP] + #endif 0; } @@ -6519,6 +6526,14 @@ static void skb_ext_put_sp(struct sec_path *sp) } #endif +#ifdef CONFIG_MCTP_FLOWS +static void skb_ext_put_mctp(struct mctp_flow *flow) +{ + if (flow->key) + mctp_key_unref(flow->key); +} +#endif + void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id) { struct skb_ext *ext = skb->extensions; @@ -6554,6 +6569,10 @@ void __skb_ext_put(struct skb_ext *ext) if (__skb_ext_exist(ext, SKB_EXT_SEC_PATH)) skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH)); #endif +#if CONFIG_MCTP_FLOWS + if (__skb_ext_exist(ext, SKB_EXT_MCTP)) + skb_ext_put_mctp(skb_ext_get_ptr(ext, SKB_EXT_MCTP)); +#endif kmem_cache_free(skbuff_ext_cache, ext); } diff --git a/net/mctp/Kconfig b/net/mctp/Kconfig index 868c92272cbd..de739f49c40c 100644 --- a/net/mctp/Kconfig +++ b/net/mctp/Kconfig @@ -1,7 +1,7 @@ menuconfig MCTP depends on NET - tristate "MCTP core protocol support" + bool "MCTP core protocol support" help Management Component Transport Protocol (MCTP) is an in-system protocol for communicating between management controllers and @@ -16,3 +16,7 @@ config MCTP_TEST bool "MCTP core tests" if !KUNIT_ALL_TESTS depends on MCTP=y && KUNIT=y default KUNIT_ALL_TESTS + +config MCTP_FLOWS + bool + select SKB_EXTENSIONS From patchwork Thu Oct 28 06:18:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 12589373 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94D52C433FE for ; Thu, 28 Oct 2021 06:18:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6B97F61039 for ; Thu, 28 Oct 2021 06:18:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229788AbhJ1GVO (ORCPT ); Thu, 28 Oct 2021 02:21:14 -0400 Received: from pi.codeconstruct.com.au ([203.29.241.158]:42824 "EHLO codeconstruct.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229732AbhJ1GVN (ORCPT ); Thu, 28 Oct 2021 02:21:13 -0400 Received: by codeconstruct.com.au (Postfix, from userid 10000) id E60B120293; Thu, 28 Oct 2021 14:18:45 +0800 (AWST) From: Jeremy Kerr To: netdev@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Matt Johnston , Andrew Jeffery Subject: [PATCH net-next 3/3] mctp: Pass flow data & flow release events to drivers Date: Thu, 28 Oct 2021 14:18:33 +0800 Message-Id: <20211028061833.2390354-3-jk@codeconstruct.com.au> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211028061833.2390354-1-jk@codeconstruct.com.au> References: <20211028061833.2390354-1-jk@codeconstruct.com.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Now that we have an extension for MCTP data in skbs, populate the flow when a key has been created for the packet, and add a device driver operation to inform of flow destruction. Signed-off-by: Jeremy Kerr Reported-by: kernel test robot --- include/net/mctp.h | 5 ++++ include/net/mctpdevice.h | 14 ++++++++++ net/mctp/device.c | 51 +++++++++++++++++++++++++++++++++++++ net/mctp/route.c | 55 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/include/net/mctp.h b/include/net/mctp.h index 7a5ba801703c..73d5db9164e1 100644 --- a/include/net/mctp.h +++ b/include/net/mctp.h @@ -152,6 +152,11 @@ struct mctp_sk_key { /* expiry timeout; valid (above) cleared on expiry */ unsigned long expiry; + + /* free to use for device flow state tracking. Initialised to + * zero on inital key creation*/ + unsigned long dev_flow_state; + struct mctp_dev *dev; }; struct mctp_skb_cb { diff --git a/include/net/mctpdevice.h b/include/net/mctpdevice.h index 3a439463f055..fb95f52ce1c9 100644 --- a/include/net/mctpdevice.h +++ b/include/net/mctpdevice.h @@ -21,6 +21,8 @@ struct mctp_dev { unsigned int net; + const struct mctp_netdev_ops *ops; + /* Only modified under RTNL. Reads have addrs_lock held */ u8 *addrs; size_t num_addrs; @@ -29,12 +31,24 @@ struct mctp_dev { struct rcu_head rcu; }; +struct mctp_netdev_ops { + void (*release_flow)(struct mctp_dev *dev, + struct mctp_sk_key *key); +}; + #define MCTP_INITIAL_DEFAULT_NET 1 struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev); struct mctp_dev *__mctp_dev_get(const struct net_device *dev); +int mctp_register_netdev(struct net_device *dev, + const struct mctp_netdev_ops *ops); +void mctp_unregister_netdev(struct net_device *dev); + void mctp_dev_hold(struct mctp_dev *mdev); void mctp_dev_put(struct mctp_dev *mdev); +void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key); +void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key); + #endif /* __NET_MCTPDEVICE_H */ diff --git a/net/mctp/device.c b/net/mctp/device.c index 3827d62f52c9..8799ee77e7b7 100644 --- a/net/mctp/device.c +++ b/net/mctp/device.c @@ -260,6 +260,24 @@ void mctp_dev_put(struct mctp_dev *mdev) } } +void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key) + __must_hold(&key->lock) +{ + if (!dev) + return; + if (dev->ops && dev->ops->release_flow) + dev->ops->release_flow(dev, key); + key->dev = NULL; + mctp_dev_put(dev); +} + +void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key) + __must_hold(&key->lock) +{ + mctp_dev_hold(dev); + key->dev = dev; +} + static struct mctp_dev *mctp_add_dev(struct net_device *dev) { struct mctp_dev *mdev; @@ -414,6 +432,39 @@ static int mctp_dev_notify(struct notifier_block *this, unsigned long event, return NOTIFY_OK; } +static int mctp_register_netdevice(struct net_device *dev, + const struct mctp_netdev_ops *ops) +{ + struct mctp_dev *mdev; + + mdev = mctp_add_dev(dev); + if (IS_ERR(mdev)) + return PTR_ERR(mdev); + + mdev->ops = ops; + + return register_netdevice(dev); +} + +int mctp_register_netdev(struct net_device *dev, + const struct mctp_netdev_ops *ops) +{ + int rc; + + rtnl_lock(); + rc = mctp_register_netdevice(dev, ops); + rtnl_unlock(); + + return rc; +} +EXPORT_SYMBOL_GPL(mctp_register_netdev); + +void mctp_unregister_netdev(struct net_device *dev) +{ + unregister_netdev(dev); +} +EXPORT_SYMBOL_GPL(mctp_unregister_netdev); + static struct rtnl_af_ops mctp_af_ops = { .family = AF_MCTP, .fill_link_af = mctp_fill_link_af, diff --git a/net/mctp/route.c b/net/mctp/route.c index 82cc10a2fb0c..46c44823edb7 100644 --- a/net/mctp/route.c +++ b/net/mctp/route.c @@ -29,6 +29,8 @@ static const unsigned int mctp_message_maxlen = 64 * 1024; static const unsigned long mctp_key_lifetime = 6 * CONFIG_HZ; +static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev); + /* route output callbacks */ static int mctp_route_discard(struct mctp_route *route, struct sk_buff *skb) { @@ -152,8 +154,19 @@ static struct mctp_sk_key *mctp_key_alloc(struct mctp_sock *msk, void mctp_key_unref(struct mctp_sk_key *key) { - if (refcount_dec_and_test(&key->refs)) - kfree(key); + unsigned long flags; + + if (!refcount_dec_and_test(&key->refs)) + return; + + /* even though no refs exist here, the lock allows us to stay + * consistent with the locking requirement of mctp_dev_release_key + */ + spin_lock_irqsave(&key->lock, flags); + mctp_dev_release_key(key->dev, key); + spin_unlock_irqrestore(&key->lock, flags); + + kfree(key); } static int mctp_key_add(struct mctp_sk_key *key, struct mctp_sock *msk) @@ -204,6 +217,7 @@ static void __mctp_key_unlock_drop(struct mctp_sk_key *key, struct net *net, key->reasm_head = NULL; key->reasm_dead = true; key->valid = false; + mctp_dev_release_key(key->dev, key); spin_unlock_irqrestore(&key->lock, flags); spin_lock_irqsave(&net->mctp.keys_lock, flags); @@ -222,6 +236,40 @@ static void __mctp_key_unlock_drop(struct mctp_sk_key *key, struct net *net, } +#ifdef CONFIG_MCTP_FLOWS +static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) +{ + struct mctp_flow *flow; + + flow = skb_ext_add(skb, SKB_EXT_MCTP); + if (!flow) + return; + + refcount_inc(&key->refs); + flow->key = key; +} + +static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) +{ + struct mctp_sk_key *key; + struct mctp_flow *flow; + + flow = skb_ext_find(skb, SKB_EXT_MCTP); + if (!flow) + return; + + key = flow->key; + + if (WARN_ON(key->dev && key->dev != dev)) + return; + + mctp_dev_set_key(dev, key); +} +#else +static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {} +static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {} +#endif + static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb) { struct mctp_hdr *hdr = mctp_hdr(skb); @@ -465,6 +513,8 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb) return -EHOSTUNREACH; } + mctp_flow_prepare_output(skb, route->dev); + rc = dev_queue_xmit(skb); if (rc) rc = net_xmit_errno(rc); @@ -803,6 +853,7 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, rc = PTR_ERR(key); goto out_release; } + mctp_skb_set_flow(skb, key); /* done with the key in this scope */ mctp_key_unref(key); tag |= MCTP_HDR_FLAG_TO;