From patchwork Sat Jun 13 18:04:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Feldman X-Patchwork-Id: 483906 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C5EEB1401F0 for ; Sun, 14 Jun 2015 04:02:49 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=xvYnDjzh; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753518AbbFMSCo (ORCPT ); Sat, 13 Jun 2015 14:02:44 -0400 Received: from mail-ie0-f175.google.com ([209.85.223.175]:36696 "EHLO mail-ie0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753241AbbFMSCk (ORCPT ); Sat, 13 Jun 2015 14:02:40 -0400 Received: by iecrd14 with SMTP id rd14so9497054iec.3 for ; Sat, 13 Jun 2015 11:02:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hSHDI/yxzkTdV37fqUTtB+gx8YvCnYUhyjYmwyI6EzU=; b=xvYnDjzh6/DrqLpL+QRCq6HvhwMgD9N5bAovJAJIVgHU/qm1wRPWb0k8fNacRI3Rs+ uQVDRukmLZkPrlG8LXuMayWp1JvTRaDcX5xAbpOVIiSXPLARP7fPIBvU0Z6bBvDaqwWm tsJC5Qxr9qzjtdy8aQZ3Mbbk0D0pnktM1nACvq+ygjY49tKvDtMoiu5Sgn8YUqKWMZNm jtQDcN0oiZcCmu3g2rrNpLJM4hzZB/QSa9GZBdlbacIYYfIZE/ZDIpBsBJVs3+1AbkZ+ /GVuQ3ye9nOsWSeJrHtQIO5HNgU8oXoEGG1XIiu84brcl3GIFDCFz9JhCxmrJ1FAIhNr NmDg== X-Received: by 10.107.17.161 with SMTP id 33mr8913376ior.48.1434218559393; Sat, 13 Jun 2015 11:02:39 -0700 (PDT) Received: from rocker1.rocker.net ([199.58.98.143]) by mx.google.com with ESMTPSA id t7sm3777377ign.8.2015.06.13.11.02.37 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 13 Jun 2015 11:02:38 -0700 (PDT) From: sfeldma@gmail.com To: netdev@vger.kernel.org Cc: jiri@resnulli.us, simon.horman@netronome.com, roopa@cumulusnetworks.com, ronen.arad@intel.com, john.r.fastabend@intel.com, andrew@lunn.ch, f.fainelli@gmail.com, linux@roeck-us.net, davidch@broadcom.com, stephen@networkplumber.org Subject: [RFC PATCH net-next 2/4] switchdev: add fwd_mark generator helper Date: Sat, 13 Jun 2015 11:04:28 -0700 Message-Id: <1434218670-43821-3-git-send-email-sfeldma@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1434218670-43821-1-git-send-email-sfeldma@gmail.com> References: <1434218670-43821-1-git-send-email-sfeldma@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Scott Feldman skb->fwd_mark and dev->fwd_mark are 32-bit and should be unique for device and maybe even unique for a sub-set of ports within device, so add switchdev helper function to generate unique marks based on driver-supplied key. Typically, the driver would use device switch ID for key, and maybe additional fields in key for grouped ports such as bridge ifindex. The key can be of arbitrary length. The generator uses a global hash table to store fwd_marks hashed by key. Signed-off-by: Scott Feldman Acked-by: Roopa Prabhu --- include/net/switchdev.h | 6 ++++ net/switchdev/switchdev.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 437f8fe..6eaceee 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -157,6 +157,7 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, struct net_device *filter_dev, int idx); +u32 switchdev_mark_get(void *key, size_t key_len); #else @@ -271,6 +272,11 @@ static inline int switchdev_port_fdb_dump(struct sk_buff *skb, return -EOPNOTSUPP; } +static inline u32 switchdev_mark_get(void *key, size_t key_len) +{ + return 0; +} + #endif #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index a5d0f8e..9ca37b3 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -924,3 +926,73 @@ void switchdev_fib_ipv4_abort(struct fib_info *fi) fi->fib_net->ipv4.fib_offload_disabled = true; } EXPORT_SYMBOL_GPL(switchdev_fib_ipv4_abort); + +#define SWITCHDEV_MARK_HT_BITS 5 +static DEFINE_HASHTABLE(switchdev_mark_ht, SWITCHDEV_MARK_HT_BITS); +static DEFINE_SPINLOCK(switchdev_mark_lock); +static u32 switchdev_mark_next = 1; + +/** + * switchdev_mark_get - Generate a unique mark for key + * + * @key: key used to generate mark + * @key_len: length of key in bytes + * + * Returns unqiue 32-bit mark for given key, or 0 if error. + * A small global hash table stores the marks for each key. + * The length of the key and key contents are arbitrary. + * The marks can be used, for example, to skb->fwd_mark a pkt + * to associate the skb with a key. + */ +u32 switchdev_mark_get(void *key, size_t key_len) +{ + struct switchdev_mark_ht_entry { + struct hlist_node entry; + void *key; + size_t key_len; + u32 key_crc32; + u32 mark; + } *entry; + u32 key_crc32 = crc32(~0, key, key_len); + u32 mark = 0; + unsigned long flags; + + spin_lock_irqsave(&switchdev_mark_lock, flags); + hash_for_each_possible(switchdev_mark_ht, entry, + entry, key_crc32) { + if (entry->key_len != key_len) + continue; + if (memcmp(entry->key, key, key_len) == 0) { + mark = entry->mark; + break; + } + } + spin_unlock_irqrestore(&switchdev_mark_lock, flags); + + if (mark) + goto out; + + entry = kmalloc(GFP_KERNEL, sizeof(*entry)); + if (!entry) + goto out; + + entry->key = kmalloc(GFP_KERNEL, key_len); + if (!entry->key) { + kfree(entry); + goto out; + } + + memcpy(entry->key, key, key_len); + entry->key_len = key_len; + entry->key_crc32 = key_crc32; + + spin_lock_irqsave(&switchdev_mark_lock, flags); + mark = switchdev_mark_next++; + entry->mark = mark; + hash_add(switchdev_mark_ht, &entry->entry, key_crc32); + spin_unlock_irqrestore(&switchdev_mark_lock, flags); + +out: + return mark; +} +EXPORT_SYMBOL_GPL(switchdev_mark_get);