* Re: [PATCH net-next 1/3] net:tracepoint: replace tcp_set_state tracepoint with sock_set_state tracepoint
From: Yafang Shao @ 2017-12-13 9:50 UTC (permalink / raw)
To: Song Liu
Cc: David Miller, marcelo.leitner@gmail.com, edumazet@google.com,
Cong Wang, mingo@redhat.com, kuznet@ms2.inr.ac.ru,
yoshfuji@linux-ipv6.org, Steven Rostedt, Brendan Gregg,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <662FAEA6-5A62-4950-8D6D-66776C35E8FE@fb.com>
2017-12-13 9:19 GMT+08:00 Song Liu <songliubraving@fb.com>:
>
>> On Dec 10, 2017, at 7:31 AM, Yafang Shao <laoar.shao@gmail.com> wrote:
>>
>> As sk_state is a common field for struct sock, so the state
>> transition should not be a TCP specific feature.
>> So I rename tcp_set_state tracepoint to sock_set_state tracepoint with
>> some minor changes and move it into file trace/events/sock.h.
>>
>> The minor changes against on the original tcp_set_state tracepoint:
>> - Protocol name is printed to distinguish which protocol it is belonging
>> to
>> - The macros defined in the file are undefed at the end of this file as
>> they are only used in this file
>>
>> Two helpers are introduced to trace sk_state transition
>> - void sk_state_store(struct sock *sk, int state);
>> - void sk_set_state(struct sock *sk, int state);
>>
>> As trace header should not be included in other header files,
>> so they are defined in sock.c.
>>
>> The protocol such as SCTP maybe compiled as a ko, hence export
>> sk_set_state().
>>
>> Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
>> ---
>> include/net/sock.h | 15 ++-----
>> include/trace/events/sock.h | 95 +++++++++++++++++++++++++++++++++++++++++
>> include/trace/events/tcp.h | 76 ---------------------------------
>> net/core/sock.c | 13 ++++++
>> net/ipv4/inet_connection_sock.c | 4 +-
>> net/ipv4/inet_hashtables.c | 2 +-
>> net/ipv4/tcp.c | 4 --
>> 7 files changed, 114 insertions(+), 95 deletions(-)
>>
>> diff --git a/include/net/sock.h b/include/net/sock.h
>> index 79e1a2c..b307b60 100644
>> --- a/include/net/sock.h
>> +++ b/include/net/sock.h
>> @@ -2348,18 +2348,9 @@ static inline int sk_state_load(const struct sock *sk)
>> return smp_load_acquire(&sk->sk_state);
>> }
>>
>> -/**
>> - * sk_state_store - update sk->sk_state
>> - * @sk: socket pointer
>> - * @newstate: new state
>> - *
>> - * Paired with sk_state_load(). Should be used in contexts where
>> - * state change might impact lockless readers.
>> - */
>> -static inline void sk_state_store(struct sock *sk, int newstate)
>> -{
>> - smp_store_release(&sk->sk_state, newstate);
>> -}
>> +/* For sock_set_state tracepoint */
>> +void sk_state_store(struct sock *sk, int newstate);
>> +void sk_set_state(struct sock *sk, int state);
>>
>> void sock_enable_timestamp(struct sock *sk, int flag);
>> int sock_get_timestamp(struct sock *, struct timeval __user *);
>> diff --git a/include/trace/events/sock.h b/include/trace/events/sock.h
>> index ec4dade..2728892 100644
>> --- a/include/trace/events/sock.h
>> +++ b/include/trace/events/sock.h
>> @@ -6,7 +6,33 @@
>> #define _TRACE_SOCK_H
>>
>> #include <net/sock.h>
>> +#include <net/ipv6.h>
>> #include <linux/tracepoint.h>
>> +#include <linux/ipv6.h>
>> +#include <linux/tcp.h>
>> +
>> +#define inet_protocol_name(protocol) {IPPROTO_##protocol, #protocol}
>> +#define show_inet_protocol_name(val) \
>> + __print_symbolic(val, \
>> + inet_protocol_name(TCP), \
>> + inet_protocol_name(DCCP), \
>> + inet_protocol_name(SCTP))
>> +
>> +#define tcp_state_name(state) { state, #state }
>> +#define show_tcp_state_name(val) \
>> + __print_symbolic(val, \
>> + tcp_state_name(TCP_ESTABLISHED), \
>> + tcp_state_name(TCP_SYN_SENT), \
>> + tcp_state_name(TCP_SYN_RECV), \
>> + tcp_state_name(TCP_FIN_WAIT1), \
>> + tcp_state_name(TCP_FIN_WAIT2), \
>> + tcp_state_name(TCP_TIME_WAIT), \
>> + tcp_state_name(TCP_CLOSE), \
>> + tcp_state_name(TCP_CLOSE_WAIT), \
>> + tcp_state_name(TCP_LAST_ACK), \
>> + tcp_state_name(TCP_LISTEN), \
>> + tcp_state_name(TCP_CLOSING), \
>> + tcp_state_name(TCP_NEW_SYN_RECV))
>
> Please include Steven's fix to export names to user space:
>
> https://patchwork.kernel.org/patch/10052201/
>
OK.
>
>> TRACE_EVENT(sock_rcvqueue_full,
>>
>> @@ -63,6 +89,75 @@
>> __entry->rmem_alloc)
>> );
>>
>> +TRACE_EVENT(sock_set_state,
>> +
>> + TP_PROTO(const struct sock *sk, const int oldstate, const int newstate),
>> +
>> + TP_ARGS(sk, oldstate, newstate),
>> +
>> + TP_STRUCT__entry(
>> + __field(const void *, skaddr)
>> + __field(int, oldstate)
>> + __field(int, newstate)
>> + __field(__u16, sport)
>> + __field(__u16, dport)
>> + __field(__u8, protocol);
>> + __array(__u8, saddr, 4)
>> + __array(__u8, daddr, 4)
>> + __array(__u8, saddr_v6, 16)
>> + __array(__u8, daddr_v6, 16)
>> + ),
>> +
>> + TP_fast_assign(
>> + struct inet_sock *inet = inet_sk(sk);
>> + struct in6_addr *pin6;
>> + __be32 *p32;
>> +
>> + __entry->skaddr = sk;
>> + __entry->oldstate = oldstate;
>> + __entry->newstate = newstate;
>> +
>> + __entry->protocol = sk->sk_protocol;
>> + __entry->sport = ntohs(inet->inet_sport);
>> + __entry->dport = ntohs(inet->inet_dport);
>> +
>> + p32 = (__be32 *) __entry->saddr;
>> + *p32 = inet->inet_saddr;
>> +
>> + p32 = (__be32 *) __entry->daddr;
>> + *p32 = inet->inet_daddr;
>> +
>> +#if IS_ENABLED(CONFIG_IPV6)
>> + if (sk->sk_family == AF_INET6) {
>> + pin6 = (struct in6_addr *)__entry->saddr_v6;
>> + *pin6 = sk->sk_v6_rcv_saddr;
>> + pin6 = (struct in6_addr *)__entry->daddr_v6;
>> + *pin6 = sk->sk_v6_daddr;
>> + } else
>> +#endif
>> + {
>> + pin6 = (struct in6_addr *)__entry->saddr_v6;
>> + ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
>> + pin6 = (struct in6_addr *)__entry->daddr_v6;
>> + ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
>> + }
>> + ),
>> +
>> + TP_printk("protocol=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4"
>> + "saddrv6=%pI6c daddrv6=%pI6c oldstate=%s newstate=%s",
>> + show_inet_protocol_name(__entry->protocol),
>> + __entry->sport, __entry->dport,
>> + __entry->saddr, __entry->daddr,
>> + __entry->saddr_v6, __entry->daddr_v6,
>> + show_tcp_state_name(__entry->oldstate),
>> + show_tcp_state_name(__entry->newstate))
>> +);
>> +
>> +#undef show_tcp_state_name
>> +#undef tcp_state_name
>> +#undef show_inet_protocol_name
>> +#undef inet_protocol_name
>> +
>> #endif /* _TRACE_SOCK_H */
>>
>> /* This part must be outside protection */
>> diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
>> index 07cccca..7399399 100644
>> --- a/include/trace/events/tcp.h
>> +++ b/include/trace/events/tcp.h
>> @@ -9,22 +9,6 @@
>> #include <linux/tracepoint.h>
>> #include <net/ipv6.h>
>>
>> -#define tcp_state_name(state) { state, #state }
>> -#define show_tcp_state_name(val) \
>> - __print_symbolic(val, \
>> - tcp_state_name(TCP_ESTABLISHED), \
>> - tcp_state_name(TCP_SYN_SENT), \
>> - tcp_state_name(TCP_SYN_RECV), \
>> - tcp_state_name(TCP_FIN_WAIT1), \
>> - tcp_state_name(TCP_FIN_WAIT2), \
>> - tcp_state_name(TCP_TIME_WAIT), \
>> - tcp_state_name(TCP_CLOSE), \
>> - tcp_state_name(TCP_CLOSE_WAIT), \
>> - tcp_state_name(TCP_LAST_ACK), \
>> - tcp_state_name(TCP_LISTEN), \
>> - tcp_state_name(TCP_CLOSING), \
>> - tcp_state_name(TCP_NEW_SYN_RECV))
>> -
>> /*
>> * tcp event with arguments sk and skb
>> *
>> @@ -177,66 +161,6 @@
>> TP_ARGS(sk)
>> );
>>
>> -TRACE_EVENT(tcp_set_state,
>> -
>> - TP_PROTO(const struct sock *sk, const int oldstate, const int newstate),
>> -
>> - TP_ARGS(sk, oldstate, newstate),
>> -
>> - TP_STRUCT__entry(
>> - __field(const void *, skaddr)
>> - __field(int, oldstate)
>> - __field(int, newstate)
>> - __field(__u16, sport)
>> - __field(__u16, dport)
>> - __array(__u8, saddr, 4)
>> - __array(__u8, daddr, 4)
>> - __array(__u8, saddr_v6, 16)
>> - __array(__u8, daddr_v6, 16)
>> - ),
>> -
>> - TP_fast_assign(
>> - struct inet_sock *inet = inet_sk(sk);
>> - struct in6_addr *pin6;
>> - __be32 *p32;
>> -
>> - __entry->skaddr = sk;
>> - __entry->oldstate = oldstate;
>> - __entry->newstate = newstate;
>> -
>> - __entry->sport = ntohs(inet->inet_sport);
>> - __entry->dport = ntohs(inet->inet_dport);
>> -
>> - p32 = (__be32 *) __entry->saddr;
>> - *p32 = inet->inet_saddr;
>> -
>> - p32 = (__be32 *) __entry->daddr;
>> - *p32 = inet->inet_daddr;
>> -
>> -#if IS_ENABLED(CONFIG_IPV6)
>> - if (sk->sk_family == AF_INET6) {
>> - pin6 = (struct in6_addr *)__entry->saddr_v6;
>> - *pin6 = sk->sk_v6_rcv_saddr;
>> - pin6 = (struct in6_addr *)__entry->daddr_v6;
>> - *pin6 = sk->sk_v6_daddr;
>> - } else
>> -#endif
>> - {
>> - pin6 = (struct in6_addr *)__entry->saddr_v6;
>> - ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
>> - pin6 = (struct in6_addr *)__entry->daddr_v6;
>> - ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
>> - }
>> - ),
>> -
>> - TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c oldstate=%s newstate=%s",
>> - __entry->sport, __entry->dport,
>> - __entry->saddr, __entry->daddr,
>> - __entry->saddr_v6, __entry->daddr_v6,
>> - show_tcp_state_name(__entry->oldstate),
>> - show_tcp_state_name(__entry->newstate))
>> -);
>> -
>> TRACE_EVENT(tcp_retransmit_synack,
>>
>> TP_PROTO(const struct sock *sk, const struct request_sock *req),
>> diff --git a/net/core/sock.c b/net/core/sock.c
>> index c0b5b2f..ee0c1bc 100644
>> --- a/net/core/sock.c
>> +++ b/net/core/sock.c
>> @@ -2859,6 +2859,19 @@ int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp)
>> }
>> EXPORT_SYMBOL(sock_get_timestampns);
>>
>> +void sk_state_store(struct sock *sk, int state)
>> +{
>> + trace_sock_set_state(sk, sk->sk_state, state);
>> + smp_store_release(&sk->sk_state, state);
>> +}
>> +
>> +void sk_set_state(struct sock *sk, int state)
>> +{
>> + trace_sock_set_state(sk, sk->sk_state, state);
>> + sk->sk_state = state;
>> +}
>> +EXPORT_SYMBOL(sk_set_state);
>
> These two functions are short. Can we keep this in sock.h?
sock.h is included in trace/events/sock.h, so it will cause compile
error if hese two functions are defined in sock.h.
>
> Thanks,
> Song
>
>> +
>> void sock_enable_timestamp(struct sock *sk, int flag)
>> {
>> if (!sock_flag(sk, flag)) {
>> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
>> index 4ca46dc..001f7b0 100644
>> --- a/net/ipv4/inet_connection_sock.c
>> +++ b/net/ipv4/inet_connection_sock.c
>> @@ -783,7 +783,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
>> if (newsk) {
>> struct inet_connection_sock *newicsk = inet_csk(newsk);
>>
>> - newsk->sk_state = TCP_SYN_RECV;
>> + sk_set_state(newsk, TCP_SYN_RECV);
>> newicsk->icsk_bind_hash = NULL;
>>
>> inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
>> @@ -888,7 +888,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
>> return 0;
>> }
>>
>> - sk->sk_state = TCP_CLOSE;
>> + sk_set_state(sk, TCP_CLOSE);
>> return err;
>> }
>> EXPORT_SYMBOL_GPL(inet_csk_listen_start);
>> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
>> index f6f5810..5973693 100644
>> --- a/net/ipv4/inet_hashtables.c
>> +++ b/net/ipv4/inet_hashtables.c
>> @@ -544,7 +544,7 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk)
>> sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
>> } else {
>> percpu_counter_inc(sk->sk_prot->orphan_count);
>> - sk->sk_state = TCP_CLOSE;
>> + sk_set_state(sk, TCP_CLOSE);
>> sock_set_flag(sk, SOCK_DEAD);
>> inet_csk_destroy_sock(sk);
>> }
>> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
>> index 1803116..000504f 100644
>> --- a/net/ipv4/tcp.c
>> +++ b/net/ipv4/tcp.c
>> @@ -283,8 +283,6 @@
>> #include <asm/ioctls.h>
>> #include <net/busy_poll.h>
>>
>> -#include <trace/events/tcp.h>
>> -
>> struct percpu_counter tcp_orphan_count;
>> EXPORT_SYMBOL_GPL(tcp_orphan_count);
>>
>> @@ -2040,8 +2038,6 @@ void tcp_set_state(struct sock *sk, int state)
>> {
>> int oldstate = sk->sk_state;
>>
>> - trace_tcp_set_state(sk, oldstate, state);
>> -
>> switch (state) {
>> case TCP_ESTABLISHED:
>> if (oldstate != TCP_ESTABLISHED)
>> --
>> 1.8.3.1
>>
>
^ permalink raw reply
* [PATCH 1/2] qla3xxx: Fix a possible sleep-in-atomic bug in ql_sem_spinlock
From: Jia-Ju Bai @ 2017-12-13 10:01 UTC (permalink / raw)
To: Dept-GELinuxNICDev; +Cc: netdev, linux-kernel, Jia-Ju Bai
The driver may sleep under a spinlock.
The function call paths are:
ql_get_full_dup (acquire the spinlock)
ql_sem_spinlock
ssleep --> may sleep
ql_get_auto_cfg_status (acquire the spinlock)
ql_sem_spinlock
ssleep --> may sleep
To fix it, ssleep is replaced with mdelay.
This bug is found by my static analysis tool(DSAC) and checked by my code review.
Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
drivers/net/ethernet/qlogic/qla3xxx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 9e5264d..8ad3e24 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -115,7 +115,7 @@ static int ql_sem_spinlock(struct ql3_adapter *qdev,
value = readl(&port_regs->CommonRegs.semaphoreReg);
if ((value & (sem_mask >> 16)) == sem_bits)
return 0;
- ssleep(1);
+ mdelay(1000);
} while (--seconds);
return -1;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/2] qla3xxx: Fix a possible sleep-in-atomic bug in ql_wait_for_drvr_lock
From: Jia-Ju Bai @ 2017-12-13 10:01 UTC (permalink / raw)
To: Dept-GELinuxNICDev; +Cc: netdev, linux-kernel, Jia-Ju Bai
The driver may sleep under a spinlock.
The function call path is:
ql_adapter_up (acquire the spinlock)
ql_wait_for_drvr_lock
ssleep --> may sleep
To fix it, ssleep is replaced with mdelay.
This bug is found by my static analysis tool(DSAC) and checked by my code review.
Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
drivers/net/ethernet/qlogic/qla3xxx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
index 8ad3e24..7994d04 100644
--- a/drivers/net/ethernet/qlogic/qla3xxx.c
+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -155,7 +155,7 @@ static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev)
"driver lock acquired\n");
return 1;
}
- ssleep(1);
+ mdelay(1000);
} while (++i < 10);
netdev_err(qdev->ndev, "Timed out waiting for driver lock...\n");
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH net-next] net: stmmac: fix broken dma_interrupt handling for multi-queues
From: Joao Pinto @ 2017-12-13 10:04 UTC (permalink / raw)
To: Niklas Cassel, Joao.Pinto, Giuseppe Cavallaro, Alexandre Torgue
Cc: Niklas Cassel, netdev, linux-kernel, Jose Abreu
In-Reply-To: <20171207225610.15572-1-niklas.cassel@axis.com>
Hi Niklas,
Às 10:56 PM de 12/7/2017, Niklas Cassel escreveu:
> There is nothing that says that number of TX queues == number of RX
> queues. E.g. the ARTPEC-6 SoC has 2 TX queues and 1 RX queue.
>
Yes you are totally right. Our Hardware was configured with 4RX queues and 4TX
queues and that lead us not to detect some of the issues that you are reporting.
We are already developing a prototype with a number of RX Queue different from
TX Queues.
We would like to resume a discussion that we had a couple of months ago, about
Synopsys testing stmmac in market boards. Currently I am the new Software Team
Manager and so I would like to say to you that we are interested in testing the
driver in several boards to assure quality in the stmmac driver, since we will
be constantly developing the new features for future HW releases.
If some vendors can send us sample boards it would be great, if we have to buy
some, it would be very useful to have reference suggestions.
Thanks and best regards,
Joao
> This code is obviously wrong:
> for (chan = 0; chan < tx_channel_count; chan++) {
> struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
>
> priv->rx_queue has size MTL_MAX_RX_QUEUES, so this will send an
> uninitialized napi_struct to __napi_schedule(), causing us to
> crash in net_rx_action(), because napi_struct->poll is zero.
>
> [12846.759880] Unable to handle kernel NULL pointer dereference at virtual address 00000000
> [12846.768014] pgd = (ptrval)
> [12846.770742] [00000000] *pgd=39ec7831, *pte=00000000, *ppte=00000000
> [12846.777023] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM
> [12846.782942] Modules linked in:
> [12846.785998] CPU: 0 PID: 161 Comm: dropbear Not tainted 4.15.0-rc2-00285-gf5fb5f2f39a7 #36
> [12846.794177] Hardware name: Axis ARTPEC-6 Platform
> [12846.798879] task: (ptrval) task.stack: (ptrval)
> [12846.803407] PC is at 0x0
> [12846.805942] LR is at net_rx_action+0x274/0x43c
> [12846.810383] pc : [<00000000>] lr : [<80bff064>] psr: 200e0113
> [12846.816648] sp : b90d9ae8 ip : b90d9ae8 fp : b90d9b44
> [12846.821871] r10: 00000008 r9 : 0013250e r8 : 00000100
> [12846.827094] r7 : 0000012c r6 : 00000000 r5 : 00000001 r4 : bac84900
> [12846.833619] r3 : 00000000 r2 : b90d9b08 r1 : 00000000 r0 : bac84900
>
> Since each DMA channel can be used for rx and tx simultaneously,
> the current code should probably be rewritten so that napi_struct is
> embedded in a new struct stmmac_channel.
> That way, stmmac_poll() can call stmmac_tx_clean() on just the tx queue
> where we got the IRQ, instead of looping through all tx queues.
> This is also how the xgbe driver does it (another driver for this IP).
>
> Fixes: c22a3f48ef99 ("net: stmmac: adding multiple napi mechanism")
> Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 54 +++++++++++++++++++----
> 1 file changed, 46 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index d7250539d0bd..c52a9963c19d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1997,22 +1997,60 @@ static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
> static void stmmac_dma_interrupt(struct stmmac_priv *priv)
> {
> u32 tx_channel_count = priv->plat->tx_queues_to_use;
> - int status;
> + u32 rx_channel_count = priv->plat->rx_queues_to_use;
> + u32 channels_to_check = tx_channel_count > rx_channel_count ?
> + tx_channel_count : rx_channel_count;
> u32 chan;
> + bool poll_scheduled = false;
> + int status[channels_to_check];
> +
> + /* Each DMA channel can be used for rx and tx simultaneously, yet
> + * napi_struct is embedded in struct stmmac_rx_queue rather than in a
> + * stmmac_channel struct.
> + * Because of this, stmmac_poll currently checks (and possibly wakes)
> + * all tx queues rather than just a single tx queue.
> + */
> + for (chan = 0; chan < channels_to_check; chan++)
> + status[chan] = priv->hw->dma->dma_interrupt(priv->ioaddr,
> + &priv->xstats,
> + chan);
>
> - for (chan = 0; chan < tx_channel_count; chan++) {
> - struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
> + for (chan = 0; chan < rx_channel_count; chan++) {
> + if (likely(status[chan] & handle_rx)) {
> + struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
>
> - status = priv->hw->dma->dma_interrupt(priv->ioaddr,
> - &priv->xstats, chan);
> - if (likely((status & handle_rx)) || (status & handle_tx)) {
> if (likely(napi_schedule_prep(&rx_q->napi))) {
> stmmac_disable_dma_irq(priv, chan);
> __napi_schedule(&rx_q->napi);
> + poll_scheduled = true;
> + }
> + }
> + }
> +
> + /* If we scheduled poll, we already know that tx queues will be checked.
> + * If we didn't schedule poll, see if any DMA channel (used by tx) has a
> + * completed transmission, if so, call stmmac_poll (once).
> + */
> + if (!poll_scheduled) {
> + for (chan = 0; chan < tx_channel_count; chan++) {
> + if (status[chan] & handle_tx) {
> + /* It doesn't matter what rx queue we choose
> + * here. We use 0 since it always exists.
> + */
> + struct stmmac_rx_queue *rx_q =
> + &priv->rx_queue[0];
> +
> + if (likely(napi_schedule_prep(&rx_q->napi))) {
> + stmmac_disable_dma_irq(priv, chan);
> + __napi_schedule(&rx_q->napi);
> + }
> + break;
> }
> }
> + }
>
> - if (unlikely(status & tx_hard_error_bump_tc)) {
> + for (chan = 0; chan < tx_channel_count; chan++) {
> + if (unlikely(status[chan] & tx_hard_error_bump_tc)) {
> /* Try to bump up the dma threshold on this failure */
> if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
> (tc <= 256)) {
> @@ -2029,7 +2067,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
> chan);
> priv->xstats.threshold = tc;
> }
> - } else if (unlikely(status == tx_hard_error)) {
> + } else if (unlikely(status[chan] == tx_hard_error)) {
> stmmac_tx_err(priv, chan);
> }
> }
>
^ permalink raw reply
* Re: [PATCH v3 09/33] nds32: Cache and TLB routines
From: Greentime Hu @ 2017-12-13 10:04 UTC (permalink / raw)
To: Guo Ren
Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev,
Vincent Chen, DTML, Al Viro, David Howells, Will Deacon,
Daniel Lezcano, linux-serial-u79uwXL29TY76Z2rM5mHXA,
Geert Uytterhoeven, Linus Walleij, Mark Rutland, Greg KH
In-Reply-To: <20171213094548.GA23563@gary-OptiPlex-3050>
2017-12-13 17:45 GMT+08:00 Guo Ren <ren_guo-Y+KPrCd2zL4AvxtiuMwx3w@public.gmane.org>:
> Hello,
>
> CPU team could improve the tlbop_*. Eg: Design a hardware
> internal flag bit for SR_TLB_VPN, tlbop_* will invalid it and mtsr
> SR_TLB_VPN will valid it.
>
> So:
> On Wed, Dec 13, 2017 at 05:03:33PM +0800, Greentime Hu wrote:
>> mtsr addr1 NDS32_SR_TLB_VPN
>> interrupt coming
>> mtsr addr2 NDS32_SR_TLB_VPN <- TLB_VPN has been set to addr2
> mtsr SR_TLB_VPN will valid the flag bit
>> tlbop_rwr(*pte);
> tlbop_rwr will invalid SR_TLB_VPN flag bit
>> interrupt finish
>> tlbop_rwr(*pte); <- it will use the wrong TLB_VPN
> Because SR_TLB_VPN is in a invalid state, no operation happen on
> tlbop_rwr.
>
> Then they are atomic safe ,no spin_lock_irq need.
> :)
>
Oh, I see. I may propose this idea to our ARCH colleagues for the next
version design.
Many thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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
* Re: [PATCH iproute2] Show 'external' link mode in output
From: Sergei Shtylyov @ 2017-12-13 10:05 UTC (permalink / raw)
To: Phil Dibowitz, netdev; +Cc: phild
In-Reply-To: <20171212202319.GA7066@ipom.com>
Hello!
On 12/12/2017 11:23 PM, Phil Dibowitz wrote:
> Recently `external` support was added to the tunnel drivers, but there is no way
> to introspect this from userspace. This adds support for that.
>
> Now `ip -details link` shows it:
>
> ```
> 7: tunl60@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group
> default qlen 1
> link/tunnel6 :: brd :: promiscuity 0
> ip6tnl external any remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
> ```
>
> Signed-off-by: Phil Dibowitz <phil@ipom.com>
> ---
> ip/link_ip6tnl.c | 3 +++
> ip/link_iptnl.c | 3 +++
> 2 files changed, 6 insertions(+)
>
> diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
> index 43287ab..5d0efc8 100644
> --- a/ip/link_ip6tnl.c
> +++ b/ip/link_ip6tnl.c
> @@ -345,6 +345,9 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
> if (!tb)
> return;
>
> + if (tb[IFLA_IPTUN_COLLECT_METADATA])
> + print_bool(PRINT_ANY, "external", "external ", true);
> +
The original code is indented with tabs, you're using spaces. Not good. :-)
> if (tb[IFLA_IPTUN_FLAGS])
> flags = rta_getattr_u32(tb[IFLA_IPTUN_FLAGS]);
>
> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
> index 4940b8b..e345b5c 100644
> --- a/ip/link_iptnl.c
> +++ b/ip/link_iptnl.c
> @@ -393,6 +393,9 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
> if (!tb)
> return;
>
> + if (tb[IFLA_IPTUN_COLLECT_METADATA])
> + print_bool(PRINT_ANY, "external", "external ", true);
> +
> if (tb[IFLA_IPTUN_REMOTE]) {
> unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
>
Here as well...
MBR, Sergei
^ permalink raw reply
* [BUG] atlx: a possible sleep-in-atomic bug in atl1_intr
From: Jia-Ju Bai @ 2017-12-13 10:07 UTC (permalink / raw)
To: jcliburn, chris.snook, davem, geliangtang, keescook, khoroshilov,
edumazet
Cc: netdev, Linux Kernel Mailing List
The driver may sleep in the interrupt handler.
The function call path is:
atl1_intr (interrupt handler)
atlx_irq_disable
synchronize_irq --> may sleep
I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and checked
by my code review.
Thanks,
Jia-Ju Bai
^ permalink raw reply
* [BUG] tulip/de4x5: a possible sleep-in-atomic bug in de4x5_interrupt
From: Jia-Ju Bai @ 2017-12-13 10:13 UTC (permalink / raw)
To: davem, Stephen Hemminger, keescook, dhowells, allen.lkml,
johannes.berg, arvind.yadav.cs
Cc: netdev, linux-parisc, Linux Kernel Mailing List
According to drivers/net/ethernet/dec/tulip/de4x5.c, the driver may
sleep in the interrupt handler.
The function call path is:
de4x5_interrupt (interrupt handler)
synchronize_irq --> may sleep
I do not find a good way to fix it, so I only report.
This possible bug is found by my static analysis tool (DSAC) and checked
by my code review.
Thanks,
Jia-Ju Bai
^ permalink raw reply
* Re: AF_VSOCK connection refused errno
From: Jorgen S. Hansen @ 2017-12-13 10:28 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: Dexuan Cui, netdev@vger.kernel.org
In-Reply-To: <20171212155352.GA10090@stefanha-x1.localdomain>
> On Dec 12, 2017, at 4:53 PM, Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> When connect(2) fails because the peer is not listening the virtio vsock
> transport returns ECONNRESET. I believe the VMCI transport does the
> same (based on code inspection).
>
> Jorgen: Can you confirm this VMCI transport behavior?
Yes, that is correct.
> I'd like to change to ECONNREFUSED for all transports because developers
> will be surprised when they get ECONNRESET. It makes porting AF_INET
> code harder.
>
> On the other hand, it may be too late to fix this if there userspace
> applications that rely on ECONNRESET? I'm not aware of any such
> applications myself.
In the past, I’ve explained to customers that an ECONNRESET error on connect
can indicate that the peer isn’t listening on the dest address. Whether they went
and used that information isn’t clear, but changing this behavior now would
risk breaking applications. While it is unfortunate that we deviate from INET in
this case, I would prefer it to stay as is.
Thanks,
Jorgen
^ permalink raw reply
* RE: [PATCH V3 net-next 3/8] net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support
From: Salil Mehta @ 2017-12-13 10:35 UTC (permalink / raw)
To: Philippe Ombredanne
Cc: David S. Miller, Zhuangyuzeng (Yisen), lipeng (Y), Salil Mehta,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, LKML,
linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linuxarm
In-Reply-To: <CAOFm3uGs2yO4jfFZSVzZMbE6cbgzzkSBDPFAO_fbt-1XKx7FpQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Philippe,
> -----Original Message-----
> From: Philippe Ombredanne [mailto:pombredanne@nexb.com]
> Sent: Tuesday, December 12, 2017 10:41 PM
> To: Salil Mehta <salil.mehta@huawei.com>
> Cc: David S. Miller <davem@davemloft.net>; Zhuangyuzeng (Yisen)
> <yisen.zhuang@huawei.com>; lipeng (Y) <lipeng321@huawei.com>; Salil
> Mehta <mehta.salil.lnk@gmail.com>; netdev@vger.kernel.org; LKML <linux-
> kernel@vger.kernel.org>; linux-rdma@vger.kernel.org; Linuxarm
> <linuxarm@huawei.com>
> Subject: Re: [PATCH V3 net-next 3/8] net: hns3: Add HNS3 VF
> HCL(Hardware Compatibility Layer) Support
>
> Dear Salil,
>
> On Tue, Dec 12, 2017 at 6:52 PM, Salil Mehta <salil.mehta@huawei.com>
> wrote:
> > This patch adds the support of hardware compatibiltiy layer to the
> > HNS3 VF Driver. This layer implements various {set|get} operations
> > over MAC address for a virtual port, RSS related configuration,
> > fetches the link status info from PF, does various VLAN related
> > configuration over the virtual port, queries the statistics from
> > the hardware etc.
> >
> > This layer can directly interact with hardware through the
> > IMP(Integrated Mangement Processor) interface or can use mailbox
> > to interact with the PF driver.
> >
> > Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
> > Signed-off-by: lipeng <lipeng321@huawei.com>
> > ---
> > Patch V3: Addressed SPDX change requested by Philippe Ombredanne
> > Link: https://lkml.org/lkml/2017/12/8/874
> > Patch V2: Addressed some internal comments
> > Patch V1: Initial Submit
> > ---
> > .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 1490
> ++++++++++++++++++++
> > .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 164 +++
> > 2 files changed, 1654 insertions(+)
> > create mode 100644
> drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
> > create mode 100644
> drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
> >
> > diff --git
> a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
> b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
> > new file mode 100644
> > index 0000000..ff55f4c
> > --- /dev/null
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
> > @@ -0,0 +1,1490 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2016-2017 Hisilicon Limited.
> > + */
>
> This is just me nitpicking and this is entirely up to you.... but in
> such a simple case you could go all the way too:
>
> > +// SPDX-License-Identifier: GPL-2.0+
> > +// Copyright (c) 2016-2017 Hisilicon Limited.
>
> In this case this can make the thing look more consistent.
Ok I can do that, no issues with that.
As such, I changed according to Jonathan Corbet's article on LWN.
https://lwn.net/Articles/739183/
and also searched the SPDX identifier usage in the existing kernel
and I can see community following different ways including
(*) For Kernel C files:
// SPDX-License-Identifier: GPL-2.0+
// Copyright (c) 2016-2017 Hisilicon Limited.
OR
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2016-2017 Hisilicon Limited.
*/
OR
// SPDX-License-Identifier: GPL-2.0+
(*) For Kernel h files:
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2016-2017 Hisilicon Limited. */
(*) For Makefiles
# SPDX-License-Identifier: GPL-2.0+
OR
# id: Makefile
# SPDX-License-Identifier: GPL-2.0+
I could also make out from different articles, including from the below,
Linus suggesting moving to "//" type instead of starred ones for headers.
It looks SPDX change is still a suggestion?
> See also Linus commentaries about this [1][2][3][4]
>
> [1] https://lkml.org/lkml/2017/11/25/133
> [2] https://lkml.org/lkml/2017/11/25/125
> [3] https://lkml.org/lkml/2017/11/2/715
> [4] https://lkml.org/lkml/2017/11/2/805
Sure, thanks.
Salil
^ permalink raw reply
* [PATCH] macb: Fix a possible sleep-in-atomic bug in macb_tx_error_task
From: Jia-Ju Bai @ 2017-12-13 10:46 UTC (permalink / raw)
To: nicolas.ferre, rafalo, bfolta; +Cc: netdev, linux-kernel, Jia-Ju Bai
The driver may sleep under a spinlock.
The function call path is:
macb_tx_error_task (acquire the spinlock)
macb_halt_tx
usleep_range --> may sleep
To fix it, usleep_range is replaced with udelay.
This bug is found by my static analysis tool(DSAC) and checked by my code review.
Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
drivers/net/ethernet/cadence/macb_main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 72a67f7..b02c806 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -645,7 +645,7 @@ static int macb_halt_tx(struct macb *bp)
if (!(status & MACB_BIT(TGO)))
return 0;
- usleep_range(10, 250);
+ udelay(250);
} while (time_before(halt_time, timeout));
return -ETIMEDOUT;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] net: thunderx: add support for rgmii internal delay
From: Andrew Lunn @ 2017-12-13 11:10 UTC (permalink / raw)
To: Tim Harvey; +Cc: Sunil Goutham, netdev
In-Reply-To: <1513119114-17511-1-git-send-email-tharvey@gateworks.com>
> +void xcv_init_hw(int phy_mode)
> {
> u64 cfg;
>
> @@ -81,12 +81,31 @@ void xcv_init_hw(void)
> /* Wait for DLL to lock */
> msleep(1);
>
> - /* Configure DLL - enable or bypass
> - * TX no bypass, RX bypass
> - */
> + /* enable/bypass DLL providing MAC based internal TX/RX delays */
> cfg = readq_relaxed(xcv->reg_base + XCV_DLL_CTL);
> - cfg &= ~0xFF03;
> - cfg |= CLKRX_BYP;
> + cfg &= ~0xffff00;
> + switch (phy_mode) {
> + /* RX and TX delays are added by the MAC */
> + case PHY_INTERFACE_MODE_RGMII:
> + break;
> + /* internal RX and TX delays provided by the PHY */
> + case PHY_INTERFACE_MODE_RGMII_ID:
> + cfg |= CLKRX_BYP;
> + cfg |= CLKTX_BYP;
> + break;
> + /* internal RX delay provided by the PHY, the MAC
> + * should not add an RX delay in this case
> + */
> + case PHY_INTERFACE_MODE_RGMII_RXID:
> + cfg |= CLKRX_BYP;
> + break;
> + /* internal TX delay provided by the PHY, the MAC
> + * should not add an TX delay in this case
> + */
> + case PHY_INTERFACE_MODE_RGMII_TXID:
> + cfg |= CLKRX_BYP;
> + break;
> + }
Hi Tim
This i don't get. Normally, you leave the PHY to handle delays, if
needed. The MAC should not add any. Here you seem to assume a delay is
always needed, and if the PHY is not providing it, the MAC should.
Andrew
^ permalink raw reply
* [PATCH] ipv6: icmp6: Allow icmp messages to be looped back
From: Brendan McGrath @ 2017-12-13 11:14 UTC (permalink / raw)
To: David S . Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI, netdev,
linux-kernel
Cc: Brendan McGrath
One example of when an ICMPv6 packet is required to be looped back is
when a host acts as both a Multicast Listener and a Multicast Router.
A Multicast Router will listen on address ff02::16 for MLDv2 messages.
Currently, MLDv2 messages originating from a Multicast Listener running
on the same host as the Multicast Router are not being delivered to the
Multicast Router. This is due to dst.input being assigned the default
value of dst_discard.
This results in the packet being looped back but discarded before being
delivered to the Multicast Router.
This patch sets dst.input to ip6_input to ensure a looped back packet
is delivered to the Multicast Router.
Signed-off-by: Brendan McGrath <redmcg@redmandi.dyndns.org>
---
I considered putting this in mld_sendpack after the call to icmp6_dst_alloc
but it looks like igmp6_send could use this fix too.
In the end I followed the example set by addrconf_dst_alloc
net/ipv6/route.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b3f4d19..5c014ce 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2336,6 +2336,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
}
rt->dst.flags |= DST_HOST;
+ rt->dst.input = ip6_input;
rt->dst.output = ip6_output;
rt->rt6i_gateway = fl6->daddr;
rt->rt6i_dst.addr = fl6->daddr;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net-next 2/2] tools: bpftool: create "uninstall", "doc-uninstall" make targets
From: Arnaldo Carvalho de Melo @ 2017-12-13 11:16 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, oss-drivers, daniel, alexei.starovoitov, acme,
Quentin Monnet, Masahiro Yamada
In-Reply-To: <20171207230018.7510-3-jakub.kicinski@netronome.com>
Em Thu, Dec 07, 2017 at 03:00:18PM -0800, Jakub Kicinski escreveu:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Create two targets to remove executable and documentation that would
> have been previously installed with `make install` and `make
> doc-install`.
>
> Also create a "QUIET_UNINST" helper in tools/scripts/Makefile.include.
>
> Do not attempt to remove directories /usr/local/sbin and
> /usr/share/bash-completions/completions, even if they are empty, as
> those specific directories probably already existed on the system before
> we installed the program, and we do not wish to break other makefiles
> that might assume their existence. Do remvoe /usr/local/share/man/man8
> if empty however, as this directory does not seem to exist by default.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> ---
> For addition to tools/scripts/Makefile.include:
>
> CC: Arnaldo Carvalho de Melo <acme@redhat.com>
> CC: Masahiro Yamada <yamada.masahiro@socionext.com>
>
> tools/bpf/bpftool/Documentation/Makefile | 8 +++++++-
> tools/bpf/bpftool/Makefile | 12 ++++++++++--
> tools/scripts/Makefile.include | 1 +
> 3 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/tools/bpf/bpftool/Documentation/Makefile b/tools/bpf/bpftool/Documentation/Makefile
> index 71c17fab4f2f..c462a928e03d 100644
> --- a/tools/bpf/bpftool/Documentation/Makefile
> +++ b/tools/bpf/bpftool/Documentation/Makefile
> @@ -3,6 +3,7 @@ include ../../../scripts/utilities.mak
>
> INSTALL ?= install
> RM ?= rm -f
> +RMDIR ?= rmdir --ignore-fail-on-non-empty
>
> ifeq ($(V),1)
> Q =
> @@ -34,5 +35,10 @@ install: man
> $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir)
> $(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir)
>
> -.PHONY: man man8 clean install
> +uninstall:
> + $(call QUIET_UNINST, Documentation-man)
> + $(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8))
> + $(Q)$(RMDIR) $(DESTDIR)$(man8dir)
> +
> +.PHONY: man man8 clean install uninstall
> .DEFAULT_GOAL := man
> diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
> index 203ae2e14fbc..3f17ad317512 100644
> --- a/tools/bpf/bpftool/Makefile
> +++ b/tools/bpf/bpftool/Makefile
> @@ -70,6 +70,11 @@ install: $(OUTPUT)bpftool
> $(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(bash_compdir)
> $(Q)$(INSTALL) -m 0644 bash-completion/bpftool $(DESTDIR)$(bash_compdir)
>
> +uninstall:
> + $(call QUIET_UNINST, bpftool)
> + $(Q)$(RM) $(DESTDIR)$(prefix)/sbin/bpftool
> + $(Q)$(RM) $(DESTDIR)$(bash_compdir)/bpftool
> +
> doc:
> $(call descend,Documentation)
>
> @@ -79,8 +84,11 @@ install: $(OUTPUT)bpftool
> doc-install:
> $(call descend,Documentation,install)
>
> +doc-uninstall:
> + $(call descend,Documentation,uninstall)
> +
> FORCE:
>
> -.PHONY: all FORCE clean install
> -.PHONY: doc doc-clean doc-install
> +.PHONY: all FORCE clean install uninstall
> +.PHONY: doc doc-clean doc-install doc-uninstall
> .DEFAULT_GOAL := all
> diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
> index 3fab179b1aba..fcb3ed0be5f8 100644
> --- a/tools/scripts/Makefile.include
> +++ b/tools/scripts/Makefile.include
> @@ -99,5 +99,6 @@ ifneq ($(silent),1)
>
> QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
> QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
> + QUIET_UNINST = @printf ' UNINST %s\n' $1;
> endif
> endif
> --
> 2.15.1
^ permalink raw reply
* [bpf-next V1-RFC PATCH 00/14] xdp: new XDP rx-queue info concept
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, Jesper Dangaard Brouer, dsahern, gospo, bjorn.topel,
michael.chan
NOTICE: I send this as RFC to give driver developers a heads-up,
while I complete the testing of the drivers (which I have HW for).
I don't expect many changes before I post it officially.
There is a need for XDP to know more about the RX-queue a given XDP
frames have arrived on. For both the XDP bpf-prog and kernel side.
Instead of extending struct xdp_buff each time new info is needed,
this patchset takes a different approach. Struct xdp_buff is only
extended with a pointer to a struct xdp_rxq_info (allowing for easier
extending this later). This xdp_rxq_info contains information related
to how the driver have setup the individual RX-queue's. This is
read-mostly information, and all xdp_buff frames (in drivers
napi_poll) point to the same xdp_rxq_info (per RX-queue).
We stress this data/cache-line is for read-mostly info. This is NOT
for dynamic per packet info, use the data_meta for such use-cases.
This patchset start out small, and only expose ingress_ifindex and the
RX queue index to the XDP/BPF program. Access to tangible info like
the ingress ifindex and RX queue index, is fairly easy to comprehent.
The other future use-cases could allow XDP frames to be recycled back
to the originating device driver, by providing info on RX device and
queue number.
As XDP doesn't have driver feature flags, and eBPF code due to
bpf-tail-calls cannot determine that XDP driver invoke it, this
patchset have to update every driver that support XDP.
For driver developers (review individual driver patches!):
The xdp_rxq_info is tied to the drivers RX-ring(s). Whenever a RX-ring
modification require (temporary) stopping RX frames, then the
xdp_rxq_info should (likely) also be unregistred and re-registered,
especially if reallocating the pages in the ring. Make sure ethtool
set_channels does the right thing. When replacing XDP prog, if and
only if RX-ring need to be changed, then also re-register the
xdp_rxq_info.
I'm Cc'ing the individual driver patches to the registered maintainers.
Testing:
I've only tested the NIC drivers I have hardware for. The general
test procedure is to (DUT = Device Under Test):
(1) run pktgen script pktgen_sample04_many_flows.sh (against DUT),
(2) run samples/bpf program xdp_rxq_info --dev $DEV (on DUT)
(3) runtime modify NIC queue via ethtool -L (on DUT)
RFC notes/questions:
(A) Didn't update driver netdevsim, as it doesn't reference xdp_buff.
(B) Must I write a test for tools/testing/selftests/bpf/ ?
(C) The bnxt_en driver should re-register when changing ring layout
(D) Should xdp_rxq_info be SLAB allocated instead of embedding into drv structs?
(E) Should struct be named xdp_info instead for future (e.g TX) use-cases?
Patch based on git tree bpf-next (at commit 553a8f2f42):
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/
---
Jesper Dangaard Brouer (14):
xdp: base API for new XDP rx-queue info concept
xdp/mlx5: setup xdp_rxq_info and extend with qtype
i40e: setup xdp_rxq_info
ixgbe: setup xdp_rxq_info
xdp/qede: setup xdp_rxq_info and intro xdp_rxq_info_is_reg
mlx4: setup xdp_rxq_info
bnxt_en: setup xdp_rxq_info
nfp: setup xdp_rxq_info
thunderx: setup xdp_rxq_info
tun: setup xdp_rxq_info
virtio_net: setup xdp_rxq_info
xdp: generic XDP handling of xdp_rxq_info
bpf: finally expose xdp_rxq_info to XDP bpf-programs
samples/bpf: program demonstrating access to xdp_rxq_info
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 1
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 11
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 7
drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 2
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 18 +
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 3
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 11
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 3
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 13
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 4
drivers/net/ethernet/mellanox/mlx5/core/en.h | 4
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 14 +
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 1
drivers/net/ethernet/netronome/nfp/nfp_net.h | 5
.../net/ethernet/netronome/nfp/nfp_net_common.c | 10
drivers/net/ethernet/qlogic/qede/qede.h | 2
drivers/net/ethernet/qlogic/qede/qede_fp.c | 1
drivers/net/ethernet/qlogic/qede/qede_main.c | 12
drivers/net/tun.c | 25 +
drivers/net/virtio_net.c | 12
include/linux/filter.h | 2
include/linux/netdevice.h | 2
include/net/xdp.h | 69 +++
include/uapi/linux/bpf.h | 3
net/core/Makefile | 2
net/core/dev.c | 60 ++
net/core/filter.c | 19 +
net/core/xdp.c | 57 ++
samples/bpf/Makefile | 4
samples/bpf/xdp_rxq_info_kern.c | 96 ++++
samples/bpf/xdp_rxq_info_user.c | 533 ++++++++++++++++++++
34 files changed, 996 insertions(+), 24 deletions(-)
create mode 100644 include/net/xdp.h
create mode 100644 net/core/xdp.c
create mode 100644 samples/bpf/xdp_rxq_info_kern.c
create mode 100644 samples/bpf/xdp_rxq_info_user.c
^ permalink raw reply
* [bpf-next V1-RFC PATCH 01/14] xdp: base API for new XDP rx-queue info concept
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, Jesper Dangaard Brouer, dsahern, gospo, bjorn.topel,
michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
This patch only introduce the core data structures and API functions.
All XDP enabled drivers must use the API before this info can used.
There is a need for XDP to know more about the RX-queue a given XDP
frames have arrived on. For both the XDP bpf-prog and kernel side.
Instead of extending xdp_buff each time new info is needed, the patch
creates a separate read-mostly struct xdp_rxq_info, that contains this
info. We stress this data/cache-line is for read-only info. This is
NOT for dynamic per packet info, use the data_meta for such use-cases.
The performance advantage is this info can be setup at RX-ring init
time, instead of updating N-members in xdp_buff. A possible (driver
level) micro optimization is that xdp_buff->rxq assignment could be
done once per XDP/NAPI loop. The extra pointer deref only happens for
program needing access to this info (thus, no slowdown to existing
use-cases).
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
include/linux/filter.h | 2 ++
include/net/xdp.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
net/core/Makefile | 2 +-
net/core/xdp.c | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 include/net/xdp.h
create mode 100644 net/core/xdp.c
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 5feb441d3dd9..111107fcace6 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -19,6 +19,7 @@
#include <linux/cryptohash.h>
#include <linux/set_memory.h>
+#include <net/xdp.h>
#include <net/sch_generic.h>
#include <uapi/linux/filter.h>
@@ -496,6 +497,7 @@ struct xdp_buff {
void *data_end;
void *data_meta;
void *data_hard_start;
+ struct xdp_rxq_info *rxq;
};
/* Compute the linear packet data range [data, data_end) which
diff --git a/include/net/xdp.h b/include/net/xdp.h
new file mode 100644
index 000000000000..e4acd198fd60
--- /dev/null
+++ b/include/net/xdp.h
@@ -0,0 +1,45 @@
+/* include/net/xdp.h
+ *
+ * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
+ * Released under terms in GPL version 2. See COPYING.
+ */
+#ifndef __LINUX_NET_XDP_H__
+#define __LINUX_NET_XDP_H__
+
+/**
+ * DOC: XDP RX-queue information
+ *
+ * The XDP RX-queue info (xdp_rxq_info) is associated with the driver
+ * level RX-ring queues. It is information that is specific to how
+ * the driver have configured a given RX-ring queue.
+ *
+ * Each xdp_buff frame received in the driver carry a (pointer)
+ * reference to this xdp_rxq_info structure. This provides the XDP
+ * data-path read-access to RX-info for both kernel and bpf-side
+ * (limited subset).
+ *
+ * For now, direct access is only safe while running in NAPI/softirq
+ * context.
+ *
+ * The driver usage API is an init, register and unregister API.
+ *
+ * The struct is not directly tied to the XDP prog. A new XDP prog
+ * can be attached as long as it doesn't change the underlying
+ * RX-ring. If the RX-ring does change significantly, the NIC driver
+ * naturally need to stop the RX-ring before purging and reallocating
+ * memory. In that process the driver MUST call unregistor (which
+ * also apply for driver shutdown and unload). The init and register
+ * API is also mandatory during RX-ring setup.
+ */
+
+struct xdp_rxq_info {
+ struct net_device *dev;
+ u32 queue_index;
+ u32 reg_state;
+} ____cacheline_aligned; /* perf critical, avoid false-sharing */
+
+void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq);
+void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq);
+void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq);
+
+#endif /* __LINUX_NET_XDP_H__ */
diff --git a/net/core/Makefile b/net/core/Makefile
index 1fd0a9c88b1b..6dbbba8c57ae 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \
neighbour.o rtnetlink.o utils.o link_watch.o filter.o \
sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
- fib_notifier.o
+ fib_notifier.o xdp.o
obj-y += net-sysfs.o
obj-$(CONFIG_PROC_FS) += net-procfs.o
diff --git a/net/core/xdp.c b/net/core/xdp.c
new file mode 100644
index 000000000000..a9d2dd7b1ede
--- /dev/null
+++ b/net/core/xdp.c
@@ -0,0 +1,40 @@
+/* net/core/xdp.c
+ *
+ * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
+ * Released under terms in GPL version 2. See COPYING.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+
+#include <net/xdp.h>
+
+#define REG_STATE_NEW 0x0
+#define REG_STATE_REGISTRED 0x1
+#define REG_STATE_UNREGISTRED 0x2
+
+void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq)
+{
+ xdp_rxq->reg_state = REG_STATE_UNREGISTRED;
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg);
+
+void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq)
+{
+ if (xdp_rxq->reg_state == REG_STATE_REGISTRED) {
+ WARN(1, "Missing unregister, handled but fix driver\n");
+ xdp_rxq_info_unreg(xdp_rxq);
+ }
+ memset(xdp_rxq, 0, sizeof(*xdp_rxq));
+ xdp_rxq->queue_index = U32_MAX;
+ xdp_rxq->reg_state = REG_STATE_NEW;
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_init);
+
+void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq)
+{
+ WARN(!xdp_rxq->dev, "Missing net_device from driver");
+ WARN(xdp_rxq->queue_index == U32_MAX, "Miss queue_index from driver");
+ WARN(!(xdp_rxq->reg_state == REG_STATE_NEW),"API violation, miss init");
+ xdp_rxq->reg_state = REG_STATE_REGISTRED;
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_reg);
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 02/14] xdp/mlx5: setup xdp_rxq_info and extend with qtype
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, dsahern, Matan Barak, Saeed Mahameed,
Jesper Dangaard Brouer, gospo, bjorn.topel, michael.chan,
Tariq Toukan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
The mlx5 driver have a special drop-RQ queue (one per interface) that
simply drops all incoming traffic. It helps driver keep other HW
objects (flow steering) alive upon down/up operations. It is
temporarily pointed by flow steering objects during the interface
setup, and when interface is down. It lacks many fields that are set
in a regular RQ (for example its state is never switched to
MLX5_RQC_STATE_RDY). (Thanks to Tariq Toukan for explaination).
The XDP RX-queue info API is extended with a queue-type, and mlx5 uses
this kind of drop/sink-type (RXQ_TYPE_SINK) for this kind of sink queue.
Driver hook points for xdp_rxq_info:
* init+reg: mlx5e_alloc_rq()
* init+reg: mlx5e_alloc_drop_rq()
* unreg : mlx5e_free_rq()
Tested on actual hardware with samples/bpf program
Cc: Saeed Mahameed <saeedm@mellanox.com>
Cc: Matan Barak <matanb@mellanox.com>
Cc: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 ++++
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 14 +++++++++++++
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 1 +
include/net/xdp.h | 23 +++++++++++++++++++++
net/core/xdp.c | 6 +++++
5 files changed, 48 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index c0872b3284cb..fe10a042783b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -46,6 +46,7 @@
#include <linux/mlx5/transobj.h>
#include <linux/rhashtable.h>
#include <net/switchdev.h>
+#include <net/xdp.h>
#include "wq.h"
#include "mlx5_core.h"
#include "en_stats.h"
@@ -568,6 +569,9 @@ struct mlx5e_rq {
u32 rqn;
struct mlx5_core_dev *mdev;
struct mlx5_core_mkey umr_mkey;
+
+ /* XDP read-mostly */
+ struct xdp_rxq_info xdp_rxq;
} ____cacheline_aligned_in_smp;
struct mlx5e_channel {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 0f5c012de52e..ea44b5f25e11 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -582,6 +582,12 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
rq->ix = c->ix;
rq->mdev = mdev;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rq->xdp_rxq);
+ rq->xdp_rxq.dev = rq->netdev;
+ rq->xdp_rxq.queue_index = rq->ix;
+ xdp_rxq_info_reg(&rq->xdp_rxq);
+
rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
if (IS_ERR(rq->xdp_prog)) {
err = PTR_ERR(rq->xdp_prog);
@@ -695,6 +701,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
err_rq_wq_destroy:
if (rq->xdp_prog)
bpf_prog_put(rq->xdp_prog);
+ xdp_rxq_info_unreg(&rq->xdp_rxq);
mlx5_wq_destroy(&rq->wq_ctrl);
return err;
@@ -707,6 +714,8 @@ static void mlx5e_free_rq(struct mlx5e_rq *rq)
if (rq->xdp_prog)
bpf_prog_put(rq->xdp_prog);
+ xdp_rxq_info_unreg(&rq->xdp_rxq);
+
switch (rq->wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
mlx5e_rq_free_mpwqe_info(rq);
@@ -2768,6 +2777,11 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
if (err)
return err;
+ /* XDP RX-queue info for "Drop-RQ", packets never reach XDP */
+ xdp_rxq_info_init(&rq->xdp_rxq);
+ xdp_rxq_info_type(&rq->xdp_rxq, RXQ_TYPE_SINK);
+ xdp_rxq_info_reg(&rq->xdp_rxq);
+
rq->mdev = mdev;
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index 5b499c7a698f..7b38480811d4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -812,6 +812,7 @@ static inline int mlx5e_xdp_handle(struct mlx5e_rq *rq,
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + *len;
xdp.data_hard_start = va;
+ xdp.rxq = &rq->xdp_rxq;
act = bpf_prog_run_xdp(prog, &xdp);
switch (act) {
diff --git a/include/net/xdp.h b/include/net/xdp.h
index e4acd198fd60..5be560d943e1 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -36,10 +36,33 @@ struct xdp_rxq_info {
struct net_device *dev;
u32 queue_index;
u32 reg_state;
+ u32 qtype;
} ____cacheline_aligned; /* perf critical, avoid false-sharing */
void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq);
+/**
+ * DOC: XDP RX-queue type
+ *
+ * The XDP RX-queue info can have associated a type.
+ *
+ * @RXQ_TYPE_DEFAULT: default no specifik queue type need to be specified
+ *
+ * @RXQ_TYPE_SINK: indicate a fake queue that never reach XDP RX
+ * code. Some drivers have a need to maintain a lower layer
+ * RX-queue as a sink queue, while reconfiguring other RX-queues.
+ */
+#define RXQ_TYPE_DEFAULT 0
+#define RXQ_TYPE_SINK 1
+#define RXQ_TYPE_MAX RXQ_TYPE_SINK
+
+static inline
+void xdp_rxq_info_type(struct xdp_rxq_info *xdp_rxq, u32 qtype)
+{
+ BUILD_BUG_ON(qtype > RXQ_TYPE_MAX);
+ xdp_rxq->qtype = qtype;
+}
+
#endif /* __LINUX_NET_XDP_H__ */
diff --git a/net/core/xdp.c b/net/core/xdp.c
index a9d2dd7b1ede..2a111f5987f6 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -32,8 +32,14 @@ EXPORT_SYMBOL_GPL(xdp_rxq_info_init);
void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq)
{
+ if (xdp_rxq->qtype == RXQ_TYPE_SINK)
+ goto skip_content_check;
+
+ /* Check information setup by driver code */
WARN(!xdp_rxq->dev, "Missing net_device from driver");
WARN(xdp_rxq->queue_index == U32_MAX, "Miss queue_index from driver");
+
+skip_content_check:
WARN(!(xdp_rxq->reg_state == REG_STATE_NEW),"API violation, miss init");
xdp_rxq->reg_state = REG_STATE_REGISTRED;
}
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 03/14] i40e: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, Jesper Dangaard Brouer, intel-wired-lan, Jeff Kirsher,
dsahern, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
The i40e driver have a special "FDIR" RX-ring (I40E_VSI_FDIR) which is
a sideband channel for configuring/updating the flow director tables.
This (i40e_vsi_)type does not invoke XDP-ebpf code. Thus, mark this
type as a XDP RX-queue type RXQ_TYPE_SINK.
Driver hook points for xdp_rxq_info:
* init+reg: i40e_setup_rx_descriptors (via i40e_vsi_setup_rx_resources)
* unreg : i40e_free_rx_resources (via i40e_vsi_free_rx_resources)
Tested on actual hardware with samples/bpf program.
Cc: intel-wired-lan@lists.osuosl.org
Cc: Björn Töpel <bjorn.topel@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 18 +++++++++++++++++-
drivers/net/ethernet/intel/i40e/i40e_txrx.h | 3 +++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 4566d66ffc7c..d1bfc4232ca9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -27,6 +27,7 @@
#include <linux/prefetch.h>
#include <net/busy_poll.h>
#include <linux/bpf_trace.h>
+#include <net/xdp.h>
#include "i40e.h"
#include "i40e_trace.h"
#include "i40e_prototype.h"
@@ -1236,6 +1237,7 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
void i40e_free_rx_resources(struct i40e_ring *rx_ring)
{
i40e_clean_rx_ring(rx_ring);
+ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
rx_ring->xdp_prog = NULL;
kfree(rx_ring->rx_bi);
rx_ring->rx_bi = NULL;
@@ -1283,6 +1285,18 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring)
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rx_ring->xdp_rxq);
+
+ /* Flow director side channel does not invoke XDP/bpf */
+ if (rx_ring->vsi->type == I40E_VSI_FDIR)
+ xdp_rxq_info_type(&rx_ring->xdp_rxq, RXQ_TYPE_SINK);
+ else
+ rx_ring->xdp_rxq.dev = rx_ring->netdev;
+
+ rx_ring->xdp_rxq.queue_index = rx_ring->queue_index;
+ xdp_rxq_info_reg(&rx_ring->xdp_rxq);
+
rx_ring->xdp_prog = rx_ring->vsi->xdp_prog;
return 0;
@@ -2068,11 +2082,13 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
struct sk_buff *skb = rx_ring->skb;
u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);
bool failure = false, xdp_xmit = false;
+ struct xdp_buff xdp;
+
+ xdp.rxq = &rx_ring->xdp_rxq;
while (likely(total_rx_packets < (unsigned int)budget)) {
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
- struct xdp_buff xdp;
unsigned int size;
u16 vlan_tag;
u8 rx_ptype;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
index fbae1182e2ea..2d08760fc4ce 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -27,6 +27,8 @@
#ifndef _I40E_TXRX_H_
#define _I40E_TXRX_H_
+#include <net/xdp.h>
+
/* Interrupt Throttling and Rate Limiting Goodies */
#define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */
@@ -428,6 +430,7 @@ struct i40e_ring {
*/
struct i40e_channel *ch;
+ struct xdp_rxq_info xdp_rxq;
} ____cacheline_internodealigned_in_smp;
static inline bool ring_uses_build_skb(struct i40e_ring *ring)
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 04/14] ixgbe: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, dsahern, Alexander Duyck, intel-wired-lan, Jeff Kirsher,
Jesper Dangaard Brouer, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
Driver hook points for xdp_rxq_info:
* init+reg: ixgbe_setup_rx_resources()
* unreg : ixgbe_free_rx_resources()
Cc: intel-wired-lan@lists.osuosl.org
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Alexander Duyck <alexander.duyck@gmail.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 ++
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 11 ++++++++++-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 468c3555a629..8611763d6129 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -53,6 +53,7 @@
#include <linux/dca.h>
#endif
+#include <net/xdp.h>
#include <net/busy_poll.h>
/* common prefix used by pr_<> macros */
@@ -371,6 +372,7 @@ struct ixgbe_ring {
struct ixgbe_tx_queue_stats tx_stats;
struct ixgbe_rx_queue_stats rx_stats;
};
+ struct xdp_rxq_info xdp_rxq;
} ____cacheline_internodealigned_in_smp;
enum ixgbe_ring_f_enum {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 7737a05c717c..2a8196427776 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2318,12 +2318,14 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
#endif /* IXGBE_FCOE */
u16 cleaned_count = ixgbe_desc_unused(rx_ring);
bool xdp_xmit = false;
+ struct xdp_buff xdp;
+
+ xdp.rxq = &rx_ring->xdp_rxq;
while (likely(total_rx_packets < budget)) {
union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *rx_buffer;
struct sk_buff *skb;
- struct xdp_buff xdp;
unsigned int size;
/* return some buffers to hardware, one at a time is too slow */
@@ -6444,6 +6446,12 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rx_ring->xdp_rxq);
+ rx_ring->xdp_rxq.dev = adapter->netdev;
+ rx_ring->xdp_rxq.queue_index = rx_ring->queue_index;
+ xdp_rxq_info_reg(&rx_ring->xdp_rxq);
+
rx_ring->xdp_prog = adapter->xdp_prog;
return 0;
@@ -6541,6 +6549,7 @@ void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring)
ixgbe_clean_rx_ring(rx_ring);
rx_ring->xdp_prog = NULL;
+ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
vfree(rx_ring->rx_buffer_info);
rx_ring->rx_buffer_info = NULL;
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 05/14] xdp/qede: setup xdp_rxq_info and intro xdp_rxq_info_is_reg
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: bjorn.topel, netdev, Jesper Dangaard Brouer, Ariel Elior, dsahern,
gospo, everest-linux-l2, michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
The driver code qede_free_fp_array() depend on kfree() can be called
with a NULL pointer. This stems from the qede_alloc_fp_array()
function which either (kz)alloc memory for fp->txq or fp->rxq.
This also simplifies error handling code in case of memory allocation
failures, but xdp_rxq_info_unreg need to know the difference.
Introduce xdp_rxq_info_is_reg() to handle if a memory allocation fails
and detect this is the failure path by seeing that xdp_rxq_info was
not registred yet, which first happens after successful alloaction in
qede_init_fp().
Driver hook points for xdp_rxq_info:
* init+reg: qede_init_fp
* unreg : qede_free_fp_array
Tested on actual hardware with samples/bpf program.
Cc: everest-linux-l2@cavium.com
Cc: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/qlogic/qede/qede.h | 2 ++
drivers/net/ethernet/qlogic/qede/qede_fp.c | 1 +
drivers/net/ethernet/qlogic/qede/qede_main.c | 12 ++++++++++++
include/net/xdp.h | 1 +
net/core/xdp.c | 11 +++++++++++
5 files changed, 27 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index a3a70ade411f..62f47736511b 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -40,6 +40,7 @@
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/bpf.h>
+#include <net/xdp.h>
#include <linux/qed/qede_rdma.h>
#include <linux/io.h>
#ifdef CONFIG_RFS_ACCEL
@@ -345,6 +346,7 @@ struct qede_rx_queue {
u64 xdp_no_pass;
void *handle;
+ struct xdp_rxq_info xdp_rxq;
};
union db_prod {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 48ec4c56cddf..dafc079ab6b9 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1006,6 +1006,7 @@ static bool qede_rx_xdp(struct qede_dev *edev,
xdp.data = xdp.data_hard_start + *data_offset;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + *len;
+ xdp.rxq = &rxq->xdp_rxq;
/* Queues always have a full reset currently, so for the time
* being until there's atomic program replace just mark read
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 57332b3e5e64..a7264fdf4112 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -762,6 +762,12 @@ static void qede_free_fp_array(struct qede_dev *edev)
fp = &edev->fp_array[i];
kfree(fp->sb_info);
+ /* Handle mem alloc failure case where qede_init_fp
+ * didn't register xdp_rxq_info yet.
+ * Implicit only (fp->type & QEDE_FASTPATH_RX)
+ */
+ if (fp->rxq && xdp_rxq_info_is_reg(&fp->rxq->xdp_rxq))
+ xdp_rxq_info_unreg(&fp->rxq->xdp_rxq);
kfree(fp->rxq);
kfree(fp->xdp_tx);
kfree(fp->txq);
@@ -1498,6 +1504,12 @@ static void qede_init_fp(struct qede_dev *edev)
else
fp->rxq->data_direction = DMA_FROM_DEVICE;
fp->rxq->dev = &edev->pdev->dev;
+
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&fp->rxq->xdp_rxq);
+ fp->rxq->xdp_rxq.dev = edev->ndev;
+ fp->rxq->xdp_rxq.queue_index = fp->rxq->rxq_id;
+ xdp_rxq_info_reg(&fp->rxq->xdp_rxq);
}
if (fp->type & QEDE_FASTPATH_TX) {
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 5be560d943e1..106ec8ed4db5 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -42,6 +42,7 @@ struct xdp_rxq_info {
void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq);
void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq);
+bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq);
/**
* DOC: XDP RX-queue type
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 2a111f5987f6..f0203b8fc04c 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -44,3 +44,14 @@ void xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq)
xdp_rxq->reg_state = REG_STATE_REGISTRED;
}
EXPORT_SYMBOL_GPL(xdp_rxq_info_reg);
+
+bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq)
+{
+ if (!xdp_rxq) {
+ WARN(1, "API violation, xdp_rxq is NULL");
+ return false;
+ }
+
+ return (xdp_rxq->reg_state == REG_STATE_REGISTRED);
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_is_reg);
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 06/14] mlx4: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, dsahern, Jesper Dangaard Brouer, gospo, bjorn.topel,
michael.chan, Tariq Toukan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
Driver hook points for xdp_rxq_info:
* init+reg: mlx4_en_create_rx_ring
* unreg : mlx4_en_destroy_rx_ring
Cc: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 3 ++-
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 13 +++++++++++--
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 4 +++-
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 99051a294fa6..0cfcf3089ae4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2172,8 +2172,9 @@ static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
prof->rx_ring_size, priv->stride,
- node))
+ node, i))
goto err;
+
}
#ifdef CONFIG_RFS_ACCEL
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 85e28efcda33..2091c9734e6a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -262,7 +262,7 @@ void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev)
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring **pring,
- u32 size, u16 stride, int node)
+ u32 size, u16 stride, int node, int queue_index)
{
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_rx_ring *ring;
@@ -286,6 +286,12 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
ring->log_stride = ffs(ring->stride) - 1;
ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&ring->xdp_rxq);
+ ring->xdp_rxq.dev = priv->dev;
+ ring->xdp_rxq.queue_index = queue_index;
+ xdp_rxq_info_reg(&ring->xdp_rxq);
+
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
sizeof(struct mlx4_en_rx_alloc));
ring->rx_info = vzalloc_node(tmp, node);
@@ -318,6 +324,7 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
vfree(ring->rx_info);
ring->rx_info = NULL;
err_ring:
+ xdp_rxq_info_unreg(&ring->xdp_rxq);
kfree(ring);
*pring = NULL;
@@ -440,6 +447,7 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
lockdep_is_held(&mdev->state_lock));
if (old_prog)
bpf_prog_put(old_prog);
+ xdp_rxq_info_unreg(&ring->xdp_rxq);
mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
vfree(ring->rx_info);
ring->rx_info = NULL;
@@ -650,6 +658,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
int cq_ring = cq->ring;
bool doorbell_pending;
struct mlx4_cqe *cqe;
+ struct xdp_buff xdp;
int polled = 0;
int index;
@@ -664,6 +673,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
/* Protect accesses to: ring->xdp_prog, priv->mac_hash list */
rcu_read_lock();
xdp_prog = rcu_dereference(ring->xdp_prog);
+ xdp.rxq = &ring->xdp_rxq;
doorbell_pending = 0;
/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
@@ -748,7 +758,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
* read bytes but not past the end of the frag.
*/
if (xdp_prog) {
- struct xdp_buff xdp;
dma_addr_t dma;
void *orig_data;
u32 act;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 1856e279a7e0..bdfb4362b35a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -46,6 +46,7 @@
#endif
#include <linux/cpu_rmap.h>
#include <linux/ptp_clock_kernel.h>
+#include <net/xdp.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
@@ -353,6 +354,7 @@ struct mlx4_en_rx_ring {
unsigned long dropped;
int hwtstamp_rx_filter;
cpumask_var_t affinity_mask;
+ struct xdp_rxq_info xdp_rxq;
};
struct mlx4_en_cq {
@@ -716,7 +718,7 @@ void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev);
void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv);
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring **pring,
- u32 size, u16 stride, int node);
+ u32 size, u16 stride, int node, int queue_index);
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring **pring,
u32 size, u16 stride);
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 07/14] bnxt_en: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:19 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: netdev, Jesper Dangaard Brouer, dsahern, michael.chan,
bjorn.topel, gospo, Andy Gospodarek
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
Driver hook points for xdp_rxq_info:
* init+reg: bnxt_alloc_rx_rings
* unreg : bnxt_free_rx_rings
This driver should be updated to re-register when changing
allocation mode of RX rings.
Cc: Andy Gospodarek <andy@greyhouse.net>
Cc: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 ++++++++++
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 ++
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 1 +
3 files changed, 13 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index af6c83f355ae..1eb65a6d6d9a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2246,6 +2246,7 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
if (rxr->xdp_prog)
bpf_prog_put(rxr->xdp_prog);
+ xdp_rxq_info_unreg(&rxr->xdp_rxq);
kfree(rxr->rx_tpa);
rxr->rx_tpa = NULL;
@@ -2280,6 +2281,12 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp)
ring = &rxr->rx_ring_struct;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rxr->xdp_rxq);
+ rxr->xdp_rxq.dev = bp->dev;
+ rxr->xdp_rxq.queue_index = i;
+ xdp_rxq_info_reg(&rxr->xdp_rxq);
+
rc = bnxt_alloc_ring(bp, ring);
if (rc)
return rc;
@@ -2834,6 +2841,9 @@ void bnxt_set_ring_params(struct bnxt *bp)
bp->cp_ring_mask = bp->cp_bit - 1;
}
+/* Changing allocation mode of RX rings.
+ * TODO: Update when extending xdp_rxq_info to support allocation modes.
+ */
int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
{
if (page_mode) {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 5359a1f0045f..2d268fc26f5e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -23,6 +23,7 @@
#include <net/devlink.h>
#include <net/dst_metadata.h>
#include <net/switchdev.h>
+#include <net/xdp.h>
struct tx_bd {
__le32 tx_bd_len_flags_type;
@@ -664,6 +665,7 @@ struct bnxt_rx_ring_info {
struct bnxt_ring_struct rx_ring_struct;
struct bnxt_ring_struct rx_agg_ring_struct;
+ struct xdp_rxq_info xdp_rxq;
};
struct bnxt_cp_ring_info {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index 261e5847557a..1389ab5e05df 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -96,6 +96,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
xdp.data = *data_ptr;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = *data_ptr + *len;
+ xdp.rxq = &rxr->xdp_rxq;
orig_data = xdp.data;
mapping = rx_buf->mapping - bp->rx_dma_offset;
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 08/14] nfp: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:20 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: dsahern, Jakub Kicinski, oss-drivers, Simon Horman,
Jesper Dangaard Brouer, netdev, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
Driver hook points for xdp_rxq_info:
* init+reg: nfp_net_rx_ring_alloc
* unreg : nfp_net_rx_ring_free
In struct nfp_net_rx_ring moved member @size into a hole on 64-bit.
Thus, the size remaines the same after adding member @xdp_rxq.
Cc: oss-drivers@netronome.com
Cc: Jakub Kicinski <jakub.kicinski@netronome.com>
Cc: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/netronome/nfp/nfp_net.h | 5 ++++-
.../net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 3801c52098d5..0e564cfabe7e 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -47,6 +47,7 @@
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/io-64-nonatomic-hi-lo.h>
+#include <net/xdp.h>
#include "nfp_net_ctrl.h"
@@ -350,6 +351,7 @@ struct nfp_net_rx_buf {
* @rxds: Virtual address of FL/RX ring in host memory
* @dma: DMA address of the FL/RX ring
* @size: Size, in bytes, of the FL/RX ring (needed to free)
+ * @xdp_rxq: RX-ring info avail for XDP
*/
struct nfp_net_rx_ring {
struct nfp_net_r_vector *r_vec;
@@ -361,13 +363,14 @@ struct nfp_net_rx_ring {
u32 idx;
int fl_qcidx;
+ unsigned int size;
u8 __iomem *qcp_fl;
struct nfp_net_rx_buf *rxbufs;
struct nfp_net_rx_desc *rxds;
dma_addr_t dma;
- unsigned int size;
+ struct xdp_rxq_info xdp_rxq;
} ____cacheline_aligned;
/**
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index ad3e9f6a61e5..6474aecd0451 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1608,11 +1608,13 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
unsigned int true_bufsz;
struct sk_buff *skb;
int pkts_polled = 0;
+ struct xdp_buff xdp;
int idx;
rcu_read_lock();
xdp_prog = READ_ONCE(dp->xdp_prog);
true_bufsz = xdp_prog ? PAGE_SIZE : dp->fl_bufsz;
+ xdp.rxq = &rx_ring->xdp_rxq;
tx_ring = r_vec->xdp_ring;
while (pkts_polled < budget) {
@@ -1703,7 +1705,6 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
dp->bpf_offload_xdp) && !meta.portid) {
void *orig_data = rxbuf->frag + pkt_off;
unsigned int dma_off;
- struct xdp_buff xdp;
int act;
xdp.data_hard_start = rxbuf->frag + NFP_NET_RX_BUF_HEADROOM;
@@ -2252,6 +2253,7 @@ static void nfp_net_rx_ring_free(struct nfp_net_rx_ring *rx_ring)
struct nfp_net_r_vector *r_vec = rx_ring->r_vec;
struct nfp_net_dp *dp = &r_vec->nfp_net->dp;
+ xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
kfree(rx_ring->rxbufs);
if (rx_ring->rxds)
@@ -2277,6 +2279,12 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
{
int sz;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rx_ring->xdp_rxq);
+ rx_ring->xdp_rxq.dev = dp->netdev;
+ rx_ring->xdp_rxq.queue_index = rx_ring->idx;
+ xdp_rxq_info_reg(&rx_ring->xdp_rxq);
+
rx_ring->cnt = dp->rxd_cnt;
rx_ring->size = sizeof(*rx_ring->rxds) * rx_ring->cnt;
rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size,
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 09/14] thunderx: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:20 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: bjorn.topel, Robert Richter, netdev, dsahern,
Jesper Dangaard Brouer, gospo, Sunil Goutham, michael.chan,
linux-arm-kernel
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
This driver uses a bool scheme for "enable"/"disable" when setting up
different resources. Thus, the hook points for xdp_rxq_info is done
in the same function call nicvf_rcv_queue_config(). This is activated
through enable/disble via nicvf_config_data_transfer(), which is tied
into nicvf_stop()/nicvf_open().
Extending driver packet handler call-path nicvf_rcv_pkt_handler() with
a pointer to the given struct rcv_queue, in-order to access the
xdp_rxq_info data area (in nicvf_xdp_rx()).
Cc: linux-arm-kernel@lists.infradead.org
Cc: Sunil Goutham <sgoutham@cavium.com>
Cc: Robert Richter <rric@kernel.org>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 11 +++++++----
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 7 +++++++
drivers/net/ethernet/cavium/thunder/nicvf_queues.h | 2 ++
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 52b3a6044f85..21618d0d694f 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -521,7 +521,7 @@ static void nicvf_unmap_page(struct nicvf *nic, struct page *page, u64 dma_addr)
static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
struct cqe_rx_t *cqe_rx, struct snd_queue *sq,
- struct sk_buff **skb)
+ struct rcv_queue *rq, struct sk_buff **skb)
{
struct xdp_buff xdp;
struct page *page;
@@ -545,6 +545,7 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
xdp.data = (void *)cpu_addr;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + len;
+ xdp.rxq = &rq->xdp_rxq;
orig_data = xdp.data;
rcu_read_lock();
@@ -698,7 +699,8 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
static void nicvf_rcv_pkt_handler(struct net_device *netdev,
struct napi_struct *napi,
- struct cqe_rx_t *cqe_rx, struct snd_queue *sq)
+ struct cqe_rx_t *cqe_rx,
+ struct snd_queue *sq, struct rcv_queue *rq)
{
struct sk_buff *skb = NULL;
struct nicvf *nic = netdev_priv(netdev);
@@ -724,7 +726,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
/* For XDP, ignore pkts spanning multiple pages */
if (nic->xdp_prog && (cqe_rx->rb_cnt == 1)) {
/* Packet consumed by XDP */
- if (nicvf_xdp_rx(snic, nic->xdp_prog, cqe_rx, sq, &skb))
+ if (nicvf_xdp_rx(snic, nic->xdp_prog, cqe_rx, sq, rq, &skb))
return;
} else {
skb = nicvf_get_rcv_skb(snic, cqe_rx,
@@ -781,6 +783,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
struct cqe_rx_t *cq_desc;
struct netdev_queue *txq;
struct snd_queue *sq = &qs->sq[cq_idx];
+ struct rcv_queue *rq = &qs->rq[cq_idx];
unsigned int tx_pkts = 0, tx_bytes = 0, txq_idx;
spin_lock_bh(&cq->lock);
@@ -811,7 +814,7 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
switch (cq_desc->cqe_type) {
case CQE_TYPE_RX:
- nicvf_rcv_pkt_handler(netdev, napi, cq_desc, sq);
+ nicvf_rcv_pkt_handler(netdev, napi, cq_desc, sq, rq);
work_done++;
break;
case CQE_TYPE_SEND:
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 095c18aeb8d5..2f2a736ea102 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -760,6 +760,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
if (!rq->enable) {
nicvf_reclaim_rcv_queue(nic, qs, qidx);
+ xdp_rxq_info_unreg(&rq->xdp_rxq);
return;
}
@@ -772,6 +773,12 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
/* all writes of RBDR data to be loaded into L2 Cache as well*/
rq->caching = 1;
+ /* XDP RX-queue info */
+ xdp_rxq_info_init(&rq->xdp_rxq);
+ rq->xdp_rxq.dev = nic->netdev;
+ rq->xdp_rxq.queue_index = qidx;
+ xdp_rxq_info_reg(&rq->xdp_rxq);
+
/* Send a mailbox msg to PF to config RQ */
mbx.rq.msg = NIC_MBOX_MSG_RQ_CFG;
mbx.rq.qs_num = qs->vnic_id;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 178ab6e8e3c5..7d1e4e2aaad0 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -12,6 +12,7 @@
#include <linux/netdevice.h>
#include <linux/iommu.h>
#include <linux/bpf.h>
+#include <net/xdp.h>
#include "q_struct.h"
#define MAX_QUEUE_SET 128
@@ -255,6 +256,7 @@ struct rcv_queue {
u8 start_qs_rbdr_idx; /* RBDR idx in the above QS */
u8 caching;
struct rx_tx_queue_stats stats;
+ struct xdp_rxq_info xdp_rxq;
} ____cacheline_aligned_in_smp;
struct cmp_queue {
^ permalink raw reply related
* [bpf-next V1-RFC PATCH 11/14] virtio_net: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-13 11:20 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: Michael S. Tsirkin, netdev, Jesper Dangaard Brouer,
virtualization, dsahern, gospo, bjorn.topel, michael.chan
In-Reply-To: <151316391502.14967.13292358380181773729.stgit@firesoul>
The virtio_net driver doesn't dynamically change the RX-ring queue
layout and backing pages, but instead reject XDP setup if all the
conditions for XDP is not meet. Thus, the xdp_rxq_info also remains
fairly static. This allow us to simply add the init+reg/unreg to
net_device open/close functions.
Driver hook points for xdp_rxq_info:
* init+reg: virtnet_open
* unreg : virtnet_close
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: virtualization@lists.linux-foundation.org
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/virtio_net.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 19a985ef9104..9792183befbf 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -31,6 +31,7 @@
#include <linux/average.h>
#include <linux/filter.h>
#include <net/route.h>
+#include <net/xdp.h>
static int napi_weight = NAPI_POLL_WEIGHT;
module_param(napi_weight, int, 0444);
@@ -115,6 +116,8 @@ struct receive_queue {
/* Name of this receive queue: input.$index */
char name[40];
+
+ struct xdp_rxq_info xdp_rxq;
};
struct virtnet_info {
@@ -556,6 +559,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
xdp.data = xdp.data_hard_start + xdp_headroom;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + len;
+ xdp.rxq = &rq->xdp_rxq;
orig_data = xdp.data;
act = bpf_prog_run_xdp(xdp_prog, &xdp);
@@ -1229,6 +1233,13 @@ static int virtnet_open(struct net_device *dev)
/* Make sure we have some buffers: if oom use wq. */
if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
schedule_delayed_work(&vi->refill, 0);
+
+ /* XDP RX queue info */
+ xdp_rxq_info_init(&vi->rq[i].xdp_rxq);
+ vi->rq[i].xdp_rxq.dev = dev;
+ vi->rq[i].xdp_rxq.queue_index = i;
+ xdp_rxq_info_reg(&vi->rq[i].xdp_rxq);
+
virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
}
@@ -1557,6 +1568,7 @@ static int virtnet_close(struct net_device *dev)
cancel_delayed_work_sync(&vi->refill);
for (i = 0; i < vi->max_queue_pairs; i++) {
+ xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
napi_disable(&vi->rq[i].napi);
virtnet_napi_tx_disable(&vi->sq[i].napi);
}
^ 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