* Re: [PATCH net] ipv4: Don't override return code from ip_route_input_noref()
From: Sabrina Dubroca @ 2017-08-31 23:45 UTC (permalink / raw)
To: Stefano Brivio; +Cc: David S . Miller, netdev, Wei Wang
In-Reply-To: <c4d8970306e614ac139cf2f33ab5e6bb73b30154.1504194307.git.sbrivio@redhat.com>
2017-08-31, 18:11:41 +0200, Stefano Brivio wrote:
> After ip_route_input() calls ip_route_input_noref(), another
> check on skb_dst() is done, but if this fails, we shouldn't
> override the return code from ip_route_input_noref(), as it
> could have been more specific (i.e. -EHOSTUNREACH).
>
> This also saves one call to skb_dst_force_safe() and one to
> skb_dst() in case the ip_route_input_noref() check fails.
>
> Reported-by: Sabrina Dubroca <sdubroca@redhat.com>
> Fixes: ad65a2f05695 ("ipv4: call dst_hold_safe() properly")
That should be instead:
Fixes: 9df16efadd2a ("ipv4: call dst_hold_safe() properly")
Acked-by: Sabrina Dubroca <sd@queasysnail.net>
--
Sabrina
^ permalink raw reply
* Re: [PATCH 31/31] timer: Switch to testing for .function instead of .data
From: Dmitry Torokhov @ 2017-08-31 23:45 UTC (permalink / raw)
To: Kees Cook
Cc: Thomas Gleixner, Rafael J. Wysocki, Pavel Machek, Len Brown,
Greg Kroah-Hartman, Mike Marciniszyn, Dennis Dalessandro,
Doug Ledford, Sean Hefty, Hal Rosenstock, Jeff Kirsher,
linux-pm@vger.kernel.org, linux-rdma, linux-input@vger.kernel.org,
intel-wired-lan, netdev, lkml
In-Reply-To: <1504222183-61202-32-git-send-email-keescook@chromium.org>
On Thu, Aug 31, 2017 at 4:29 PM, Kees Cook <keescook@chromium.org> wrote:
> In several places, .data is checked for initialization to gate early
> calls to del_timer_sync(). Checking for .function is equally valid, so
> switch to this in all callers.
Not seeing the rest of patches it is unclear from the patch
description why this is needed/wanted.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v2 net-next 0/2] net: ubuf_info.refcnt conversion
From: Eric Dumazet @ 2017-08-31 23:48 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
Yet another atomic_t -> refcount_t conversion, split in two patches.
First patch prepares the automatic conversion done in the second patch.
Eric Dumazet (2):
net: prepare (struct ubuf_info)->refcnt conversion
net: convert (struct ubuf_info)->refcnt to refcount_t
drivers/vhost/net.c | 2 +-
include/linux/skbuff.h | 5 +++--
net/core/skbuff.c | 14 ++++----------
net/ipv4/tcp.c | 2 --
4 files changed, 8 insertions(+), 15 deletions(-)
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply
* [PATCH v2 net-next 1/2] net: prepare (struct ubuf_info)->refcnt conversion
From: Eric Dumazet @ 2017-08-31 23:48 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
In-Reply-To: <20170831234822.26612-1-edumazet@google.com>
In order to convert this atomic_t refcnt to refcount_t,
we need to init the refcount to one to not trigger
a 0 -> 1 transition.
This also removes one atomic operation in fast path.
v2: removed dead code in sock_zerocopy_put_abort()
as suggested by Willem.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/core/skbuff.c | 10 ++--------
net/ipv4/tcp.c | 2 --
2 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 917da73d3ab3b82163cf0a9ee944da09cb5a391f..1a754d7896ceac1eb85e3b13c1422b4d6a88fedf 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -963,7 +963,7 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
uarg->len = 1;
uarg->bytelen = size;
uarg->zerocopy = 1;
- atomic_set(&uarg->refcnt, 0);
+ atomic_set(&uarg->refcnt, 1);
sock_hold(sk);
return uarg;
@@ -1005,6 +1005,7 @@ struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
uarg->len++;
uarg->bytelen = bytelen;
atomic_set(&sk->sk_zckey, ++next);
+ sock_zerocopy_get(uarg);
return uarg;
}
}
@@ -1102,13 +1103,6 @@ void sock_zerocopy_put_abort(struct ubuf_info *uarg)
atomic_dec(&sk->sk_zckey);
uarg->len--;
- /* sock_zerocopy_put expects a ref. Most sockets take one per
- * skb, which is zero on abort. tcp_sendmsg holds one extra, to
- * avoid an skb send inside the main loop triggering uarg free.
- */
- if (sk->sk_type != SOCK_STREAM)
- atomic_inc(&uarg->refcnt);
-
sock_zerocopy_put(uarg);
}
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 21ca2df274c5130a13d31a391a1408d779af34af..fff4d7bc3b8b46174e7bd0a04d7c212307e55cb5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1190,8 +1190,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
goto out_err;
}
- /* skb may be freed in main loop, keep extra ref on uarg */
- sock_zerocopy_get(uarg);
if (!(sk_check_csum_caps(sk) && sk->sk_route_caps & NETIF_F_SG))
uarg->zerocopy = 0;
}
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* [PATCH v2 net-next 2/2] net: convert (struct ubuf_info)->refcnt to refcount_t
From: Eric Dumazet @ 2017-08-31 23:48 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Willem de Bruijn, Eric Dumazet, Eric Dumazet
In-Reply-To: <20170831234822.26612-1-edumazet@google.com>
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
v2: added the change in drivers/vhost/net.c as spotted
by Willem.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/vhost/net.c | 2 +-
include/linux/skbuff.h | 5 +++--
net/core/skbuff.c | 6 +++---
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index ba08b78ed630c429ccf415af69bf27f2433af4f0..8d2bcae53a2ec9ea1c876625e581bcd429abe365 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -533,7 +533,7 @@ static void handle_tx(struct vhost_net *net)
ubuf->callback = vhost_zerocopy_callback;
ubuf->ctx = nvq->ubufs;
ubuf->desc = nvq->upend_idx;
- atomic_set(&ubuf->refcnt, 1);
+ refcount_set(&ubuf->refcnt, 1);
msg.msg_control = ubuf;
msg.msg_controllen = sizeof(ubuf);
ubufs = nvq->ubufs;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7594e19bce622a38dc39c054093c3da15b99b67b..316a92b45351f53709886ee0099cbc83b66f1b15 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -22,6 +22,7 @@
#include <linux/cache.h>
#include <linux/rbtree.h>
#include <linux/socket.h>
+#include <linux/refcount.h>
#include <linux/atomic.h>
#include <asm/types.h>
@@ -456,7 +457,7 @@ struct ubuf_info {
u32 bytelen;
};
};
- atomic_t refcnt;
+ refcount_t refcnt;
struct mmpin {
struct user_struct *user;
@@ -472,7 +473,7 @@ struct ubuf_info *sock_zerocopy_realloc(struct sock *sk, size_t size,
static inline void sock_zerocopy_get(struct ubuf_info *uarg)
{
- atomic_inc(&uarg->refcnt);
+ refcount_inc(&uarg->refcnt);
}
void sock_zerocopy_put(struct ubuf_info *uarg);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 1a754d7896ceac1eb85e3b13c1422b4d6a88fedf..06b9ddca3188442d1d1d2052fc060cf5b1e2a6f4 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -963,7 +963,7 @@ struct ubuf_info *sock_zerocopy_alloc(struct sock *sk, size_t size)
uarg->len = 1;
uarg->bytelen = size;
uarg->zerocopy = 1;
- atomic_set(&uarg->refcnt, 1);
+ refcount_set(&uarg->refcnt, 1);
sock_hold(sk);
return uarg;
@@ -1086,7 +1086,7 @@ EXPORT_SYMBOL_GPL(sock_zerocopy_callback);
void sock_zerocopy_put(struct ubuf_info *uarg)
{
- if (uarg && atomic_dec_and_test(&uarg->refcnt)) {
+ if (uarg && refcount_dec_and_test(&uarg->refcnt)) {
if (uarg->callback)
uarg->callback(uarg, uarg->zerocopy);
else
@@ -1483,7 +1483,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
if (skb_orphan_frags(skb, gfp_mask))
goto nofrags;
if (skb_zcopy(skb))
- atomic_inc(&skb_uarg(skb)->refcnt);
+ refcount_inc(&skb_uarg(skb)->refcnt);
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
skb_frag_ref(skb, i);
--
2.14.1.581.gf28d330327-goog
^ permalink raw reply related
* [PATCH 25/31] net/atm/mpc: Use separate static data field with with static timer
From: Kees Cook @ 2017-08-31 23:29 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Kees Cook, David S. Miller, Andrew Morton, Alexey Dobriyan,
Reshetova, Elena, netdev, linux-kernel
In-Reply-To: <1504222183-61202-1-git-send-email-keescook@chromium.org>
In preparation for changing the timer callback argument to the timer
pointer, move to a separate static data variable.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: "Reshetova, Elena" <elena.reshetova@intel.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
net/atm/mpc.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 5baa31b8500c..fc24a46500ae 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -95,7 +95,7 @@ static netdev_tx_t mpc_send_packet(struct sk_buff *skb,
static int mpoa_event_listener(struct notifier_block *mpoa_notifier,
unsigned long event, void *dev);
static void mpc_timer_refresh(void);
-static void mpc_cache_check(unsigned long checking_time);
+static void mpc_cache_check(unsigned long unused);
static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
0xaa, 0xaa, 0x03,
@@ -121,7 +121,8 @@ static struct notifier_block mpoa_notifier = {
struct mpoa_client *mpcs = NULL; /* FIXME */
static struct atm_mpoa_qos *qos_head = NULL;
-static DEFINE_TIMER(mpc_timer, NULL);
+static DEFINE_TIMER(mpc_timer, mpc_cache_check);
+static unsigned long checking_time;
static struct mpoa_client *find_mpc_by_itfnum(int itf)
@@ -1411,12 +1412,11 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
static void mpc_timer_refresh(void)
{
mpc_timer.expires = jiffies + (MPC_P2 * HZ);
- mpc_timer.data = mpc_timer.expires;
- mpc_timer.function = mpc_cache_check;
+ checking_time = mpc_timer.expires;
add_timer(&mpc_timer);
}
-static void mpc_cache_check(unsigned long checking_time)
+static void mpc_cache_check(unsigned long unused)
{
struct mpoa_client *mpc = mpcs;
static unsigned long previous_resolving_check_time;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v2 net-next 1/2] net: prepare (struct ubuf_info)->refcnt conversion
From: Willem de Bruijn @ 2017-08-31 23:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S . Miller, netdev, Willem de Bruijn, Eric Dumazet
In-Reply-To: <20170831234822.26612-2-edumazet@google.com>
On Thu, Aug 31, 2017 at 7:48 PM, Eric Dumazet <edumazet@google.com> wrote:
> In order to convert this atomic_t refcnt to refcount_t,
> we need to init the refcount to one to not trigger
> a 0 -> 1 transition.
>
> This also removes one atomic operation in fast path.
>
> v2: removed dead code in sock_zerocopy_put_abort()
> as suggested by Willem.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply
* Re: [PATCH v2 net-next 2/2] net: convert (struct ubuf_info)->refcnt to refcount_t
From: Willem de Bruijn @ 2017-08-31 23:55 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S . Miller, netdev, Willem de Bruijn, Eric Dumazet
In-Reply-To: <20170831234822.26612-3-edumazet@google.com>
On Thu, Aug 31, 2017 at 7:48 PM, Eric Dumazet <edumazet@google.com> wrote:
> refcount_t type and corresponding API should be
> used instead of atomic_t when the variable is used as
> a reference counter. This allows to avoid accidental
> refcounter overflows that might lead to use-after-free
> situations.
>
> v2: added the change in drivers/vhost/net.c as spotted
> by Willem.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply
* Re: [PATCH 31/31] timer: Switch to testing for .function instead of .data
From: Kees Cook @ 2017-08-31 23:59 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Thomas Gleixner, Rafael J. Wysocki, Pavel Machek, Len Brown,
Greg Kroah-Hartman, Mike Marciniszyn, Dennis Dalessandro,
Doug Ledford, Sean Hefty, Hal Rosenstock, Jeff Kirsher,
linux-pm@vger.kernel.org, linux-rdma, linux-input@vger.kernel.org,
intel-wired-lan, netdev, lkml
In-Reply-To: <CAKdAkRTSgs+JTKRa2nvcSPD+zQ5OhsLx_aM8WaZyg304QQN3hA@mail.gmail.com>
On Thu, Aug 31, 2017 at 4:45 PM, Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
> On Thu, Aug 31, 2017 at 4:29 PM, Kees Cook <keescook@chromium.org> wrote:
>> In several places, .data is checked for initialization to gate early
>> calls to del_timer_sync(). Checking for .function is equally valid, so
>> switch to this in all callers.
>
> Not seeing the rest of patches it is unclear from the patch
> description why this is needed/wanted.
The CC list would have been really giant, but here is the first patch
and the earlier series list:
https://lkml.org/lkml/2017/8/31/904
https://lkml.org/lkml/2017/8/30/760
tl;dr: We're going to switch all struct timer_list callbacks to get
the timer pointer as the argument instead of from the .data field.
This patch is one step in removing open-coded users of the .data
field.
-Kees
--
Kees Cook
Pixel Security
^ permalink raw reply
* Re: [PATCH v2 net-next 0/2] net: ubuf_info.refcnt conversion
From: Eric Dumazet @ 2017-09-01 0:04 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S . Miller, netdev, Willem de Bruijn
In-Reply-To: <20170831234822.26612-1-edumazet@google.com>
On Thu, 2017-08-31 at 16:48 -0700, Eric Dumazet wrote:
> Yet another atomic_t -> refcount_t conversion, split in two patches.
>
> First patch prepares the automatic conversion done in the second patch.
>
> Eric Dumazet (2):
> net: prepare (struct ubuf_info)->refcnt conversion
> net: convert (struct ubuf_info)->refcnt to refcount_t
>
> drivers/vhost/net.c | 2 +-
> include/linux/skbuff.h | 5 +++--
> net/core/skbuff.c | 14 ++++----------
> net/ipv4/tcp.c | 2 --
> 4 files changed, 8 insertions(+), 15 deletions(-)
>
David please ignore this series, I will send a V3 :)
^ permalink raw reply
* Re: [RFC net-next 0/8] net: dsa: Multi-queue awareness
From: Andrew Lunn @ 2017-09-01 0:05 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev, jiri, jhs, davem, xiyou.wangcong, vivien.didelot
In-Reply-To: <1504138732-65383-1-git-send-email-f.fainelli@gmail.com>
On Wed, Aug 30, 2017 at 05:18:44PM -0700, Florian Fainelli wrote:
> This patch series is sent as reference, especially because the last patch
> is trying not to be creating too many layer violations, but clearly there
> are a little bit being created here anyways.
>
> Essentially what I am trying to achieve is that you have a stacked device which
> is multi-queue aware, that applications will be using, and for which they can
> control the queue selection (using mq) the way they want. Each of each stacked
> network devices are created for each port of the switch (this is what DSA
> does). When a skb is submitted from say net_device X, we can derive its port
> number and look at the queue_mapping value to determine which port of the
> switch and queue we should be sending this to. The information is embedded in a
> tag (4 bytes) and is used by the switch to steer the transmission.
>
> These stacked devices will actually transmit using a "master" or conduit
> network device which has a number of queues as well. In one version of the
> hardware that I work with, we have up to 4 ports, each with 8 queues, and the
> master device has a total of 32 hardware queues, so a 1:1 mapping is easy. With
> another version of the hardware, same number of ports and queues, but only 16
> hardware queues, so only a 2:1 mapping is possible.
>
> In order for congestion information to work properly, I need to establish a
> mapping, preferably before transmission starts (but reconfiguration while
> interfaces are running would be possible too) between these stacked device's
> queue and the conduit interface's queue.
>
> Comments, flames, rotten tomatoes, anything!
Right, i think i understand.
This works just for traffic between the host and ports. The host can
set the egress queue. And i assume the queues are priorities, either
absolute or weighted round robin, etc.
But this has no effect on traffic going from port to port. At some
point, i expect you will want to offload TC for that.
How will the two interact? Could the TC rules also act on traffic from
the host to a port? Would it be simpler in the long run to just
implement TC rules?
Andrew
^ permalink raw reply
* Re: [PATCH net-next v5 2/2] tcp_diag: report TCP MD5 signing keys and addresses
From: Ivan Delalande @ 2017-09-01 0:21 UTC (permalink / raw)
To: Sabrina Dubroca; +Cc: David Miller, Eric Dumazet, netdev
In-Reply-To: <20170831232633.GA678@bistromath.localdomain>
On Fri, Sep 01, 2017 at 01:26:33AM +0200, Sabrina Dubroca wrote:
> 2017-08-31, 09:59:39 -0700, Ivan Delalande wrote:
> > diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
> > index a748c74aa8b7..abbf0edcf6c2 100644
> > --- a/net/ipv4/tcp_diag.c
> > +++ b/net/ipv4/tcp_diag.c
> [...]
> > +static int tcp_diag_get_aux(struct sock *sk, bool net_admin,
> > + struct sk_buff *skb)
> > +{
> > +#ifdef CONFIG_TCP_MD5SIG
> > + if (net_admin) {
>
> In tcp_diag_get_aux_size() you put a check for sk_fullsock. I don't
> see anything preventing you from reaching this with a !fullsock?
Currently handler->idiag_get_aux is only called from inet_sk_diag_fill
which has a `BUG_ON(!sk_fullsock(sk));`, but I could add another
explicit check in that function if you think it's more consistent.
Actually, I wasn't sure when adding this idiag_get_aux in v2 if it
should be called from inet_twsk_diag_fill, inet_req_diag_fill and
inet_csk_diag_fill, or just the last one. I chose that simpler approach
for now to avoid duplicating these state checks in the idiag_get_aux
defined by protocols and because we didn't need for INET_DIAG_MD5SIG,
but it shouldn't be too hard to change. Do you think this could be
useful for other protocols or attributes?
Thank you,
--
Ivan Delalande
Arista Networks
^ permalink raw reply
* Re: netdev carrier changes is one even after ethernet link up.
From: Florian Fainelli @ 2017-09-01 0:23 UTC (permalink / raw)
To: Bhadram Varka, andrew@lunn.ch; +Cc: linux-netdev
In-Reply-To: <974898714b3e4e59b933983ded977ce2@bgmail102.nvidia.com>
On 08/30/2017 10:53 PM, Bhadram Varka wrote:
> Hi,
>
>
>
> I have observed that carrier_changes is one even in case of the ethernet
> link is up.
>
>
>
> After investigating the code below is my observation –
>
>
>
> ethernet_driver_probe()
>
> +--->phy_connect()
>
> | +--->phy_attach_direct()
>
> | +---> netif_carrier_off() : which increments
> carrier_changes to one.
>
> +--->register_netdevice() : will the carrier_changes becomes zero here ?
>
> +--->netif_carrier_off(): not increment the carrier_changes since
> __LINK_STATE_NOCARRIER already set.
>
>
>
> From ethernet driver open will start the PHY and trigger the
> phy_state_machine.
>
> Phy_state_machine workqueue calling netif_carrier_on() once the link is UP.
>
> netif_carrier_on() increments the carrier_changes by one.
If the call trace is correct, then there is at least two problems here:
- phy_connect() does start the PHY machine which means that as soon as
it detects a link state of any kind (up or down) it can call
netif_carrier_off() respectively netif_carrier_on()
- as soon as you call register_netdevice() notifiers run and other parts
of the kernel or user-space programs can see an inconsistent link state
I would suggest doing the following sequence instead:
netif_carrier_off()
register_netdevice()
phy_connect()
Which should result in a consistent link state and carrier value.
>
>
>
> After link is UP if we check the carrier_changes sysfs node - it will be
> one only.
>
>
>
> $ cat /sys/class/net/eth0/carrier_changes
>
> 1
>
>
>
> After reverting the change - https://lkml.org/lkml/2016/1/9/173 (net:
> phy: turn carrier off on phy attach) then I could see the carrier
> changes incremented to 2 after Link UP.
>
> $ cat /sys/class/net/eth0/carrier_changes
>
> 2
>
>
>
> Thanks,
>
> Bhadram.
>
> ------------------------------------------------------------------------
> This email message is for the sole use of the intended recipient(s) and
> may contain confidential information. Any unauthorized review, use,
> disclosure or distribution is prohibited. If you are not the intended
> recipient, please contact the sender by reply email and destroy all
> copies of the original message.
> ------------------------------------------------------------------------
--
Florian
^ permalink raw reply
* Re: [PATCH 19/31] timer: Remove open-coded casts for .data and .function
From: Tyrel Datwyler @ 2017-09-01 0:28 UTC (permalink / raw)
To: Kees Cook, Thomas Gleixner
Cc: Samuel Ortiz, James E.J. Bottomley, Martin K. Petersen,
linux-kernel, linux-scsi, netdev, Paul Mackerras, Tyrel Datwyler,
linuxppc-dev
In-Reply-To: <1504222183-61202-20-git-send-email-keescook@chromium.org>
On 08/31/2017 04:29 PM, Kees Cook wrote:
> This standardizes the callback and data prototypes in several places that
> perform casting, in an effort to remove more open-coded .data and
> .function uses in favor of setup_timer().
>
> Cc: Samuel Ortiz <samuel@sortiz.org>
> Cc: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
> Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-scsi@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
> drivers/net/irda/bfin_sir.c | 5 +++--
> drivers/scsi/ibmvscsi/ibmvfc.c | 14 ++++++--------
> drivers/scsi/ibmvscsi/ibmvscsi.c | 8 ++++----
> 3 files changed, 13 insertions(+), 14 deletions(-)
For ibmvfc & ibmvscsi portions:
Acked-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
^ permalink raw reply
* Re: [PATCH 19/31] timer: Remove open-coded casts for .data and .function
From: Tyrel Datwyler @ 2017-09-01 0:29 UTC (permalink / raw)
To: Kees Cook, Thomas Gleixner
Cc: Samuel Ortiz, James E.J. Bottomley, Martin K. Petersen,
linux-kernel, linux-scsi, netdev, Paul Mackerras, Tyrel Datwyler,
linuxppc-dev
In-Reply-To: <1504222183-61202-20-git-send-email-keescook@chromium.org>
On 08/31/2017 04:29 PM, Kees Cook wrote:
> This standardizes the callback and data prototypes in several places that
> perform casting, in an effort to remove more open-coded .data and
> .function uses in favor of setup_timer().
>
> Cc: Samuel Ortiz <samuel@sortiz.org>
> Cc: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
> Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
> Cc: netdev@vger.kernel.org
> Cc: linux-scsi@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
> drivers/net/irda/bfin_sir.c | 5 +++--
> drivers/scsi/ibmvscsi/ibmvfc.c | 14 ++++++--------
> drivers/scsi/ibmvscsi/ibmvscsi.c | 8 ++++----
> 3 files changed, 13 insertions(+), 14 deletions(-)
Resending from correct email address.
For ibmvfc & ibmvscsi portions:
Acked-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
^ permalink raw reply
* Re: [PATCH 2/3] security: bpf: Add eBPF LSM hooks and security field to eBPF map
From: Chenbo Feng @ 2017-09-01 0:29 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Chenbo Feng, linux-security-module, Jeffrey Vander Stoep, netdev,
SELinux, Alexei Starovoitov, Lorenzo Colitti
In-Reply-To: <59A88FF0.9010605@iogearbox.net>
On Thu, Aug 31, 2017 at 3:38 PM, Daniel Borkmann <daniel@iogearbox.net> wrote:
> On 08/31/2017 10:56 PM, Chenbo Feng wrote:
>>
>> From: Chenbo Feng <fengc@google.com>
>>
>> Introduce a pointer into struct bpf_map to hold the security information
>> about the map. The actual security struct varies based on the security
>> models implemented. Place the LSM hooks before each of the unrestricted
>> eBPF operations, the map_update_elem and map_delete_elem operations are
>> checked by security_map_modify. The map_lookup_elem and map_get_next_key
>> operations are checked by securtiy_map_read.
>>
>> Signed-off-by: Chenbo Feng <fengc@google.com>
>
>
> Against which tree is this by the way, net-next? There are
> changes here which require a rebase of your set.
>
This patch series is rebased on security subsystem since patch 1/3 is
a patch for
security system I assume. But I am not sure where this specific patch
should go in.
If I should submit this one to net-next, I will rebase it against
net-next and submit again.
>> ---
>> include/linux/bpf.h | 3 +++
>> kernel/bpf/syscall.c | 28 ++++++++++++++++++++++++++++
>> 2 files changed, 31 insertions(+)
>>
>> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> index b69e7a5869ff..ca3e6ff7091d 100644
>> --- a/include/linux/bpf.h
>> +++ b/include/linux/bpf.h
>> @@ -53,6 +53,9 @@ struct bpf_map {
>> struct work_struct work;
>> atomic_t usercnt;
>> struct bpf_map *inner_map_meta;
>> +#ifdef CONFIG_SECURITY
>> + void *security;
>> +#endif
>> };
>>
>> /* function argument constraints */
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 045646da97cc..b15580bcf3b1 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -279,6 +279,10 @@ static int map_create(union bpf_attr *attr)
>> if (err)
>> return -EINVAL;
>>
>> + err = security_map_create();
>
>
> Seems a bit limited to me, don't you want to be able to
> also differentiate between different map types? Same goes
> for security_prog_load() wrt prog types, no?
>
I don't want to introduce extra complexity into it if not necessary.
so I only included the
thing needed for the selinux implementation for now. But I agree that the map
and program type information could be useful when people developing more complex
security checks. I will add a union bpf_attr *attr pointer into the
security hook functions
for future needs.
>> + if (err)
>> + return -EACCES;
>> +
>> /* find map type and init map: hashtable vs rbtree vs bloom vs ...
>> */
>> map = find_and_alloc_map(attr);
>> if (IS_ERR(map))
>> @@ -291,6 +295,10 @@ static int map_create(union bpf_attr *attr)
>> if (err)
>> goto free_map_nouncharge;
>>
>> + err = security_post_create(map);
>> + if (err < 0)
>> + goto free_map;
>> +
>
>
> So the hook you implement in patch 3/3 does:
>
> +static int selinux_bpf_post_create(struct bpf_map *map)
> +{
> + struct bpf_security_struct *bpfsec;
> +
> + bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
> + if (!bpfsec)
> + return -ENOMEM;
> +
> + bpfsec->sid = current_sid();
> + map->security = bpfsec;
> +
> + return 0;
> +}
>
> Where do you kfree() bpfsec when the map gets released
> normally or in error path?
>
Will add it in next version. Thanks for point it out.
>> err = bpf_map_alloc_id(map);
>> if (err)
>> goto free_map;
>> @@ -410,6 +418,10 @@ static int map_lookup_elem(union bpf_attr *attr)
>> if (IS_ERR(map))
>> return PTR_ERR(map);
>>
>> + err = security_map_read(map);
>> + if (err)
>> + return -EACCES;
>
>
> How about actually dropping ref?
>
May bad, thanks again.
>> +
>> key = memdup_user(ukey, map->key_size);
>> if (IS_ERR(key)) {
>> err = PTR_ERR(key);
>> @@ -490,6 +502,10 @@ static int map_update_elem(union bpf_attr *attr)
>> if (IS_ERR(map))
>> return PTR_ERR(map);
>>
>> + err = security_map_modify(map);
>> + if (err)
>> + return -EACCES;
>
>
> Ditto ...
>
>> key = memdup_user(ukey, map->key_size);
>> if (IS_ERR(key)) {
>> err = PTR_ERR(key);
>> @@ -573,6 +589,10 @@ static int map_delete_elem(union bpf_attr *attr)
>> if (IS_ERR(map))
>> return PTR_ERR(map);
>>
>> + err = security_map_modify(map);
>> + if (err)
>> + return -EACCES;
>
>
> Ditto ...
>
>> key = memdup_user(ukey, map->key_size);
>> if (IS_ERR(key)) {
>> err = PTR_ERR(key);
>> @@ -616,6 +636,10 @@ static int map_get_next_key(union bpf_attr *attr)
>> if (IS_ERR(map))
>> return PTR_ERR(map);
>>
>> + err = security_map_read(map);
>> + if (err)
>> + return -EACCES;
>
>
> And once again here ... :(
>
>
>> if (ukey) {
>> key = memdup_user(ukey, map->key_size);
>> if (IS_ERR(key)) {
>> @@ -935,6 +959,10 @@ static int bpf_prog_load(union bpf_attr *attr)
>> if (CHECK_ATTR(BPF_PROG_LOAD))
>> return -EINVAL;
>>
>> + err = security_prog_load();
>> + if (err)
>> + return -EACCES;
>> +
>> if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
>> return -EINVAL;
>>
>>
>
^ permalink raw reply
* Re: [PATCH 31/31] timer: Switch to testing for .function instead of .data
From: Dmitry Torokhov @ 2017-09-01 1:06 UTC (permalink / raw)
To: Kees Cook
Cc: Thomas Gleixner, Rafael J. Wysocki, Pavel Machek, Len Brown,
Greg Kroah-Hartman, Mike Marciniszyn, Dennis Dalessandro,
Doug Ledford, Sean Hefty, Hal Rosenstock, Jeff Kirsher,
linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-rdma,
linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
intel-wired-lan-qjLDD68F18P21nG7glBr7A, netdev, lkml
In-Reply-To: <CAGXu5jK84cN9MdjfzaipD7GN8a37JMfD8X0Em4mk2_aFGuaOUg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, Aug 31, 2017 at 4:59 PM, Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> On Thu, Aug 31, 2017 at 4:45 PM, Dmitry Torokhov
> <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Thu, Aug 31, 2017 at 4:29 PM, Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>>> In several places, .data is checked for initialization to gate early
>>> calls to del_timer_sync(). Checking for .function is equally valid, so
>>> switch to this in all callers.
>>
>> Not seeing the rest of patches it is unclear from the patch
>> description why this is needed/wanted.
>
> The CC list would have been really giant, but here is the first patch
> and the earlier series list:
>
> https://lkml.org/lkml/2017/8/31/904
> https://lkml.org/lkml/2017/8/30/760
>
> tl;dr: We're going to switch all struct timer_list callbacks to get
> the timer pointer as the argument instead of from the .data field.
> This patch is one step in removing open-coded users of the .data
> field.
>
And that is exactly what should have been in the patch description.
FWIW for input bits:
Acked-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RFC net-next 0/5] TSN: Add qdisc-based config interfaces for traffic shapers
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
andre.guedes, ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
Hi,
This patchset is an RFC on a proposal of how the Traffic Control subsystem can
be used to offload the configuration of traffic shapers into network devices
that provide support for them in HW. Our goal here is to start upstreaming
support for features related to the Time-Sensitive Networking (TSN) set of
standards into the kernel.
As part of this work, we've assessed previous public discussions related to TSN
enabling: patches from Henrik Austad (Cisco), the presentation from Eric Mann
at Linux Plumbers 2012, patches from Gangfeng Huang (National Instruments) and
the current state of the OpenAVNU project (https://github.com/AVnu/OpenAvnu/).
Please note that the patches provided as part of this RFC are implementing what
is needed only for 802.1Qav (FQTSS) only, but we'd like to take advantage of
this discussion and share our WIP ideas for the 802.1Qbv and 802.1Qbu interfaces
as well. The current patches are only providing support for HW offload of the
configs.
Overview
========
Time-sensitive Networking (TSN) is a set of standards that aim to address
resources availability for providing bandwidth reservation and bounded latency
on Ethernet based LANs. The proposal described here aims to cover mainly what is
needed to enable the following standards: 802.1Qat, 802.1Qav, 802.1Qbv and
802.1Qbu.
The initial target of this work is the Intel i210 NIC, but other controllers'
datasheet were also taken into account, like the Renesas RZ/A1H RZ/A1M group and
the Synopsis DesignWare Ethernet QoS controller.
Proposal
========
Feature-wise, what is covered here are configuration interfaces for HW
implementations of the Credit-Based shaper (CBS, 802.1Qav), Time-Aware shaper
(802.1Qbv) and Frame Preemption (802.1Qbu). CBS is a per-queue shaper, while
Qbv and Qbu must be configured per port, with the configuration covering all
queues. Given that these features are related to traffic shaping, and that the
traffic control subsystem already provides a queueing discipline that offloads
config into the device driver (i.e. mqprio), designing new qdiscs for the
specific purpose of offloading the config for each shaper seemed like a good
fit.
For steering traffic into the correct queues, we use the socket option
SO_PRIORITY and then a mechanism to map priority to traffic classes / Tx queues.
The qdisc mqprio is currently used in our tests.
As for the shapers config interface:
* CBS (802.1Qav)
This patchset is proposing a new qdisc called 'cbs'. Its 'tc' cmd line is:
$ tc qdisc add dev IFACE parent ID cbs locredit N hicredit M sendslope S \
idleslope I
Note that the parameters for this qdisc are the ones defined by the
802.1Q-2014 spec, so no hardware specific functionality is exposed here.
* Time-aware shaper (802.1Qbv):
The idea we are currently exploring is to add a "time-aware", priority based
qdisc, that also exposes the Tx queues available and provides a mechanism for
mapping priority <-> traffic class <-> Tx queues in a similar fashion as
mqprio. We are calling this qdisc 'taprio', and its 'tc' cmd line would be:
$ $ tc qdisc add dev ens4 parent root handle 100 taprio num_tc 4 \
map 2 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
queues 0 1 2 3 \
sched-file gates.sched [base-time <interval>] \
[cycle-time <interval>] [extension-time <interval>]
<file> is multi-line, with each line being of the following format:
<cmd> <gate mask> <interval in nanoseconds>
Qbv only defines one <cmd>: "S" for 'SetGates'
For example:
S 0x01 300
S 0x03 500
This means that there are two intervals, the first will have the gate
for traffic class 0 open for 300 nanoseconds, the second will have
both traffic classes open for 500 nanoseconds.
Additionally, an option to set just one entry of the gate control list will
also be provided by 'taprio':
$ tc qdisc (...) \
sched-row <row number> <cmd> <gate mask> <interval> \
[base-time <interval>] [cycle-time <interval>] \
[extension-time <interval>]
* Frame Preemption (802.1Qbu):
To control even further the latency, it may prove useful to signal which
traffic classes are marked as preemptable. For that, 'taprio' provides the
preemption command so you set each traffic class as preemptable or not:
$ tc qdisc (...) \
preemption 0 1 1 1
* Time-aware shaper + Preemption:
As an example of how Qbv and Qbu can be used together, we may specify
both the schedule and the preempt-mask, and this way we may also
specify the Set-Gates-and-Hold and Set-Gates-and-Release commands as
specified in the Qbu spec:
$ tc qdisc add dev ens4 parent root handle 100 taprio num_tc 4 \
map 2 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
queues 0 1 2 3 \
preemption 0 1 1 1 \
sched-file preempt_gates.sched
<file> is multi-line, with each line being of the following format:
<cmd> <gate mask> <interval in nanoseconds>
For this case, two new commands are introduced:
"H" for 'set gates and hold'
"R" for 'set gates and release'
H 0x01 300
R 0x03 500
Testing this RFC
================
For testing the patches of this RFC only, you can refer to the samples and
helper script being added to samples/tsn/ and the use the 'mqprio' qdisc to
setup the priorities to Tx queues mapping, together with the 'cbs' qdisc to
configure the HW shaper of the i210 controller:
1) Setup priorities to traffic classes to hardware queues mapping
$ tc qdisc replace dev enp3s0 parent root mqprio num_tc 3 \
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@1 2@2 hw 0
2) Check scheme. You want to get the inner qdiscs ID from the bottom up
$ tc -g class show dev enp3s0
Ex.:
+---(802a:3) mqprio
| +---(802a:6) mqprio
| +---(802a:7) mqprio
|
+---(802a:2) mqprio
| +---(802a:5) mqprio
|
+---(802a:1) mqprio
+---(802a:4) mqprio
* Here '802a:4' is Tx Queue #0 and '802a:5' is Tx Queue #1.
3) Calculate CBS parameters for classes A and B. i.e. BW for A is 20Mbps and
for B is 10Mbps:
$ ./samples/tsn/calculate_cbs_params.py -A 20000 -a 1500 -B 10000 -b 1500
4) Configure CBS for traffic class A (priority 3) as provided by the script:
$ tc qdisc replace dev enp3s0 parent 802a:4 cbs locredit -1470 \
hicredit 30 sendslope -980000 idleslope 20000
5) Configure CBS for traffic class B (priority 2):
$ tc qdisc replace dev enp3s0 parent 802a:5 cbs \
locredit -1485 hicredit 31 sendslope -990000 idleslope 10000
6) Run Listener, compiled from samples/tsn/listener.c
$ ./listener -i enp3s0
7) Run Talker for class A (prio 3 here), compiled from samples/tsn/talker.c
$ ./talker -i enp3s0 -p 3
* The bandwidth displayed on the listener output at this stage should be very
close to the one configured for class A.
8) You can also run a Talker for class B (prio 2 here)
$ ./talker -i enp3s0 -p 2
* The bandwidth displayed on the listener output now should increase to very
close to the one configured for class A + class B.
Authors
=======
- Andre Guedes <andre.guedes@intel.com>
- Ivan Briano <ivan.briano@intel.com>
- Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
- Vinicius Gomes <vinicius.gomes@intel.com>
Andre Guedes (2):
igb: Add support for CBS offload
samples/tsn: Add script for calculating CBS config
Jesus Sanchez-Palencia (1):
sample: Add TSN Talker and Listener examples
Vinicius Costa Gomes (2):
net/sched: Introduce the user API for the CBS shaper
net/sched: Introduce Credit Based Shaper (CBS) qdisc
drivers/net/ethernet/intel/igb/e1000_defines.h | 23 ++
drivers/net/ethernet/intel/igb/e1000_regs.h | 8 +
drivers/net/ethernet/intel/igb/igb.h | 6 +
drivers/net/ethernet/intel/igb/igb_main.c | 349 +++++++++++++++++++++++++
include/linux/netdevice.h | 1 +
include/uapi/linux/pkt_sched.h | 29 ++
net/sched/Kconfig | 11 +
net/sched/Makefile | 1 +
net/sched/sch_cbs.c | 286 ++++++++++++++++++++
samples/tsn/calculate_cbs_params.py | 112 ++++++++
samples/tsn/listener.c | 254 ++++++++++++++++++
samples/tsn/talker.c | 136 ++++++++++
12 files changed, 1216 insertions(+)
create mode 100644 net/sched/sch_cbs.c
create mode 100755 samples/tsn/calculate_cbs_params.py
create mode 100644 samples/tsn/listener.c
create mode 100644 samples/tsn/talker.c
^ permalink raw reply
* [RFC net-next 1/5] net/sched: Introduce the user API for the CBS shaper
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
andre.guedes, ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
In-Reply-To: <20170901012625.14838-1-vinicius.gomes@intel.com>
Export the API necessary for configuring the CBS shaper (implemented
in the next patch) via the tc tool.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
include/uapi/linux/pkt_sched.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 099bf5528fed..aa4a3e5421be 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -871,4 +871,33 @@ struct tc_pie_xstats {
__u32 maxq; /* maximum queue size */
__u32 ecn_mark; /* packets marked with ecn*/
};
+
+/* CBS */
+/* FIXME: this is only for usage with ndo_setup_tc(), this should be
+ * in another header someplace else. Is pkt_cls.h the right place?
+ */
+struct tc_cbs_qopt_offload {
+ u8 enable;
+ s32 queue;
+ s32 hicredit;
+ s32 locredit;
+ s32 idleslope;
+ s32 sendslope;
+};
+
+struct tc_cbs_qopt {
+ __s32 hicredit;
+ __s32 locredit;
+ __s32 idleslope;
+ __s32 sendslope;
+};
+
+enum {
+ TCA_CBS_UNSPEC,
+ TCA_CBS_PARMS,
+ __TCA_CBS_MAX,
+};
+
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+
#endif
--
2.14.1
^ permalink raw reply related
* [RFC net-next 3/5] igb: Add support for CBS offload
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Andre Guedes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
In-Reply-To: <20170901012625.14838-1-vinicius.gomes@intel.com>
From: Andre Guedes <andre.guedes@intel.com>
This patch adds support for Credit-Based Shaper (CBS) qdisc offload
from Traffic Control system. This support enable us to leverage the
Forwarding and Queuing for Time-Sensitive Streams (FQTSS) features
from Intel i210 Ethernet Controller. FQTSS is the former 802.1Qav
standard which was merged into 802.1Q in 2014. It enables traffic
prioritization and bandwidth reservation via the Credit-Based Shaper
which is implemented in hardware by i210 controller.
The patch introduces the igb_setup_tc() function which implements the
support for CBS qdisc hardware offload in the IGB driver. CBS offload
is the only traffic control offload supported by the driver at the
moment.
FQTSS transmission mode from i210 controller is automatically enabled
by the IGB driver when the CBS is enabled for the first hardware
queue. Likewise, FQTSS mode is automatically disabled when CBS is
disabled for the last hardware queue. Changing FQTSS mode requires NIC
reset.
FQTSS feature is supported by i210 controller only.
Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
---
drivers/net/ethernet/intel/igb/e1000_defines.h | 23 ++
drivers/net/ethernet/intel/igb/e1000_regs.h | 8 +
drivers/net/ethernet/intel/igb/igb.h | 6 +
drivers/net/ethernet/intel/igb/igb_main.c | 349 +++++++++++++++++++++++++
4 files changed, 386 insertions(+)
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 1de82f247312..83cabff1e0ab 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -353,7 +353,18 @@
#define E1000_RXPBS_CFG_TS_EN 0x80000000
#define I210_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */
+#define I210_RXPBSIZE_MASK 0x0000003F
+#define I210_RXPBSIZE_PB_32KB 0x00000020
#define I210_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */
+#define I210_TXPBSIZE_MASK 0xC0FFFFFF
+#define I210_TXPBSIZE_PB0_8KB (8 << 0)
+#define I210_TXPBSIZE_PB1_8KB (8 << 6)
+#define I210_TXPBSIZE_PB2_4KB (4 << 12)
+#define I210_TXPBSIZE_PB3_4KB (4 << 18)
+
+#define I210_DTXMXPKTSZ_DEFAULT 0x00000098
+
+#define I210_SR_QUEUES_NUM 2
/* SerDes Control */
#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
@@ -1051,4 +1062,16 @@
#define E1000_VLAPQF_P_VALID(_n) (0x1 << (3 + (_n) * 4))
#define E1000_VLAPQF_QUEUE_MASK 0x03
+/* TX Qav Control fields */
+#define E1000_TQAVCTRL_XMIT_MODE BIT(0)
+#define E1000_TQAVCTRL_DATAFETCHARB BIT(4)
+#define E1000_TQAVCTRL_DATATRANARB BIT(8)
+
+/* TX Qav Credit Control fields */
+#define E1000_TQAVCC_IDLESLOPE_MASK 0xFFFF
+#define E1000_TQAVCC_QUEUEMODE BIT(31)
+
+/* Transmit Descriptor Control fields */
+#define E1000_TXDCTL_PRIORITY BIT(27)
+
#endif
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 58adbf234e07..8eee081d395f 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -421,6 +421,14 @@ do { \
#define E1000_I210_FLA 0x1201C
+#define E1000_I210_DTXMXPKTSZ 0x355C
+
+#define E1000_I210_TXDCTL(_n) (0x0E028 + ((_n) * 0x40))
+
+#define E1000_I210_TQAVCTRL 0x3570
+#define E1000_I210_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
+#define E1000_I210_TQAVHC(_n) (0x300C + ((_n) * 0x40))
+
#define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
#define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 06ffb2bc713e..92845692087a 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -281,6 +281,11 @@ struct igb_ring {
u16 count; /* number of desc. in the ring */
u8 queue_index; /* logical index of the ring*/
u8 reg_idx; /* physical index of the ring */
+ bool cbs_enable; /* indicates if CBS is enabled */
+ s32 idleslope; /* idleSlope in kbps */
+ s32 sendslope; /* sendSlope in kbps */
+ s32 hicredit; /* hiCredit in bytes */
+ s32 locredit; /* loCredit in bytes */
/* everything past this point are written often */
u16 next_to_clean;
@@ -621,6 +626,7 @@ struct igb_adapter {
#define IGB_FLAG_EEE BIT(14)
#define IGB_FLAG_VLAN_PROMISC BIT(15)
#define IGB_FLAG_RX_LEGACY BIT(16)
+#define IGB_FLAG_FQTSS BIT(17)
/* Media Auto Sense */
#define IGB_MAS_ENABLE_0 0X0001
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index fd4a46b03cc8..47cabca0c99a 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -62,6 +62,17 @@
#define BUILD 0
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
+
+enum queue_mode {
+ QUEUE_MODE_STRICT_PRIORITY,
+ QUEUE_MODE_STREAM_RESERVATION,
+};
+
+enum tx_queue_prio {
+ TX_QUEUE_PRIO_HIGH,
+ TX_QUEUE_PRIO_LOW,
+};
+
char igb_driver_name[] = "igb";
char igb_driver_version[] = DRV_VERSION;
static const char igb_driver_string[] =
@@ -1271,6 +1282,12 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
ring->count = adapter->tx_ring_count;
ring->queue_index = txr_idx;
+ ring->cbs_enable = false;
+ ring->idleslope = 0;
+ ring->sendslope = 0;
+ ring->hicredit = 0;
+ ring->locredit = 0;
+
u64_stats_init(&ring->tx_syncp);
u64_stats_init(&ring->tx_syncp2);
@@ -1598,6 +1615,292 @@ static void igb_get_hw_control(struct igb_adapter *adapter)
ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
}
+static void enable_fqtss(struct igb_adapter *adapter, bool enable)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ if (enable)
+ adapter->flags |= IGB_FLAG_FQTSS;
+ else
+ adapter->flags &= ~IGB_FLAG_FQTSS;
+
+ if (netif_running(netdev))
+ schedule_work(&adapter->reset_task);
+ else
+ igb_reset(adapter);
+}
+
+static bool is_fqtss_enabled(struct igb_adapter *adapter)
+{
+ return (adapter->flags & IGB_FLAG_FQTSS) ? true : false;
+}
+
+static int set_tx_desc_fetch_prio(struct e1000_hw *hw, int queue,
+ enum tx_queue_prio prio)
+{
+ u32 val;
+
+ WARN_ON(hw->mac.type != e1000_i210);
+
+ if (queue < 0 || queue > 4)
+ return -EINVAL;
+
+ val = rd32(E1000_I210_TXDCTL(queue));
+
+ if (prio == TX_QUEUE_PRIO_HIGH)
+ val |= E1000_TXDCTL_PRIORITY;
+ else
+ val &= ~E1000_TXDCTL_PRIORITY;
+
+ wr32(E1000_I210_TXDCTL(queue), val);
+ return 0;
+}
+
+static int set_queue_mode(struct e1000_hw *hw, int queue, enum queue_mode mode)
+{
+ u32 val;
+
+ WARN_ON(hw->mac.type != e1000_i210);
+
+ /* Stream reservation is only supported for queue 0 and 1. */
+ if (queue < 0 || queue > 1)
+ return -EINVAL;
+
+ val = rd32(E1000_I210_TQAVCC(queue));
+
+ if (mode == QUEUE_MODE_STREAM_RESERVATION)
+ val |= E1000_TQAVCC_QUEUEMODE;
+ else
+ val &= ~E1000_TQAVCC_QUEUEMODE;
+
+ wr32(E1000_I210_TQAVCC(queue), val);
+ return 0;
+}
+
+/**
+ * igb_configure_cbs - Configure Credit-Based Shaper (CBS)
+ * @adapter: pointer to adapter struct
+ * @queue: queue number
+ * @enable: true = enable CBS, false = disable CBS
+ * @idleslope: idleSlope in kbps
+ * @sendslope: sendSlope in kbps
+ * @hicredit: hiCredit in bytes
+ * @locredit: loCredit in bytes
+ *
+ * Configure CBS for a given hardware queue. When disabling, idleslope,
+ * sendslope, hicredit, locredit arguments are ignored. Returns 0 if
+ * success. Negative otherwise.
+ **/
+static void igb_configure_cbs(struct igb_adapter *adapter, int queue,
+ bool enable, int idleslope, int sendslope,
+ int hicredit, int locredit)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
+ u32 tqavcc;
+ u16 value;
+
+ WARN_ON(hw->mac.type != e1000_i210);
+ WARN_ON(queue < 0 || queue > 1);
+ WARN_ON(adapter->num_tx_queues < 2);
+
+ if (enable) {
+ set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_HIGH);
+ set_queue_mode(hw, queue, QUEUE_MODE_STREAM_RESERVATION);
+
+ /* According to i210 datasheet section 7.2.7.7, we should set
+ * the 'idleSlope' field from TQAVCC register following the
+ * equation:
+ *
+ * For 100 Mbps link speed:
+ *
+ * value = BW * 0x7735 * 0.2 (E1)
+ *
+ * For 1000Mbps link speed:
+ *
+ * value = BW * 0x7735 * 2 (E2)
+ *
+ * E1 and E2 can be merged into one equation as shown below.
+ * Note that 'link-speed' is in Mbps.
+ *
+ * value = BW * 0x7735 * 2 * link-speed
+ * -------------- (E3)
+ * 1000
+ *
+ * 'BW' is the percentage bandwidth out of full link speed
+ * which can be found with the following equation. Note that
+ * idleSlope here is the parameter from this function which
+ * is in kbps.
+ *
+ * BW = idleSlope
+ * ----------------- (E4)
+ * link-speed * 1000
+ *
+ * That said, we can come up with a generic equation to
+ * calculate the value we should set it TQAVCC register by
+ * replacing 'BW' in E3 by E4. The resulting equation is:
+ *
+ * value = idleSlope * 0x7735 * 2 * link-speed
+ * ----------------- -------------- (E5)
+ * link-speed * 1000 1000
+ *
+ * 'link-speed' is present in both sides of the fraction so
+ * it is canceled out. The final equation is the following:
+ *
+ * value = idleSlope * 61034
+ * ----------------- (E6)
+ * 1000000
+ */
+ value = DIV_ROUND_UP_ULL(idleslope * 61034ULL, 1000000);
+
+ tqavcc = rd32(E1000_I210_TQAVCC(queue));
+ tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK;
+ tqavcc |= value;
+ wr32(E1000_I210_TQAVCC(queue), tqavcc);
+
+ wr32(E1000_I210_TQAVHC(queue), 0x80000000 + hicredit * 0x7735);
+ } else {
+ set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_LOW);
+ set_queue_mode(hw, queue, QUEUE_MODE_STRICT_PRIORITY);
+
+ /* Set idleSlope to zero. */
+ tqavcc = rd32(E1000_I210_TQAVCC(queue));
+ tqavcc &= ~E1000_TQAVCC_IDLESLOPE_MASK;
+ wr32(E1000_I210_TQAVCC(queue), tqavcc);
+
+ /* Set hiCredit to zero. */
+ wr32(E1000_I210_TQAVHC(queue), 0);
+ }
+
+ /* XXX: In i210 controller the sendSlope and loCredit
+ * parameters from CBS are not configurable by software so we
+ * don't do any 'controller configuration' in respect to these
+ * parameters.
+ */
+
+ netdev_dbg(netdev, "CBS %s: queue %d idleslope %d sendslope %d "
+ "hiCredit %d locredit %d\n",
+ (enable) ? "enabled" : "disabled", queue,
+ idleslope, sendslope, hicredit, locredit);
+}
+
+static void igb_save_cbs_params(struct igb_adapter *adapter, int queue,
+ bool enable, int idleslope, int sendslope,
+ int hicredit, int locredit)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ struct igb_ring *ring;
+
+ WARN_ON(hw->mac.type != e1000_i210);
+ WARN_ON(queue < 0 || queue > 1);
+ WARN_ON(adapter->num_tx_queues < 2);
+
+ ring = adapter->tx_ring[queue];
+
+ ring->cbs_enable = enable;
+ ring->idleslope = idleslope;
+ ring->sendslope = sendslope;
+ ring->hicredit = hicredit;
+ ring->locredit = locredit;
+}
+
+static bool is_any_cbs_enabled(struct igb_adapter *adapter)
+{
+ struct igb_ring *ring;
+ int i;
+
+ WARN_ON(adapter->num_tx_queues < 2);
+
+ for (i = 0; i < I210_SR_QUEUES_NUM; i++) {
+ ring = adapter->tx_ring[i];
+
+ if (ring->cbs_enable)
+ return true;
+ }
+
+ return false;
+}
+
+static void igb_setup_tx_mode(struct igb_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct e1000_hw *hw = &adapter->hw;
+ u32 val;
+ int i;
+
+ /* Only i210 controller supports changing the transmission mode. */
+ if (hw->mac.type != e1000_i210)
+ return;
+
+ if (is_fqtss_enabled(adapter)) {
+ /* Configure TQAVCTRL register: set transmit mode to 'Qav',
+ * set data fetch arbitration to 'round robin' and set data
+ * transfer arbitration to 'credit shaper algorithm.
+ */
+ val = rd32(E1000_I210_TQAVCTRL);
+ val |= E1000_TQAVCTRL_XMIT_MODE | E1000_TQAVCTRL_DATATRANARB;
+ val &= ~E1000_TQAVCTRL_DATAFETCHARB;
+ wr32(E1000_I210_TQAVCTRL, val);
+
+ /* Configure Tx and Rx packet buffers sizes as described in
+ * i210 datasheet section 7.2.7.7.
+ */
+ val = rd32(E1000_TXPBS);
+ val &= ~I210_TXPBSIZE_MASK;
+ val |= I210_TXPBSIZE_PB0_8KB | I210_TXPBSIZE_PB1_8KB |
+ I210_TXPBSIZE_PB2_4KB | I210_TXPBSIZE_PB3_4KB;
+ wr32(E1000_TXPBS, val);
+
+ val = rd32(E1000_RXPBS);
+ val &= ~I210_RXPBSIZE_MASK;
+ val |= I210_RXPBSIZE_PB_32KB;
+ wr32(E1000_RXPBS, val);
+
+ /* Section 8.12.9 states that MAX_TPKT_SIZE from DTXMXPKTSZ
+ * register should not exceed the buffer size programmed in
+ * TXPBS. The smallest buffer size programmed in TXPBS is 4kB
+ * so according to the datasheet we should set MAX_TPKT_SIZE to
+ * 4kB / 64.
+ *
+ * However, when we do so, no frame from queue 2 and 3 are
+ * transmitted. It seems the MAX_TPKT_SIZE should not be great
+ * or _equal_ to the buffer size programmed in TXPBS. For this
+ * reason, we set set MAX_ TPKT_SIZE to (4kB - 1) / 64.
+ */
+ val = (4096 - 1) / 64;
+ wr32(E1000_I210_DTXMXPKTSZ, val);
+
+ /* Since FQTSS mode is enabled, apply any CBS configuration
+ * previously set. If no previous CBS configuration has been
+ * done, then the initial configuration is applied, which means
+ * CBS is disabled. CBS configuration is only supported by SR
+ * queues i.e. queue 0 and queue 1.
+ */
+ for (i = 0; i < I210_SR_QUEUES_NUM; i++) {
+ struct igb_ring *ring = adapter->tx_ring[i];
+
+ igb_configure_cbs(adapter, i, ring->cbs_enable,
+ ring->idleslope, ring->sendslope,
+ ring->hicredit, ring->locredit);
+ }
+ } else {
+ wr32(E1000_RXPBS, I210_RXPBSIZE_DEFAULT);
+ wr32(E1000_TXPBS, I210_TXPBSIZE_DEFAULT);
+ wr32(E1000_I210_DTXMXPKTSZ, I210_DTXMXPKTSZ_DEFAULT);
+
+ val = rd32(E1000_I210_TQAVCTRL);
+ /* According to Section 8.12.21, the other flags we've set when
+ * enabling FQTSS are not relevant when disabling FQTSS so we
+ * don't set they here.
+ */
+ val &= ~E1000_TQAVCTRL_XMIT_MODE;
+ wr32(E1000_I210_TQAVCTRL, val);
+ }
+
+ netdev_dbg(netdev, "FQTSS %s\n", (is_fqtss_enabled(adapter)) ?
+ "enabled" : "disabled");
+}
+
/**
* igb_configure - configure the hardware for RX and TX
* @adapter: private board structure
@@ -1609,6 +1912,7 @@ static void igb_configure(struct igb_adapter *adapter)
igb_get_hw_control(adapter);
igb_set_rx_mode(netdev);
+ igb_setup_tx_mode(adapter);
igb_restore_vlan(adapter);
@@ -2150,6 +2454,50 @@ igb_features_check(struct sk_buff *skb, struct net_device *dev,
return features;
}
+static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ void *type_data)
+{
+ struct igb_adapter *adapter = netdev_priv(dev);
+ struct e1000_hw *hw = &adapter->hw;
+ struct tc_cbs_qopt_offload *cbs;
+
+ if (hw->mac.type != e1000_i210)
+ return -ENOTSUPP;
+
+ if (type != TC_SETUP_CBS)
+ return -ENOTSUPP;
+
+ /* In order to support FQTSS feature, we must have at least 2 Tx
+ * queues enabled.
+ */
+ if (adapter->num_tx_queues < 2)
+ return -ENOTSUPP;
+
+ cbs = type_data;
+
+ /* Only queues 0 and 1 support CBS configuration. */
+ if (cbs->queue < 0 || cbs->queue > 1)
+ return -EINVAL;
+
+ igb_save_cbs_params(adapter, cbs->queue, cbs->enable,
+ cbs->idleslope, cbs->sendslope,
+ cbs->hicredit, cbs->locredit);
+
+ if (is_fqtss_enabled(adapter)) {
+ igb_configure_cbs(adapter, cbs->queue, cbs->enable,
+ cbs->idleslope, cbs->sendslope,
+ cbs->hicredit, cbs->locredit);
+
+ if (!is_any_cbs_enabled(adapter))
+ enable_fqtss(adapter, false);
+
+ } else {
+ enable_fqtss(adapter, true);
+ }
+
+ return 0;
+}
+
static const struct net_device_ops igb_netdev_ops = {
.ndo_open = igb_open,
.ndo_stop = igb_close,
@@ -2175,6 +2523,7 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_set_features = igb_set_features,
.ndo_fdb_add = igb_ndo_fdb_add,
.ndo_features_check = igb_features_check,
+ .ndo_setup_tc = igb_setup_tc,
};
/**
--
2.14.1
^ permalink raw reply related
* [RFC net-next 2/5] net/sched: Introduce Credit Based Shaper (CBS) qdisc
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
andre.guedes, ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
In-Reply-To: <20170901012625.14838-1-vinicius.gomes@intel.com>
This queueing discipline implements the shaper algorithm defined by
the 802.1Q-2014 Section 8.6.8.2 and detailed in Annex L.
It's primary usage is to apply some bandwidth reservation to user
defined traffic classes, which are mapped to different queues via the
mqprio qdisc.
Initially, it only supports offloading the traffic shaping work to
supporting controllers.
Later, when a software implementation is added, the current dependency
on being installed "under" mqprio can be lifted.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
---
include/linux/netdevice.h | 1 +
net/sched/Kconfig | 11 ++
net/sched/Makefile | 1 +
net/sched/sch_cbs.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 299 insertions(+)
create mode 100644 net/sched/sch_cbs.c
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 35de8312e0b5..dd9a2ecd0c03 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -775,6 +775,7 @@ enum tc_setup_type {
TC_SETUP_CLSFLOWER,
TC_SETUP_CLSMATCHALL,
TC_SETUP_CLSBPF,
+ TC_SETUP_CBS,
};
/* These structures hold the attributes of xdp state that are being passed
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index e70ed26485a2..c03d86a7775e 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -172,6 +172,17 @@ config NET_SCH_TBF
To compile this code as a module, choose M here: the
module will be called sch_tbf.
+config NET_SCH_CBS
+ tristate "Credit Based Shaper (CBS)"
+ ---help---
+ Say Y here if you want to use the Credit Based Shaper (CBS) packet
+ scheduling algorithm.
+
+ See the top of <file:net/sched/sch_cbs.c> for more details.
+
+ To compile this code as a module, choose M here: the
+ module will be called sch_cbs.
+
config NET_SCH_GRED
tristate "Generic Random Early Detection (GRED)"
---help---
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 7b915d226de7..80c8f92d162d 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_NET_SCH_FQ_CODEL) += sch_fq_codel.o
obj-$(CONFIG_NET_SCH_FQ) += sch_fq.o
obj-$(CONFIG_NET_SCH_HHF) += sch_hhf.o
obj-$(CONFIG_NET_SCH_PIE) += sch_pie.o
+obj-$(CONFIG_NET_SCH_CBS) += sch_cbs.o
obj-$(CONFIG_NET_CLS_U32) += cls_u32.o
obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
new file mode 100644
index 000000000000..1c86a9e14150
--- /dev/null
+++ b/net/sched/sch_cbs.c
@@ -0,0 +1,286 @@
+/*
+ * net/sched/sch_cbs.c Credit Based Shaper
+ *
+ * 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.
+ *
+ * Authors: Vininicius Costa Gomes <vinicius.gomes@intel.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <net/netlink.h>
+#include <net/sch_generic.h>
+#include <net/pkt_sched.h>
+
+struct cbs_sched_data {
+ struct Qdisc *qdisc; /* Inner qdisc, default - pfifo queue */
+ s32 queue;
+ s32 locredit;
+ s32 hicredit;
+ s32 sendslope;
+ s32 idleslope;
+};
+
+static int cbs_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ struct sk_buff **to_free)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+ int ret;
+
+ ret = qdisc_enqueue(skb, q->qdisc, to_free);
+ if (ret != NET_XMIT_SUCCESS) {
+ if (net_xmit_drop_count(ret))
+ qdisc_qstats_drop(sch);
+ return ret;
+ }
+
+ qdisc_qstats_backlog_inc(sch, skb);
+ sch->q.qlen++;
+ return NET_XMIT_SUCCESS;
+}
+
+static struct sk_buff *cbs_dequeue(struct Qdisc *sch)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb;
+
+ skb = q->qdisc->ops->peek(q->qdisc);
+ if (skb) {
+ skb = qdisc_dequeue_peeked(q->qdisc);
+ if (unlikely(!skb))
+ return NULL;
+
+ qdisc_qstats_backlog_dec(sch, skb);
+ sch->q.qlen--;
+ qdisc_bstats_update(sch, skb);
+
+ return skb;
+ }
+ return NULL;
+}
+
+static void cbs_reset(struct Qdisc *sch)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+
+ qdisc_reset(q->qdisc);
+}
+
+static const struct nla_policy cbs_policy[TCA_CBS_MAX + 1] = {
+ [TCA_CBS_PARMS] = { .len = sizeof(struct tc_cbs_qopt) },
+};
+
+static int cbs_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+ struct tc_cbs_qopt_offload cbs = { };
+ struct nlattr *tb[TCA_CBS_MAX + 1];
+ const struct net_device_ops *ops;
+ struct tc_cbs_qopt *qopt;
+ struct net_device *dev;
+ int err;
+
+ err = nla_parse_nested(tb, TCA_CBS_MAX, opt, cbs_policy, NULL);
+ if (err < 0)
+ return err;
+
+ err = -EINVAL;
+ if (!tb[TCA_CBS_PARMS])
+ goto done;
+
+ qopt = nla_data(tb[TCA_CBS_PARMS]);
+
+ dev = qdisc_dev(sch);
+ ops = dev->netdev_ops;
+
+ /* FIXME: this means that we can only install this qdisc
+ * "under" mqprio. Do we need a more generic way to retrieve
+ * the queue, or do we pass the netdev_queue to the driver?
+ */
+ cbs.queue = TC_H_MIN(sch->parent) - 1 - netdev_get_num_tc(dev);
+
+ cbs.enable = 1;
+ cbs.hicredit = qopt->hicredit;
+ cbs.locredit = qopt->locredit;
+ cbs.idleslope = qopt->idleslope;
+ cbs.sendslope = qopt->sendslope;
+
+ err = -ENOTSUPP;
+ if (!ops->ndo_setup_tc)
+ goto done;
+
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CBS, &cbs);
+ if (err < 0)
+ goto done;
+
+ q->queue = cbs.queue;
+ q->hicredit = cbs.hicredit;
+ q->locredit = cbs.locredit;
+ q->idleslope = cbs.idleslope;
+ q->sendslope = cbs.sendslope;
+
+done:
+ return err;
+}
+
+static int cbs_init(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+
+ if (!opt)
+ return -EINVAL;
+
+ q->qdisc = fifo_create_dflt(sch, &pfifo_qdisc_ops, 1024);
+ qdisc_hash_add(q->qdisc, true);
+
+ return cbs_change(sch, opt);
+}
+
+static void cbs_destroy(struct Qdisc *sch)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+ struct tc_cbs_qopt_offload cbs = { };
+ struct net_device *dev;
+ int err;
+
+ q->hicredit = 0;
+ q->locredit = 0;
+ q->idleslope = 0;
+ q->sendslope = 0;
+
+ dev = qdisc_dev(sch);
+
+ cbs.queue = q->queue;
+ cbs.enable = 0;
+
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CBS, &cbs);
+ if (err < 0)
+ pr_warn("Couldn't reset queue %d to default values\n",
+ cbs.queue);
+
+ qdisc_destroy(q->qdisc);
+}
+
+static int cbs_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+ struct nlattr *nest;
+ struct tc_cbs_qopt opt;
+
+ sch->qstats.backlog = q->qdisc->qstats.backlog;
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (!nest)
+ goto nla_put_failure;
+
+ opt.hicredit = q->hicredit;
+ opt.locredit = q->locredit;
+ opt.sendslope = q->sendslope;
+ opt.idleslope = q->idleslope;
+
+ if (nla_put(skb, TCA_CBS_PARMS, sizeof(opt), &opt))
+ goto nla_put_failure;
+
+ return nla_nest_end(skb, nest);
+
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
+ return -1;
+}
+
+static int cbs_dump_class(struct Qdisc *sch, unsigned long cl,
+ struct sk_buff *skb, struct tcmsg *tcm)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+
+ tcm->tcm_handle |= TC_H_MIN(1);
+ tcm->tcm_info = q->qdisc->handle;
+
+ return 0;
+}
+
+static int cbs_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+ struct Qdisc **old)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+
+ if (!new)
+ new = &noop_qdisc;
+
+ *old = qdisc_replace(sch, new, &q->qdisc);
+ return 0;
+}
+
+static struct Qdisc *cbs_leaf(struct Qdisc *sch, unsigned long arg)
+{
+ struct cbs_sched_data *q = qdisc_priv(sch);
+
+ return q->qdisc;
+}
+
+static unsigned long cbs_find(struct Qdisc *sch, u32 classid)
+{
+ return 1;
+}
+
+static int cbs_delete(struct Qdisc *sch, unsigned long arg)
+{
+ return 0;
+}
+
+static void cbs_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+{
+ if (!walker->stop) {
+ if (walker->count >= walker->skip)
+ if (walker->fn(sch, 1, walker) < 0) {
+ walker->stop = 1;
+ return;
+ }
+ walker->count++;
+ }
+}
+
+static const struct Qdisc_class_ops cbs_class_ops = {
+ .graft = cbs_graft,
+ .leaf = cbs_leaf,
+ .find = cbs_find,
+ .delete = cbs_delete,
+ .walk = cbs_walk,
+ .dump = cbs_dump_class,
+};
+
+static struct Qdisc_ops cbs_qdisc_ops __read_mostly = {
+ .next = NULL,
+ .cl_ops = &cbs_class_ops,
+ .id = "cbs",
+ .priv_size = sizeof(struct cbs_sched_data),
+ .enqueue = cbs_enqueue,
+ .dequeue = cbs_dequeue,
+ .peek = qdisc_peek_dequeued,
+ .init = cbs_init,
+ .reset = cbs_reset,
+ .destroy = cbs_destroy,
+ .change = cbs_change,
+ .dump = cbs_dump,
+ .owner = THIS_MODULE,
+};
+
+static int __init cbs_module_init(void)
+{
+ return register_qdisc(&cbs_qdisc_ops);
+}
+
+static void __exit cbs_module_exit(void)
+{
+ unregister_qdisc(&cbs_qdisc_ops);
+}
+module_init(cbs_module_init)
+module_exit(cbs_module_exit)
+MODULE_LICENSE("GPL");
--
2.14.1
^ permalink raw reply related
* [RFC net-next 4/5] sample: Add TSN Talker and Listener examples
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Jesus Sanchez-Palencia, jhs, xiyou.wangcong, jiri,
intel-wired-lan, andre.guedes, ivan.briano, boon.leong.ong,
richardcochran, Vinicius Costa Gomes
In-Reply-To: <20170901012625.14838-1-vinicius.gomes@intel.com>
From: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
Add two examples so one can easily test a 'TSN distributed system'
running with standard kernel interfaces. Both 'talker' and 'listener'
sides are provided, and use a AF_PACKET for Tx / Rx of frames.
Running the examples is rather simple.
For the talker, just the interface and SO_PRIORITY are expected as
parameters:
$ ./talker -i enp3s0 -p 3
For the listener, only the interface is needed:
$ ./listener -i enp3s0
The multicast MAC address being used is currently hardcoded on both
examples for simplicity.
Note that the listener side uses a BPF filter so only frames sent to
the correct "stream" destination address are received by the socket.
If you modify the address used by the talker, you must also adapt
the BPF filter otherwise no frames will be received by the socket.
The listener example will print the rate of packets reception after
every 1 second. This makes it easier to verify if the bandwidth
configured for a traffic class is being respected or not.
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Signed-off-by: Iván Briano <ivan.briano@intel.com>
---
samples/tsn/listener.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++
samples/tsn/talker.c | 136 ++++++++++++++++++++++++++
2 files changed, 390 insertions(+)
create mode 100644 samples/tsn/listener.c
create mode 100644 samples/tsn/talker.c
diff --git a/samples/tsn/listener.c b/samples/tsn/listener.c
new file mode 100644
index 000000000000..2d17bdfbea99
--- /dev/null
+++ b/samples/tsn/listener.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <alloca.h>
+#include <argp.h>
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <linux/filter.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+
+#define MAX_FRAME_SIZE 1500
+
+/* XXX: If this address is changed, the BPF filter must be adjusted. */
+static uint8_t multicast_macaddr[] = { 0xBB, 0xAA, 0xBB, 0xAA, 0xBB, 0xAA };
+static char ifname[IFNAMSIZ];
+static uint64_t data_count;
+static int arg_count;
+
+/*
+ * BPF Filter so we only receive frames from the destination MAC address of our
+ * SRP stream. This is hardcoded in multicast_macaddr[].
+ */
+static struct sock_filter dst_addr_filter[] = {
+ { 0x20, 0, 0, 0000000000 }, /* Load DST address: first 32bits only */
+ { 0x15, 0, 3, 0xbbaabbaa }, /* Compare with first 32bits from MAC */
+ { 0x28, 0, 0, 0x00000004 }, /* Load DST address: remaining 16bits */
+ { 0x15, 0, 1, 0x0000bbaa }, /* Compare with last 16bits from MAC */
+ { 0x06, 0, 0, 0xffffffff },
+ { 0x06, 0, 0, 0000000000 }, /* Ret 0. Jump here if any mismatches. */
+};
+
+/* BPF program */
+static struct sock_fprog bpf = {
+ .len = 6, /* Number of instructions on BPF filter */
+ .filter = dst_addr_filter,
+};
+
+static struct argp_option options[] = {
+ {"ifname", 'i', "IFNAME", 0, "Network Interface" },
+ { 0 }
+};
+
+static error_t parser(int key, char *arg, struct argp_state *s)
+{
+ switch (key) {
+ case 'i':
+ strncpy(ifname, arg, sizeof(ifname) - 1);
+ arg_count++;
+ break;
+ case ARGP_KEY_END:
+ if (arg_count < 1)
+ argp_failure(s, 1, 0, "Options missing. Check --help");
+ break;
+ }
+
+ return 0;
+}
+
+static struct argp argp = { options, parser };
+
+static int setup_1s_timer(void)
+{
+ struct itimerspec tspec = { 0 };
+ int fd, res;
+
+ fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd < 0) {
+ perror("Couldn't create timer");
+ return -1;
+ }
+
+ tspec.it_value.tv_sec = 1;
+ tspec.it_interval.tv_sec = 1;
+
+ res = timerfd_settime(fd, 0, &tspec, NULL);
+ if (res < 0) {
+ perror("Couldn't set timer");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static int setup_socket(void)
+{
+ struct sockaddr_ll sk_addr = {
+ .sll_family = AF_PACKET,
+ .sll_protocol = htons(ETH_P_TSN),
+ };
+ struct packet_mreq mreq;
+ struct ifreq req;
+ int fd, res;
+
+ fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_TSN));
+ if (fd < 0) {
+ perror("Couldn't open socket");
+ return -1;
+ }
+
+ res = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf));
+ if (res < 0) {
+ perror("Couldn't attach bpf filter");
+ goto err;
+ }
+
+ strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
+ res = ioctl(fd, SIOCGIFINDEX, &req);
+ if (res < 0) {
+ perror("Couldn't get interface index");
+ goto err;
+ }
+
+ sk_addr.sll_ifindex = req.ifr_ifindex;
+ res = bind(fd, (struct sockaddr *) &sk_addr, sizeof(sk_addr));
+ if (res < 0) {
+ perror("Couldn't bind() to interface");
+ goto err;
+ }
+
+ /* Use PACKET_ADD_MEMBERSHIP to add a binding to the Multicast Addr */
+ mreq.mr_ifindex = sk_addr.sll_ifindex;
+ mreq.mr_type = PACKET_MR_MULTICAST;
+ mreq.mr_alen = ETH_ALEN;
+ memcpy(&mreq.mr_address, multicast_macaddr, ETH_ALEN);
+
+ res = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+ &mreq, sizeof(struct packet_mreq));
+ if (res < 0) {
+ perror("Couldn't set PACKET_ADD_MEMBERSHIP");
+ goto err;
+ }
+
+ return fd;
+
+err:
+ close(fd);
+ return -1;
+}
+
+static void recv_packet(int fd)
+{
+ uint8_t *data = alloca(MAX_FRAME_SIZE);
+ ssize_t n = recv(fd, data, MAX_FRAME_SIZE, 0);
+
+ if (n < 0) {
+ perror("Failed to receive data");
+ return;
+ }
+
+ if (n != MAX_FRAME_SIZE)
+ printf("Size mismatch: expected %d, got %zd\n",
+ MAX_FRAME_SIZE, n);
+
+ data_count += n;
+}
+
+static void report_bw(int fd)
+{
+ uint64_t expirations;
+ ssize_t n = read(fd, &expirations, sizeof(uint64_t));
+
+ if (n < 0) {
+ perror("Couldn't read timerfd");
+ return;
+ }
+
+ if (expirations != 1)
+ printf("Something went wrong with timerfd\n");
+
+ /* Report how much data was received in 1s. */
+ printf("Data rate: %zu kbps\n", (data_count * 8) / 1000);
+
+ data_count = 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int sk_fd, timer_fd, res;
+ struct pollfd fds[2];
+
+ argp_parse(&argp, argc, argv, 0, NULL, NULL);
+
+ sk_fd = setup_socket();
+ if (sk_fd < 0)
+ return 1;
+
+ timer_fd = setup_1s_timer();
+ if (timer_fd < 0) {
+ close(sk_fd);
+ return 1;
+ }
+
+ fds[0].fd = sk_fd;
+ fds[0].events = POLLIN;
+ fds[1].fd = timer_fd;
+ fds[1].events = POLLIN;
+
+ printf("Waiting for packets...\n");
+
+ while (1) {
+ res = poll(fds, 2, -1);
+ if (res < 0) {
+ perror("Error on poll()");
+ goto err;
+ }
+
+ if (fds[0].revents & POLLIN)
+ recv_packet(fds[0].fd);
+
+ if (fds[1].revents & POLLIN)
+ report_bw(fds[1].fd);
+ }
+
+err:
+ close(timer_fd);
+ close(sk_fd);
+ return 1;
+}
diff --git a/samples/tsn/talker.c b/samples/tsn/talker.c
new file mode 100644
index 000000000000..35e6f99b48f6
--- /dev/null
+++ b/samples/tsn/talker.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <alloca.h>
+#include <argp.h>
+#include <arpa/inet.h>
+#include <inttypes.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#define MAX_FRAME_SIZE 1500
+
+static uint8_t multicast_macaddr[] = { 0xBB, 0xAA, 0xBB, 0xAA, 0xBB, 0xAA };
+static char ifname[IFNAMSIZ];
+static int prio = -1;
+static int arg_count;
+
+static struct argp_option options[] = {
+ {"ifname", 'i', "IFNAME", 0, "Network Interface" },
+ {"prio", 'p', "NUM", 0, "SO_PRIORITY to be set in socket" },
+ { 0 }
+};
+
+static error_t parser(int key, char *arg, struct argp_state *s)
+{
+ switch (key) {
+ case 'i':
+ strncpy(ifname, arg, sizeof(ifname) - 1);
+ arg_count++;
+ break;
+ case 'p':
+ prio = atoi(arg);
+ if (prio < 0)
+ argp_failure(s, 1, 0, "Priority must be >=0\n");
+ arg_count++;
+ break;
+ case ARGP_KEY_END:
+ if (arg_count < 2)
+ argp_failure(s, 1, 0,
+ "Options missing. Check --help\n");
+ break;
+ }
+
+ return 0;
+}
+
+static struct argp argp = { options, parser };
+
+int main(int argc, char *argv[])
+{
+ struct sockaddr_ll dst_ll_addr = {
+ .sll_family = AF_PACKET,
+ .sll_protocol = htons(ETH_P_TSN),
+ .sll_halen = ETH_ALEN,
+ };
+ struct ifreq req;
+ uint8_t *payload;
+ int fd, res;
+
+ argp_parse(&argp, argc, argv, 0, NULL, NULL);
+
+ fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_TSN));
+ if (fd < 0) {
+ perror("Couldn't open socket");
+ return 1;
+ }
+
+ strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
+ res = ioctl(fd, SIOCGIFINDEX, &req);
+ if (res < 0) {
+ perror("Couldn't get interface index");
+ goto err;
+ }
+
+ dst_ll_addr.sll_ifindex = req.ifr_ifindex;
+ memcpy(&dst_ll_addr.sll_addr, multicast_macaddr, ETH_ALEN);
+
+ res = setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
+ if (res < 0) {
+ perror("Couldn't set priority");
+ goto err;
+ }
+
+ payload = alloca(MAX_FRAME_SIZE);
+ memset(payload, 0xBE, MAX_FRAME_SIZE);
+
+ printf("Sending packets...\n");
+
+ while (1) {
+ ssize_t n = sendto(fd, payload, MAX_FRAME_SIZE, 0,
+ (struct sockaddr *) &dst_ll_addr,
+ sizeof(dst_ll_addr));
+
+ if (n < 0)
+ perror("Failed to send data");
+
+ /* Sleep for 500us to avoid starvation from a 20Mbps stream. */
+ usleep(500);
+ }
+
+err:
+ close(fd);
+ return 1;
+}
--
2.14.1
^ permalink raw reply related
* [RFC net-next 5/5] samples/tsn: Add script for calculating CBS config
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Andre Guedes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
In-Reply-To: <20170901012625.14838-1-vinicius.gomes@intel.com>
From: Andre Guedes <andre.guedes@intel.com>
Add a script that takes as input the parameters of the Credit-based
shaper used on FQTSS - link rate, max frame size of best effort
traffic, idleslope and maximum frame size of the time-sensitive
traffic class - for SR classes A and B, and calculates how the CBS
qdisc must be configured for each traffic class.
For example, if you want to have Class A with a bandwidth of 300 Mbps
and Class B of 200 Mbps, and the max frame size of both classes'
traffic is 1500 bytes:
$ ./calculate_cbs_params.py -A 300000 -a 1500 -B 200000 -b 1500
would give you the correct cbs qdisc config command lines to be used.
This script is just a helper to ease testing of the TSN samples -
talker and listener - and shouldn't be taken as highly accurate.
Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
---
samples/tsn/calculate_cbs_params.py | 112 ++++++++++++++++++++++++++++++++++++
1 file changed, 112 insertions(+)
create mode 100755 samples/tsn/calculate_cbs_params.py
diff --git a/samples/tsn/calculate_cbs_params.py b/samples/tsn/calculate_cbs_params.py
new file mode 100755
index 000000000000..9c46210b699f
--- /dev/null
+++ b/samples/tsn/calculate_cbs_params.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2017, Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Intel Corporation nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import argparse
+import math
+import sys
+
+def print_cbs_params_for_class_a(args):
+ idleslope = args.idleslope_a
+ sendslope = idleslope - args.link_speed
+
+ # According to 802.1Q-2014 spec, Annex L, hiCredit and
+ # loCredit for SR class A are calculated following the
+ # equations L-10 and L-12, respectively.
+ hicredit = math.ceil(idleslope * args.frame_non_sr / args.link_speed)
+ locredit = math.ceil(sendslope * args.frame_a / args.link_speed)
+
+ print("Class A --> # tc qdisc replace dev IFACE parent ID cbs " \
+ "locredit %d hicredit %d sendslope %d idleslope %d" % \
+ (locredit, hicredit, sendslope, idleslope))
+
+def print_cbs_params_for_class_b(args):
+ idleslope = args.idleslope_b
+ sendslope = idleslope - args.link_speed
+
+ # Annex L doesn't present a straightforward equation to
+ # calculate hiCredit for Class B so we have to derive it
+ # based on generic equations presented in that Annex.
+ #
+ # L-3 is the primary equation to calculate hiCredit. Section
+ # L.2 states that the 'maxInterferenceSize' for SR class B
+ # is the maximum burst size for SR class A plus the
+ # maxInterferenceSize from SR class A (which is equal to the
+ # maximum frame from non-SR traffic).
+ #
+ # The maximum burst size for SR class A equation is shown in
+ # L-16. Merging L-16 into L-3 we get the resulting equation
+ # which calculates hiCredit B (refer to section L.3 in case
+ # you're not familiar with the legend):
+ #
+ # hiCredit B = Rb * ( Mo Ma )
+ # ---------- + ------
+ # Ro - Ra Ro
+ #
+ hicredit = math.ceil(idleslope * \
+ ((args.frame_non_sr / (args.link_speed - args.idleslope_a)) + \
+ (args.frame_a / args.link_speed)))
+
+ # loCredit B is calculated following equation L-2.
+ locredit = math.ceil(sendslope * args.frame_b / args.link_speed)
+
+ print("Class B --> # tc qdisc replace dev IFACE parent ID cbs " \
+ "locredit %d hicredit %d sendslope %d idleslope %d" % \
+ (locredit, hicredit, sendslope, idleslope))
+
+def main():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('-S', dest='link_speed', default=1000000.0, type=float,
+ help='Link speed in kbps (default=1000000)')
+ parser.add_argument('-s', dest='frame_non_sr', default=1500.0, type=float,
+ help='Maximum frame size from non-SR traffic (MTU size'
+ ' usually, default=1500)')
+ parser.add_argument('-A', dest='idleslope_a', default=0, type=float,
+ help='Idleslope for SR class A in kbps')
+ parser.add_argument('-a', dest='frame_a', default=0, type=float,
+ help='Maximum frame size for SR class A traffic')
+ parser.add_argument('-B', dest='idleslope_b', default=0, type=float,
+ help='Idleslope for SR class B in kbps')
+ parser.add_argument('-b', dest='frame_b', default=0, type=float,
+ help='Maximum frame size for SR class B traffic')
+
+ args = parser.parse_args()
+
+ if not len(sys.argv) > 1:
+ parser.print_help()
+ else:
+ print("\nConfiguration lines to be used are:")
+
+ if args.idleslope_a > 0:
+ print_cbs_params_for_class_a(args)
+
+ if args.idleslope_b > 0:
+ print_cbs_params_for_class_b(args)
+
+
+if __name__ == "__main__":
+ main()
--
2.14.1
^ permalink raw reply related
* [RFC iproute2 1/2] update headers with CBS API [RFC]
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
andre.guedes, ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
include/linux/pkt_sched.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 099bf552..ba6c9a54 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -871,4 +871,33 @@ struct tc_pie_xstats {
__u32 maxq; /* maximum queue size */
__u32 ecn_mark; /* packets marked with ecn*/
};
+
+/* CBS */
+/* FIXME: this is only for usage with ndo_setup_tc(), this should be
+ * in another header someplace else. Is pkt_cls.h the right place?
+ */
+struct tc_cbs_qopt_offload {
+ __u8 enable;
+ __s32 queue;
+ __s32 hicredit;
+ __s32 locredit;
+ __s32 idleslope;
+ __s32 sendslope;
+};
+
+struct tc_cbs_qopt {
+ __s32 hicredit;
+ __s32 locredit;
+ __s32 idleslope;
+ __s32 sendslope;
+};
+
+enum {
+ TCA_CBS_UNSPEC,
+ TCA_CBS_PARMS,
+ __TCA_CBS_MAX,
+};
+
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+
#endif
--
2.14.1
^ permalink raw reply related
* [RFC iproute2 2/2] tc: Add support for the CBS qdisc
From: Vinicius Costa Gomes @ 2017-09-01 1:26 UTC (permalink / raw)
To: netdev
Cc: Vinicius Costa Gomes, jhs, xiyou.wangcong, jiri, intel-wired-lan,
andre.guedes, ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran
In-Reply-To: <20170901012646.14939-1-vinicius.gomes@intel.com>
The Credit Based Shaper (CBS) queueing discipline allows bandwidth
reservation with sub-milisecond precision. It is defined by the
802.1Q-2014 specification (section 8.6.8.2 and Annex L).
The syntax is:
tc qdisc add dev DEV parent NODE cbs locredit <LOCREDIT> hicredit
<HICREDIT> sendslope <SENDSLOPE> idleslope <IDLESLOPE>
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
tc/Makefile | 1 +
tc/q_cbs.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 135 insertions(+)
create mode 100644 tc/q_cbs.c
diff --git a/tc/Makefile b/tc/Makefile
index a9b4b8e6..f0091217 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -73,6 +73,7 @@ TCMODULES += q_hhf.o
TCMODULES += q_clsact.o
TCMODULES += e_bpf.o
TCMODULES += f_matchall.o
+TCMODULES += q_cbs.o
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)
diff --git a/tc/q_cbs.c b/tc/q_cbs.c
new file mode 100644
index 00000000..0120e838
--- /dev/null
+++ b/tc/q_cbs.c
@@ -0,0 +1,134 @@
+/*
+ * q_tbf.c TBF.
+ *
+ * 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.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... tbf hicredit BYTES locredit BYTES sendslope BPS idleslope BPS\n");
+}
+
+static void explain1(const char *arg, const char *val)
+{
+ fprintf(stderr, "cbs: illegal value for \"%s\": \"%s\"\n", arg, val);
+}
+
+static int cbs_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
+{
+ int ok = 0;
+ struct tc_cbs_qopt opt = {};
+ struct rtattr *tail;
+
+ while (argc > 0) {
+ if (matches(*argv, "hicredit") == 0) {
+ NEXT_ARG();
+ if (opt.hicredit) {
+ fprintf(stderr, "cbs: duplicate \"hicredit\" specification\n");
+ return -1;
+ }
+ if (get_s32(&opt.hicredit, *argv, 0)) {
+ explain1("hicredit", *argv);
+ return -1;
+ }
+ ok++;
+ } else if (matches(*argv, "locredit") == 0) {
+ NEXT_ARG();
+ if (opt.locredit) {
+ fprintf(stderr, "cbs: duplicate \"locredit\" specification\n");
+ return -1;
+ }
+ if (get_s32(&opt.locredit, *argv, 0)) {
+ explain1("locredit", *argv);
+ return -1;
+ }
+ ok++;
+ } else if (matches(*argv, "sendslope") == 0) {
+ NEXT_ARG();
+ if (opt.sendslope) {
+ fprintf(stderr, "cbs: duplicate \"sendslope\" specification\n");
+ return -1;
+ }
+ if (get_s32(&opt.sendslope, *argv, 0)) {
+ explain1("sendslope", *argv);
+ return -1;
+ }
+ ok++;
+ } else if (matches(*argv, "idleslope") == 0) {
+ NEXT_ARG();
+ if (opt.idleslope) {
+ fprintf(stderr, "cbs: duplicate \"idleslope\" specification\n");
+ return -1;
+ }
+ if (get_s32(&opt.idleslope, *argv, 0)) {
+ explain1("idleslope", *argv);
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
+ } else {
+ fprintf(stderr, "cbs: unknown parameter \"%s\"\n", *argv);
+ explain();
+ return -1;
+ }
+ argc--; argv++;
+ }
+
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ addattr_l(n, 2024, TCA_CBS_PARMS, &opt, sizeof(opt));
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ return 0;
+}
+
+static int cbs_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct rtattr *tb[TCA_TBF_MAX+1];
+ struct tc_cbs_qopt *qopt;
+
+ if (opt == NULL)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_CBS_MAX, opt);
+
+ if (tb[TCA_CBS_PARMS] == NULL)
+ return -1;
+
+ qopt = RTA_DATA(tb[TCA_CBS_PARMS]);
+ if (RTA_PAYLOAD(tb[TCA_CBS_PARMS]) < sizeof(*qopt))
+ return -1;
+
+ fprintf(f, "hicredit %d ", qopt->hicredit);
+ fprintf(f, "locredit %d ", qopt->locredit);
+ fprintf(f, "sendslope %d ", qopt->sendslope);
+ fprintf(f, "idleslope %d ", qopt->idleslope);
+
+ return 0;
+}
+
+struct qdisc_util cbs_qdisc_util = {
+ .id = "cbs",
+ .parse_qopt = cbs_parse_opt,
+ .print_qopt = cbs_print_opt,
+};
--
2.14.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox