From patchwork Thu Jul 14 15:08:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 649029 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 3rrngd1QtMz9sCY for ; Sat, 16 Jul 2016 08:44:29 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.b=E1SoaHPL; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751446AbcGOWo0 (ORCPT ); Fri, 15 Jul 2016 18:44:26 -0400 Received: from mail-pa0-f45.google.com ([209.85.220.45]:35681 "EHLO mail-pa0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751080AbcGOWoY (ORCPT ); Fri, 15 Jul 2016 18:44:24 -0400 Received: by mail-pa0-f45.google.com with SMTP id dx3so43140484pab.2 for ; Fri, 15 Jul 2016 15:44:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id; bh=9gLtkwJdO/jCPB3aRicBDIeW4H1Ujt7/MOUFZMoTx8s=; b=E1SoaHPL6qjyoZ5s3hSyIw+XUQ8vqvTyLKNdbZGv33ZUu6HgAJZa9DCM7c6TUT9l16 eSH2RJst73/gXjah7st1A9PnBILkzrgXdFxeWH9f2T3vlTUA8yQnugkFfu/Rj/GBlQnR LduPeMFRQQ7SSE53om2upKoBNbG9s2qlh664Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=9gLtkwJdO/jCPB3aRicBDIeW4H1Ujt7/MOUFZMoTx8s=; b=lnHVOu4AGT/rIvqUr9K6QzEy6JF8B3o4TIisuLCv8n7X9Ahtnmif0w29s/1YVtTl8x gzXZLwO9Lj45qbbmN7HgiGbijms2I5Ld9wwAgEsLEZpGqEx4ZAVzQzSrDkxSn9sBob1Y Z/8e7LBblD9lVObdsqw7yu/GLAeyZDZ59UBbJC/hTCU+DJALlEX+xL/vALNID71PtykM KJKJGDr7WTlNuJT/0H4Yauci/vXKc5JJ7TCwe/wjiYOOPPdMS251q72rkqiE4884VC4h oHnuysqGM9Nc5qTWg1Aj1g/tDrcKvmPUN17KVKAcghn8XIATdyQU7ihumHuGadUwJi5X Wa+w== X-Gm-Message-State: ALyK8tLjgYkilkvbFvEdr83eqte7smy9MmMU1mL6wev950bAnHFasP7i++1HMsHgHAyFWdYc X-Received: by 10.66.138.108 with SMTP id qp12mr35675221pab.65.1468622663453; Fri, 15 Jul 2016 15:44:23 -0700 (PDT) Received: from dev.cumulusnetworks.com ([216.129.126.126]) by smtp.gmail.com with ESMTPSA id 4sm5744926pfi.24.2016.07.15.15.44.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Jul 2016 15:44:22 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: Nikolay Aleksandrov , Roopa Prabhu , Shrijeet Mukherjee , Satish Ashok , Donald Sharp , "David S. Miller" , Alexey Kuznetsov , James Morris , Hideaki YOSHIFUJI , Patrick McHardy Subject: [PATCH net-next] net: ipmr/ip6mr: add support for keeping an entry age Date: Thu, 14 Jul 2016 18:08:50 +0300 Message-Id: <1468508930-32720-1-git-send-email-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.4.3 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In preparation for hardware offloading of ipmr/ip6mr we need an interface that allows to check (and later update) the age of entries. Relying on stats alone can show activity but not actual age of the entry, furthermore when there're tens of thousands of entries a lot of the hardware implementations only support "hit" bits which are cleared on read to denote that the entry was active and shouldn't be aged out, these can then be naturally translated into age timestamp and will be compatible with the software forwarding age. Using a lastuse entry doesn't affect performance because the entries in that cache line are written to along with the age. Once an entry goes above the member size (32 bits) we keep it at UINT_MAX as we cannot afford to wrap it which will falsely show that it was used recently. This is not supposed to happen as entries should be aged out in matter of minutes or seconds. Since all new users are encouraged to use ipmr via netlink, this is exported via the RTA_CACHEINFO attribute which has rta_lastuse entry. Signed-off-by: Nikolay Aleksandrov CC: Roopa Prabhu CC: Shrijeet Mukherjee CC: Satish Ashok CC: Donald Sharp CC: David S. Miller CC: Alexey Kuznetsov CC: James Morris CC: Hideaki YOSHIFUJI CC: Patrick McHardy --- RTA_CACHEINFO was chosen because there're other useful members of the struct which will be used later when we gradually remove the ipmr/ip6mr entry cache limitations. include/linux/mroute.h | 1 + include/linux/mroute6.h | 1 + net/ipv4/ipmr.c | 18 +++++++++++++++--- net/ipv6/ip6mr.c | 17 ++++++++++++++--- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/include/linux/mroute.h b/include/linux/mroute.h index bf9b322cb0b0..d351fd3e1049 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -104,6 +104,7 @@ struct mfc_cache { unsigned long bytes; unsigned long pkt; unsigned long wrong_if; + unsigned long lastuse; unsigned char ttls[MAXVIFS]; /* TTL thresholds */ } res; } mfc_un; diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h index 66982e764051..3987b64040c5 100644 --- a/include/linux/mroute6.h +++ b/include/linux/mroute6.h @@ -92,6 +92,7 @@ struct mfc6_cache { unsigned long bytes; unsigned long pkt; unsigned long wrong_if; + unsigned long lastuse; unsigned char ttls[MAXMIFS]; /* TTL thresholds */ } res; } mfc_un; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 5ad48ec77710..b0ba7f6d2731 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1150,6 +1150,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, c->mfc_origin = mfc->mfcc_origin.s_addr; c->mfc_mcastgrp = mfc->mfcc_mcastgrp.s_addr; c->mfc_parent = mfc->mfcc_parent; + c->mfc_un.res.lastuse = jiffies; ipmr_update_thresholds(mrt, c, mfc->mfcc_ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; @@ -1792,6 +1793,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt, vif = cache->mfc_parent; cache->mfc_un.res.pkt++; cache->mfc_un.res.bytes += skb->len; + cache->mfc_un.res.lastuse = jiffies; if (cache->mfc_origin == htonl(INADDR_ANY) && true_vifi >= 0) { struct mfc_cache *cache_proxy; @@ -2071,10 +2073,13 @@ drop: static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm) { - int ct; - struct rtnexthop *nhp; - struct nlattr *mp_attr; struct rta_mfc_stats mfcs; + struct rta_cacheinfo ci; + struct nlattr *mp_attr; + struct rtnexthop *nhp; + long delta; + int ct; + /* If cache is unresolved, don't try to parse IIF and OIF */ if (c->mfc_parent >= MAXVIFS) @@ -2109,7 +2114,14 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) < 0) return -EMSGSIZE; + memset(&ci, 0, sizeof(ci)); + delta = jiffies - c->mfc_un.res.lastuse; + /* rta_lastuse is 32 bit, we shouldn't wrap the age */ + ci.rta_lastuse = min_t(u64, jiffies_delta_to_clock_t(delta), UINT_MAX); + if (nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci) < 0) + return -EMSGSIZE; rtm->rtm_type = RTN_MULTICAST; + return 1; } diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index c7ca0f5d1a3b..6a5f1ca1dcca 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1500,6 +1500,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; c->mf6c_parent = mfc->mf6cc_parent; + c->mfc_un.res.lastuse = jiffies; ip6mr_update_thresholds(mrt, c, ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; @@ -2092,6 +2093,7 @@ static void ip6_mr_forward(struct net *net, struct mr6_table *mrt, vif = cache->mf6c_parent; cache->mfc_un.res.pkt++; cache->mfc_un.res.bytes += skb->len; + cache->mfc_un.res.lastuse = jiffies; if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) { struct mfc6_cache *cache_proxy; @@ -2234,10 +2236,12 @@ int ip6_mr_input(struct sk_buff *skb) static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) { - int ct; - struct rtnexthop *nhp; - struct nlattr *mp_attr; struct rta_mfc_stats mfcs; + struct rta_cacheinfo ci; + struct nlattr *mp_attr; + struct rtnexthop *nhp; + long delta; + int ct; /* If cache is unresolved, don't try to parse IIF and OIF */ if (c->mf6c_parent >= MAXMIFS) @@ -2273,7 +2277,14 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) < 0) return -EMSGSIZE; + memset(&ci, 0, sizeof(ci)); + delta = jiffies - c->mfc_un.res.lastuse; + /* rta_lastuse is 32 bit, we shouldn't wrap the age */ + ci.rta_lastuse = min_t(u64, jiffies_delta_to_clock_t(delta), UINT_MAX); + if (nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci) < 0) + return -EMSGSIZE; rtm->rtm_type = RTN_MULTICAST; + return 1; }