* Re: [PATCH v2 net-next] rds-tcp: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket
From: Eric Dumazet @ 2016-03-15 17:18 UTC (permalink / raw)
To: Sowmini Varadhan; +Cc: santosh shilimkar, netdev, davem
In-Reply-To: <20160315165800.GL11063@oracle.com>
On Tue, 2016-03-15 at 12:58 -0400, Sowmini Varadhan wrote:
> On (03/15/16 09:38), santosh shilimkar wrote:
> > >+ if (rtn->sndbuf_size > 0) {
> > So value of 1 is allowed as well. There should be some
> > minimum default or multiple of it. Of course above check
> > can remain as is as long as you validate the user input
> > in handlers.
>
> yes, just as user-space SO_SNDBUF allows ridiculous values
> for buffer size..
Well... Not really.
>
> > >@@ -309,6 +352,7 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
> > > {
> > > struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
> > >
> > >+ unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
> > > /* If rds_tcp_exit_net() is called as a result of netns deletion,
> > > * the rds_tcp_kill_sock() device notifier would already have cleaned
> > > * up the listen socket, thus there is no work to do in this function.
> > You need to unregister it on rds_tcp_listen_init() failure.
>
> Ok, good point.
>
> > >+ rtn->sndbuf_size = user_atoi(buffer, *lenp);
> > As mentioned above, you should make sure the buffer lengths are
> > legitimate.
>
> As above. We allow any values that the TCP socket itself allows.
> If the user wants to shoot themself in the foot, we dont stop them.
Look at SO_SNDBUF and SO_RCVBUF implementation.
sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF);
sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF);
kernel definitely has some logic here.
If you believe SOCK_MIN_SNDBUF and/or SOCK_MIN_RCVBUF are wrong, please
elaborate.
^ permalink raw reply
* Re: [PATCH net] ravb: fix result value overwrite
From: Sergei Shtylyov @ 2016-03-15 17:10 UTC (permalink / raw)
To: Yoshihiro Kaneko, netdev
Cc: David S. Miller, Simon Horman, Magnus Damm, linux-renesas-soc
In-Reply-To: <1458057136-23253-1-git-send-email-ykaneko0929@gmail.com>
Hello.
On 03/15/2016 06:52 PM, Yoshihiro Kaneko wrote:
> The result value is overwritten by a return value of
> ravb_ptp_interrupt().
>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
> ---
Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
[...]
> diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
> index 86449c3..d369af8 100644
> --- a/drivers/net/ethernet/renesas/ravb_main.c
> +++ b/drivers/net/ethernet/renesas/ravb_main.c
> @@ -765,8 +765,8 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
> result = IRQ_HANDLED;
> }
>
> - if (iss & ISS_CGIS)
> - result = ravb_ptp_interrupt(ndev);
I clearly meant to use |= here instead. Uh oh... :-(
> + if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED)
> + result = IRQ_HANDLED;
MBR, Sergei
^ permalink raw reply
* Re: [PATCH v7 net-next] ravb: Add dma queue interrupt support
From: Sergei Shtylyov @ 2016-03-15 17:08 UTC (permalink / raw)
To: Yoshihiro Kaneko
Cc: netdev, David S. Miller, Simon Horman, Magnus Damm,
linux-renesas-soc
In-Reply-To: <CAH1o70JC_OGqdUEXjGFMm1EDdVAEkGaMiJrx2JTgW+Ny1FnC3A@mail.gmail.com>
Hello.
On 03/15/2016 06:03 PM, Yoshihiro Kaneko wrote:
>>> From: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>>>
>>> This patch supports the following interrupts.
>>>
>>> - One interrupt for multiple (timestamp, error, gPTP)
>>> - One interrupt for emac
>>> - Four interrupts for dma queue (best effort rx/tx, network control rx/tx)
>>>
>>> This patch improve efficiency of the interrupt handler by adding the
>>> interrupt handler corresponding to each interrupt source described
>>> above. Additionally, it reduces the number of times of the access to
>>> EthernetAVB IF.
>>> Also this patch prevent this driver depends on the whim of a boot loader.
>>>
>>> [ykaneko0929@gmail.com: define bit names of registers]
>>> [ykaneko0929@gmail.com: add comment for gen3 only registers]
>>> [ykaneko0929@gmail.com: fix coding style]
>>> [ykaneko0929@gmail.com: update changelog]
>>> [ykaneko0929@gmail.com: gen3: fix initialization of interrupts]
>>> [ykaneko0929@gmail.com: gen3: fix clearing interrupts]
>>> [ykaneko0929@gmail.com: gen3: add helper function for request_irq()]
>>> [ykaneko0929@gmail.com: gen3: remove IRQF_SHARED flag for request_irq()]
>>> [ykaneko0929@gmail.com: revert ravb_close() and ravb_ptp_stop()]
>>> [ykaneko0929@gmail.com: avoid calling free_irq() to non-hooked interrupts]
>>> [ykaneko0929@gmail.com: make NC/BE interrupt handler a function]
>>> [ykaneko0929@gmail.com: make timestamp interrupt handler a function]
>>> [ykaneko0929@gmail.com: timestamp interrupt is handled in multiple
>>> interrupt handler instead of dma queue interrupt handler]
>>> Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>>> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
>>
>> [...]
>>>
>>> diff --git a/drivers/net/ethernet/renesas/ravb_main.c
>>> b/drivers/net/ethernet/renesas/ravb_main.c
>>> index 8f2c4fb..8fa8ffe 100644
>>> --- a/drivers/net/ethernet/renesas/ravb_main.c
>>> +++ b/drivers/net/ethernet/renesas/ravb_main.c
>>
>> [...]
>>>
>>> @@ -757,14 +806,73 @@ static irqreturn_t ravb_interrupt(int irq, void
>>> *dev_id)
>>> result = IRQ_HANDLED;
>>> }
>>>
>>> - if (iss & ISS_CGIS)
>>> - result = ravb_ptp_interrupt(ndev);
>>> + /* gPTP interrupt status summary */
>>> + if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED)
>>> + result = IRQ_HANDLED;
>>
>> Wait, this seems like a bug in the existing driver! Please do fix it with
>> a separate patch against net.git. Sorry about missing (or even adding) it
>> while cleaning up the driver before submission...
> Thanks, I will do so.
TIA.
>>
>> [...]
>>
>> Looks fine otherwise, however the new features and the fixes shouldn't be
>> mixed together, so I couldn't ACK yet. I'll go test it on gen2...
>
> Thanks in advance.
My testing on the modified Porter board went smooth.
> Thanks,
> kaneko
MBR, Sergei
^ permalink raw reply
* Re: [PATCH net-next repost] openvswitch: allow output of MPLS packets on tunnel vports
From: Jesse Gross @ 2016-03-15 17:05 UTC (permalink / raw)
To: Simon Horman; +Cc: ovs dev, Linux Kernel Network Developers, David Miller
In-Reply-To: <1458010835-18555-1-git-send-email-simon.horman-wFxRvT7yatFl57MIdRCFDg@public.gmane.org>
On Mon, Mar 14, 2016 at 8:00 PM, Simon Horman
<simon.horman@netronome.com> wrote:
> Currently output of MPLS packets on tunnel vports is not allowed by Open
> vSwitch. This is because historically encapsulation was done in such a way
> that the inner_protocol field of the skb needed to hold the inner protocol
> for both MPLS and tunnel encapsulation in order for GSO segmentation to be
> performed correctly.
>
> Since b2acd1dc3949 ("openvswitch: Use regular GRE net_device instead of
> vport") Open vSwitch makes use of lwt to output to tunnel netdevs which
> perform encapsulation. As no drivers expose support for MPLS offloads this
> means that GSO packets are segmented in software by validate_xmit_skb(),
> which is called from __dev_queue_xmit(), before tunnel encapsulation occurs.
> This means that the inner protocol of MPLS is no longer needed by the time
> encapsulation occurs and the contention on the inner_protocol field of the
> skb no longer occurs.
>
> Thus it is now safe to output MPLS to tunnel vports.
>
> Signed-off-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Jesse Gross <jesse@kernel.org>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply
* Re: [PATCH v2 net-next] rds-tcp: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket
From: Sowmini Varadhan @ 2016-03-15 16:58 UTC (permalink / raw)
To: santosh shilimkar; +Cc: netdev, davem
In-Reply-To: <56E83A6D.6060904@oracle.com>
On (03/15/16 09:38), santosh shilimkar wrote:
> >+ if (rtn->sndbuf_size > 0) {
> So value of 1 is allowed as well. There should be some
> minimum default or multiple of it. Of course above check
> can remain as is as long as you validate the user input
> in handlers.
yes, just as user-space SO_SNDBUF allows ridiculous values
for buffer size..
> >@@ -309,6 +352,7 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
> > {
> > struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
> >
> >+ unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
> > /* If rds_tcp_exit_net() is called as a result of netns deletion,
> > * the rds_tcp_kill_sock() device notifier would already have cleaned
> > * up the listen socket, thus there is no work to do in this function.
> You need to unregister it on rds_tcp_listen_init() failure.
Ok, good point.
> >+ rtn->sndbuf_size = user_atoi(buffer, *lenp);
> As mentioned above, you should make sure the buffer lengths are
> legitimate.
As above. We allow any values that the TCP socket itself allows.
If the user wants to shoot themself in the foot, we dont stop them.
I'll fix the nits and send out another patchset in a bit.
^ permalink raw reply
* Re: [PATCH v2 net-next] rds-tcp: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket
From: santosh shilimkar @ 2016-03-15 16:38 UTC (permalink / raw)
To: Sowmini Varadhan, netdev; +Cc: davem
In-Reply-To: <20160315151248.GJ11063@oracle.com>
Hi Sowmini,
$subject
s/rds-tcp: /RDS: TCP:
On 3/15/2016 8:12 AM, Sowmini Varadhan wrote:
>
> Add per-net sysctl tunables to set the size of sndbuf and
> rcvbuf on the kernel tcp socket.
>
> The tunables are added at /proc/sys/net/rds/tcp/rds_tcp_sndbuf
> and /proc/sys/net/rds/tcp/rds_tcp_rcvbuf.
>
> These values must be set before accept() or connect(),
This will be hard to achieve with RDS being reconnect protocol
but since you have added a reset, the above no longer a
problem.
> and there may be an arbitrary number of existing rds-tcp
> sockets when the tunable is modified. To make sure that all
> connections in the netns pick up the same value for the tunable,
> we reset existing rds-tcp connections in the netns, so that
> they can reconnect with the new parameters.
>
> Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
> ---
> v2: use sysctl instead of module param. Tunabes are now per netns,
> and can be dynamically modified without restarting all namespaces.
>
> net/rds/tcp.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 129 insertions(+), 10 deletions(-)
>
> diff --git a/net/rds/tcp.c b/net/rds/tcp.c
> index ad60299..5d62fd2 100644
> --- a/net/rds/tcp.c
> +++ b/net/rds/tcp.c
> @@ -52,7 +52,27 @@ static LIST_HEAD(rds_tcp_conn_list);
>
> static struct kmem_cache *rds_tcp_conn_slab;
>
> -#define RDS_TCP_DEFAULT_BUFSIZE (128 * 1024)
This seems to be unrelated change and left over from the
previous clean-up. Please do that in separate patch.
> +static int sndbuf_handler(struct ctl_table *ctl, int write,
> + void __user *buffer, size_t *lenp, loff_t *fpos);
> +static int rcvbuf_handler(struct ctl_table *ctl, int write,
> + void __user *buffer, size_t *lenp, loff_t *fpos);
> +static struct ctl_table rds_tcp_sysctl_table[] = {
> + {
> + .procname = "rds_tcp_sndbuf",
> + /* data is per-net pointer */
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = sndbuf_handler,
> + },
> + {
> + .procname = "rds_tcp_rcvbuf",
> + /* data is per-net pointer */
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = rcvbuf_handler,
> + },
> + { }
> +};
>
> /* doing it this way avoids calling tcp_sk() */
> void rds_tcp_nonagle(struct socket *sock)
> @@ -66,15 +86,6 @@ void rds_tcp_nonagle(struct socket *sock)
> set_fs(oldfs);
> }
>
> -/* All module specific customizations to the RDS-TCP socket should be done in
> - * rds_tcp_tune() and applied after socket creation. In general these
> - * customizations should be tunable via module_param()
> - */
> -void rds_tcp_tune(struct socket *sock)
> -{
> - rds_tcp_nonagle(sock);
> -}
> -
> u32 rds_tcp_snd_nxt(struct rds_tcp_connection *tc)
> {
> return tcp_sk(tc->t_sock->sk)->snd_nxt;
> @@ -272,8 +283,33 @@ static int rds_tcp_netid;
> struct rds_tcp_net {
> struct socket *rds_tcp_listen_sock;
> struct work_struct rds_tcp_accept_w;
> + struct ctl_table_header *rds_tcp_sysctl;
> + int sndbuf_size;
> + int rcvbuf_size;
> };
>
> +/* All module specific customizations to the RDS-TCP socket should be done in
> + * rds_tcp_tune() and applied after socket creation.
> + */
> +void rds_tcp_tune(struct socket *sock)
> +{
> + struct sock *sk = sock->sk;
> + struct net *net = sock_net(sk);
> + struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
> +
> + rds_tcp_nonagle(sock);
> + lock_sock(sk);
> + if (rtn->sndbuf_size > 0) {
So value of 1 is allowed as well. There should be some
minimum default or multiple of it. Of course above check
can remain as is as long as you validate the user input
in handlers.
> @@ -296,6 +332,13 @@ static __net_init int rds_tcp_init_net(struct net *net)
> {
> struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
>
> + /* 0 value for {snd, rcv}buf_size implies we let the stack
> + * pick the default, and permit auto-tuning of buffer size.
> + */
> + rtn->sndbuf_size = 0;
> + rtn->rcvbuf_size = 0;
> + rtn->rds_tcp_sysctl = register_net_sysctl(net, "net/rds/tcp",
> + rds_tcp_sysctl_table);
> rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net);
> if (!rtn->rds_tcp_listen_sock) {
> pr_warn("could not set up listen sock\n");
> @@ -309,6 +352,7 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
> {
> struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
>
> + unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
> /* If rds_tcp_exit_net() is called as a result of netns deletion,
> * the rds_tcp_kill_sock() device notifier would already have cleaned
> * up the listen socket, thus there is no work to do in this function.
You need to unregister it on rds_tcp_listen_init() failure.
[...]
> +/* when sysctl is used to modify some kernel socket parameters,this
> + * function resets the RDS connections in that netns so that we can
> + * restart with new parameters. The assumption is that such reset
> + * events are few and far-between.
> + */
> +static void rds_tcp_sysctl_reset(struct net *net)
> +{
> + struct rds_tcp_connection *tc, *_tc;
> +
> + spin_lock_irq(&rds_tcp_conn_lock);
> + list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
> + struct net *c_net = read_pnet(&tc->conn->c_net);
> +
> + if (net != c_net || !tc->t_sock)
> + continue;
a next line will be good here.
> + rds_conn_drop(tc->conn); /* reconnect with new parameters */
> + }
> + spin_unlock_irq(&rds_tcp_conn_lock);
> +}
> +
> +static int sndbuf_handler(struct ctl_table *ctl, int write,
> + void __user *buffer, size_t *lenp, loff_t *fpos)
> +{
> + struct net *net = current->nsproxy->net_ns;
> + struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
> + struct ctl_table tmp;
> +
> + tmp = *ctl;
> + tmp.data = &rtn->sndbuf_size;
> + if (!write)
> + return proc_dointvec(&tmp, write, buffer, lenp, fpos);
> +
> + rtn->sndbuf_size = user_atoi(buffer, *lenp);
As mentioned above, you should make sure the buffer lengths are
legitimate.
Regards,
Santosh
^ permalink raw reply
* Re: [PATCH] af_unix: closed SOCK_SEQPACKET socketpair must get SIGPIPE
From: Alexander Potapenko @ 2016-03-15 16:13 UTC (permalink / raw)
To: David Laight
Cc: edumazet@google.com, rweikusat@mobileactivedefense.com,
davem@davemloft.net, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D4111FC91@AcuExch.aculab.com>
On Tue, Mar 15, 2016 at 2:46 PM, David Laight <David.Laight@aculab.com> wrote:
> From: Alexander Potapenko
>> Sent: 15 March 2016 09:04
>> According to IEEE Std 1003.1, 2013, sending data to a SOCK_SEQPACKET
>> socketpair with MSG_NOSIGNAL flag set must result in a SIGPIPE if the
>> socket is no longer connected.
> ...
>> Without the below patch the behavior is as follows:
>>
>> $ ./sock seqpacket
>> sendmsg: Broken pipe
> ...
>> The behavior of the patched kernel complies with POSIX:
>>
>> $ ./sock seqpacket
>> Killed by SIGPIPE
> ...
>
> While POSIX might specify this behaviour, changing the behaviour
> could easily break applications.
> Basically this change (more or less) require every application that
> uses SOCK_SEQPACKED to be audited to ensure that MSG_NOSIGNAL is set
> on ever send/write to the socket.
This is true, but the drawback of maintaining a non-standard behavior
is that people can't write portable code.
I couldn't find the exact place where the bug has been introduced, but
according to http://lxr.free-electrons.com/ SOCK_SEQPACKET sockets did
not respect MSG_NOSIGNAL from the very beginning
(http://lxr.free-electrons.com/source/net/unix/af_unix.c?v=3.8#L1723,
there was no such thing as SOCK_SEQPACKET in AF_UNIX in 2.4.37)
Unfortunately I don't know how to estimate the number of existing
users depending on this oddity, as well as the number of people that
have to work around it, so leaving it up to maintainers to decide
whether the fix is needed.
> Personally I think the whole SIGPIPE on sockets should never have been
> allowed to get into the standard.
> I don't remember MSG_NOSIGNAL being present in SYSV.
I think it was not.
> The only time you want a write into a pipe to generate SIGPIPE is
> for pipes generates by the shell that feed stdout to stdin of the
> next process in the pipeline.
> If pipes are implemented as unix-domain socketpairs (no one does that
> any more) then it would require the SIGPIPE for write().
>
> David
>
>
--
Alexander Potapenko
Software Engineer
Google Germany GmbH
Erika-Mann-Straße, 33
80636 München
Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
^ permalink raw reply
* Re: [PATCHv3 (net.git) 2/2] stmmac: fix MDIO settings
From: Giuseppe CAVALLARO @ 2016-03-15 15:53 UTC (permalink / raw)
To: Andreas Färber
Cc: netdev, gabriel.fernandez, fschaefer.oss, dinh.linux, davem,
preid, Tomeu Vizoso
In-Reply-To: <56E75D36.2030201@suse.de>
[-- Attachment #1: Type: text/plain, Size: 4708 bytes --]
Hi Andreas
On 3/15/2016 1:54 AM, Andreas Färber wrote:
> Hi Peppe,
>
> Am 11.03.2016 um 14:33 schrieb Giuseppe Cavallaro:
>> Initially the phy_bus_name was added to manipulate the
>> driver name but It was recently just used to manage the
>
> "it"
>
>> fixed-link and then to take some decision at run-time
>> inside the main (for example to skip EEE).
>
> Word missing after "main"? ("function"?)
>
>> So the patch uses the is_pseudo_fixed_link and removes
>> removes the phy_bus_name variable not necessary anymore.
>
> Duplicate "removes".
Sure I will fix them in the v4
>
>>
>> The driver can manage the mdio registration by using phy-handle,
>> dwmac-mdio and own parameter e.g. snps,phy-addr.
>> This patch takes care about all these possible configurations
>> and fixes the mdio registration in case of there is a real
>> transceiver or a switch (that needs to be managed by using
>> fixed-link).
>>
>> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
>> Reviewed-by: Andreas Färber <afaerber@suse.de>
>> Tested-by: Frank Schäfer <fschaefer.oss@googlemail.com>
>> Cc: Gabriel Fernandez <gabriel.fernandez@linaro.org>
>> Cc: Dinh Nguyen <dinh.linux@gmail.com>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: Phil Reid <preid@electromag.com.au>
>> ---
>>
>> V2: use is_pseudo_fixed_link
>> V3: parse device-tree driver parameters to allocate PHY resources considering
>> DSA case (+ fixed-link).
>
> For next-20160314 I needed "i2c: immediately mark ourselves as
> registered" plus this build fix:
yes I will send it in a separate set for net-next.
>
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -866,9 +866,8 @@ static int stmmac_init_phy(struct net_device *dev)
> }
>
> /* If attached to a switch, there is no reason to poll phy
> handler */
> - if (priv->plat->phy_bus_name)
> - if (!strcmp(priv->plat->phy_bus_name, "fixed"))
> - phydev->irq = PHY_IGNORE_INTERRUPT;
> + if (phydev->is_pseudo_fixed_link)
> + phydev->irq = PHY_IGNORE_INTERRUPT;
>
> pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)"
> " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
>
> It then fixes the PHY error on GeekBox, so for this mini-series:
>
> Tested-by: Andreas Färber <afaerber@suse.de>
thx a lot for having tested it.
>
> The connectivity issue still remains. Kernel log snippet:
>
> [ +0.001117] rk_gmac-dwmac ff290000.ethernet: Looking up phy-supply
> from device tree
> [ +0.000028] rk808 0-001b: Looking up vcc12-supply from device tree
> [ +0.000014] vcc_lan: supplied by vcc_io
> [ +0.000101] rk_gmac-dwmac ff290000.ethernet: clock input or output?
> (input).
> [ +0.000009] rk_gmac-dwmac ff290000.ethernet: TX delay(0x30).
> [ +0.000008] rk_gmac-dwmac ff290000.ethernet: RX delay(0x10).
> [ +0.000014] rk_gmac-dwmac ff290000.ethernet: init for RGMII
> [ +0.000104] rk_gmac-dwmac ff290000.ethernet: clock input from PHY
> [ +0.005063] rk_gmac-dwmac ff290000.ethernet: no reset control found
> [ +0.000007] stmmac - user ID: 0x10, Synopsys ID: 0x35
> [ +0.000002] Ring mode enabled
> [ +0.000006] DMA HW capability register supported
> [ +0.000000] Normal descriptors
^^^^^^^^^^^^^^^^^^
> [ +0.000003] RX Checksum Offload Engine supported (type 2)
> [ +0.000002] TX Checksum insertion supported
> [ +0.000002] Wake-Up On Lan supported
> [ +0.000053] Enable RX Mitigation via HW Watchdog Timer
> [ +0.000771] of_get_named_gpiod_flags: can't parse 'snps,reset-gpio'
> property of node '/ethernet@ff290000[0]'
> [ +0.004250] libphy: stmmac: probed
> [ +0.000009] eth0: PHY ID 001cc915 at 0 IRQ POLL (stmmac-0:00) active
> [ +0.000005] eth0: PHY ID 001cc915 at 1 IRQ POLL (stmmac-0:01)
>
> As before, reverting "stmmac: first frame prep at the end of xmit
> routine" fixes it. My test cases are `ping 192.168.1.1` and `zypper up`.
so on your side, this revert fixes the issue and you do not see any
tx watchdog as Tomeu's raised.
I have fixed some problems on top of
"stmmac: first frame prep at the end of xmit ..." please
see patch attached for net-next.
Indeed, the normal tx descriptors are well filled w/o
"stmmac: first frame prep at the end of xmit ..."
I wonder if you could try the attachment in order to understand if we
have to actually revert the patch (I ask you to not revert the
patch "stmmac: first frame...").
I cannot test on an HW with Normal descriptors, unfortunately.
I am continuing to review the code to try to find other issues
on this configuration.
Let me know.
Regards
peppe
>
> Regards,
> Andreas
>
[-- Attachment #2: 0001-stmmac-fix-TX-normal-DESC.patch --]
[-- Type: text/x-patch, Size: 1490 bytes --]
>From 036b21b0396d6df42bd8e507be1449fbc7935bce Mon Sep 17 00:00:00 2001
From: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Date: Tue, 15 Mar 2016 16:54:51 +0100
Subject: [PATCH (net-next.git)] stmmac: fix TX normal DESC
This patch is to fix the normal descriptor that has
a broken len and the OWN bit never set.
Signed-off-by: Giuseppe CAVALLARO <peppe.cavallaro@st.com>
---
drivers/net/ethernet/stmicro/stmmac/norm_desc.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
index e13228f..011386f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c
@@ -199,11 +199,6 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
{
unsigned int tdes1 = p->des1;
- if (mode == STMMAC_CHAIN_MODE)
- norm_set_tx_desc_len_on_chain(p, len);
- else
- norm_set_tx_desc_len_on_ring(p, len);
-
if (is_fs)
tdes1 |= TDES1_FIRST_SEGMENT;
else
@@ -217,10 +212,15 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
if (ls)
tdes1 |= TDES1_LAST_SEGMENT;
- if (tx_own)
- tdes1 |= TDES0_OWN;
-
p->des1 = tdes1;
+
+ if (mode == STMMAC_CHAIN_MODE)
+ norm_set_tx_desc_len_on_chain(p, len);
+ else
+ norm_set_tx_desc_len_on_ring(p, len);
+
+ if (tx_own)
+ p->des0 |= TDES0_OWN;
}
static void ndesc_set_tx_ic(struct dma_desc *p)
--
1.7.4.4
^ permalink raw reply related
* [PATCH net] ravb: fix result value overwrite
From: Yoshihiro Kaneko @ 2016-03-15 15:52 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Sergei Shtylyov, Simon Horman, Magnus Damm,
linux-renesas-soc
The result value is overwritten by a return value of
ravb_ptp_interrupt().
Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
---
This patch is based on the master branch of David Miller's networking tree.
drivers/net/ethernet/renesas/ravb_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 86449c3..d369af8 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -765,8 +765,8 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
result = IRQ_HANDLED;
}
- if (iss & ISS_CGIS)
- result = ravb_ptp_interrupt(ndev);
+ if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED)
+ result = IRQ_HANDLED;
mmiowb();
spin_unlock(&priv->lock);
--
1.9.1
^ permalink raw reply related
* Re: [RFC PATCH kernel] Revert "net/mlx4_core: Set UAR page size to 4KB regardless of system page size"
From: Christoph Hellwig @ 2016-03-15 15:29 UTC (permalink / raw)
To: Or Gerlitz
Cc: Christoph Hellwig, Alexey Kardashevskiy, Huy Nguyen, Doug Ledford,
Eugenia Emantayev, Hal Rosenstock, Sean Hefty, Yishai Hadas,
Linux Kernel, linux-rdma@vger.kernel.org, Linux Netdev List,
Paul Mackerras, Carol L Soto, Yevgeny Petrilin, Daniel Jurgens,
Eli Cohen
In-Reply-To: <CAJ3xEMg5fq3Z2VH_qDjsFmTzhCibAGiXT9oEddEKbwktvSYSQQ@mail.gmail.com>
On Tue, Mar 15, 2016 at 04:23:33PM +0200, Or Gerlitz wrote:
> Let us check. I was under (the maybe wrong) impression, that before this
> patch both PF/VF drivers were not operative on some systems, so on those
> systems it's fair to require the VF driver to be patched too.
To me it sounds like the system worked before. Alexey, can you confirm?
^ permalink raw reply
* Re: [PATCH] net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)
From: Matt Wilson @ 2016-03-15 15:25 UTC (permalink / raw)
To: Netanel Belgazal
Cc: zorik, saeed, alex, aliguori, davem, linux-kernel, netdev,
antoine.tenart
In-Reply-To: <1458039006-19956-1-git-send-email-netanel@annapurnalabs.com>
Hi Netanel,
Looks like the last round of internal review went to {lkml,netdev,etc},
so this should be considered a RFC patch.
The description still needs work.
On Tue, Mar 15, 2016 at 12:50:06PM +0200, Netanel Belgazal wrote:
> This is a driver for the Amazon ethernet ENA family.
ethernet -> Ethernet
> The driver operates variety of ENA adapters through
> feature negotiation with the adapter and upgradable commands set.
> ENA driver handles PCI Physical and Virtual ENA functions.
>
> The ENA device is not yet released to public.
> He is expected to be released soon.
I would say "this is a driver for a device that will be available in
the future." I wouldn't say "He is expected to released soon."
> For the full specification of the device please refer to:
> <SPEC-PATH>
Obviously this is a placeholder. I think that the included
documentation in ena.txt and in the code provides a reasonable theory
of operation, and you don't necessarily need to provide a pointer
here. If/when a full specification is available you can submit a patch
to ena.txt that points to the canonical location.
--msw
> ---
> Documentation/networking/00-INDEX | 2 +
> Documentation/networking/ena.txt | 330 +++
> MAINTAINERS | 9 +
> drivers/net/ethernet/Kconfig | 1 +
> drivers/net/ethernet/Makefile | 1 +
> drivers/net/ethernet/amazon/Kconfig | 27 +
> drivers/net/ethernet/amazon/Makefile | 5 +
> drivers/net/ethernet/amazon/ena/Makefile | 9 +
> drivers/net/ethernet/amazon/ena/ena_admin_defs.h | 1310 +++++++++
> drivers/net/ethernet/amazon/ena/ena_com.c | 2730 ++++++++++++++++++
> drivers/net/ethernet/amazon/ena/ena_com.h | 1040 +++++++
> drivers/net/ethernet/amazon/ena/ena_common_defs.h | 52 +
> drivers/net/ethernet/amazon/ena/ena_eth_com.c | 502 ++++
> drivers/net/ethernet/amazon/ena/ena_eth_com.h | 146 +
> drivers/net/ethernet/amazon/ena/ena_eth_io_defs.h | 509 ++++
> drivers/net/ethernet/amazon/ena/ena_ethtool.c | 837 ++++++
> drivers/net/ethernet/amazon/ena/ena_netdev.c | 3179 +++++++++++++++++++++
> drivers/net/ethernet/amazon/ena/ena_netdev.h | 317 ++
> drivers/net/ethernet/amazon/ena/ena_pci_id_tbl.h | 77 +
> drivers/net/ethernet/amazon/ena/ena_regs_defs.h | 133 +
> drivers/net/ethernet/amazon/ena/ena_sysfs.c | 272 ++
> drivers/net/ethernet/amazon/ena/ena_sysfs.h | 55 +
[...]
^ permalink raw reply
* [PATCH v2 net-next] rds-tcp: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket
From: Sowmini Varadhan @ 2016-03-15 15:12 UTC (permalink / raw)
To: netdev; +Cc: sowmini.varadhan, santosh.shilimkar, davem
Add per-net sysctl tunables to set the size of sndbuf and
rcvbuf on the kernel tcp socket.
The tunables are added at /proc/sys/net/rds/tcp/rds_tcp_sndbuf
and /proc/sys/net/rds/tcp/rds_tcp_rcvbuf.
These values must be set before accept() or connect(),
and there may be an arbitrary number of existing rds-tcp
sockets when the tunable is modified. To make sure that all
connections in the netns pick up the same value for the tunable,
we reset existing rds-tcp connections in the netns, so that
they can reconnect with the new parameters.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
---
v2: use sysctl instead of module param. Tunabes are now per netns,
and can be dynamically modified without restarting all namespaces.
net/rds/tcp.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 129 insertions(+), 10 deletions(-)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index ad60299..5d62fd2 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -52,7 +52,27 @@ static LIST_HEAD(rds_tcp_conn_list);
static struct kmem_cache *rds_tcp_conn_slab;
-#define RDS_TCP_DEFAULT_BUFSIZE (128 * 1024)
+static int sndbuf_handler(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos);
+static int rcvbuf_handler(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos);
+static struct ctl_table rds_tcp_sysctl_table[] = {
+ {
+ .procname = "rds_tcp_sndbuf",
+ /* data is per-net pointer */
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = sndbuf_handler,
+ },
+ {
+ .procname = "rds_tcp_rcvbuf",
+ /* data is per-net pointer */
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = rcvbuf_handler,
+ },
+ { }
+};
/* doing it this way avoids calling tcp_sk() */
void rds_tcp_nonagle(struct socket *sock)
@@ -66,15 +86,6 @@ void rds_tcp_nonagle(struct socket *sock)
set_fs(oldfs);
}
-/* All module specific customizations to the RDS-TCP socket should be done in
- * rds_tcp_tune() and applied after socket creation. In general these
- * customizations should be tunable via module_param()
- */
-void rds_tcp_tune(struct socket *sock)
-{
- rds_tcp_nonagle(sock);
-}
-
u32 rds_tcp_snd_nxt(struct rds_tcp_connection *tc)
{
return tcp_sk(tc->t_sock->sk)->snd_nxt;
@@ -272,8 +283,33 @@ static int rds_tcp_netid;
struct rds_tcp_net {
struct socket *rds_tcp_listen_sock;
struct work_struct rds_tcp_accept_w;
+ struct ctl_table_header *rds_tcp_sysctl;
+ int sndbuf_size;
+ int rcvbuf_size;
};
+/* All module specific customizations to the RDS-TCP socket should be done in
+ * rds_tcp_tune() and applied after socket creation.
+ */
+void rds_tcp_tune(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct net *net = sock_net(sk);
+ struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+
+ rds_tcp_nonagle(sock);
+ lock_sock(sk);
+ if (rtn->sndbuf_size > 0) {
+ sk->sk_sndbuf = rtn->sndbuf_size;
+ sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
+ }
+ if (rtn->rcvbuf_size > 0) {
+ sk->sk_rcvbuf = rtn->rcvbuf_size;
+ sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
+ }
+ release_sock(sk);
+}
+
static void rds_tcp_accept_worker(struct work_struct *work)
{
struct rds_tcp_net *rtn = container_of(work,
@@ -296,6 +332,13 @@ static __net_init int rds_tcp_init_net(struct net *net)
{
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+ /* 0 value for {snd, rcv}buf_size implies we let the stack
+ * pick the default, and permit auto-tuning of buffer size.
+ */
+ rtn->sndbuf_size = 0;
+ rtn->rcvbuf_size = 0;
+ rtn->rds_tcp_sysctl = register_net_sysctl(net, "net/rds/tcp",
+ rds_tcp_sysctl_table);
rtn->rds_tcp_listen_sock = rds_tcp_listen_init(net);
if (!rtn->rds_tcp_listen_sock) {
pr_warn("could not set up listen sock\n");
@@ -309,6 +352,7 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
{
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+ unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
/* If rds_tcp_exit_net() is called as a result of netns deletion,
* the rds_tcp_kill_sock() device notifier would already have cleaned
* up the listen socket, thus there is no work to do in this function.
@@ -383,6 +427,81 @@ static struct notifier_block rds_tcp_dev_notifier = {
.priority = -10, /* must be called after other network notifiers */
};
+static int user_atoi(char __user *ubuf, size_t len)
+{
+ char buf[16];
+ unsigned long ret;
+ int err;
+
+ if (len > 15)
+ return -EINVAL;
+
+ if (copy_from_user(buf, ubuf, len))
+ return -EFAULT;
+
+ buf[len] = 0;
+ err = kstrtoul(buf, 0, &ret);
+ if (err != 0)
+ return -ERANGE;
+ return ret;
+}
+
+/* when sysctl is used to modify some kernel socket parameters,this
+ * function resets the RDS connections in that netns so that we can
+ * restart with new parameters. The assumption is that such reset
+ * events are few and far-between.
+ */
+static void rds_tcp_sysctl_reset(struct net *net)
+{
+ struct rds_tcp_connection *tc, *_tc;
+
+ spin_lock_irq(&rds_tcp_conn_lock);
+ list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
+ struct net *c_net = read_pnet(&tc->conn->c_net);
+
+ if (net != c_net || !tc->t_sock)
+ continue;
+ rds_conn_drop(tc->conn); /* reconnect with new parameters */
+ }
+ spin_unlock_irq(&rds_tcp_conn_lock);
+}
+
+static int sndbuf_handler(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+ struct ctl_table tmp;
+
+ tmp = *ctl;
+ tmp.data = &rtn->sndbuf_size;
+ if (!write)
+ return proc_dointvec(&tmp, write, buffer, lenp, fpos);
+
+ rtn->sndbuf_size = user_atoi(buffer, *lenp);
+ rds_tcp_sysctl_reset(net);
+
+ return 0;
+}
+
+static int rcvbuf_handler(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *fpos)
+{
+ struct net *net = current->nsproxy->net_ns;
+ struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
+ struct ctl_table tmp;
+
+ tmp = *ctl;
+ tmp.data = &rtn->rcvbuf_size;
+ if (!write)
+ return proc_dointvec(&tmp, write, buffer, lenp, fpos);
+
+ rtn->rcvbuf_size = user_atoi(buffer, *lenp);
+ rds_tcp_sysctl_reset(net);
+
+ return 0;
+}
+
static void rds_tcp_exit(void)
{
rds_info_deregister_func(RDS_INFO_TCP_SOCKETS, rds_tcp_tc_info);
--
1.7.1
^ permalink raw reply related
* Re: When will net-next merge with linux-next?
From: gregkh @ 2016-03-15 15:05 UTC (permalink / raw)
To: Dexuan Cui
Cc: David Miller, netdev@vger.kernel.org, KY Srinivasan,
Haiyang Zhang
In-Reply-To: <BLUPR03MB141045D7EED478CB0A086CA1BF890@BLUPR03MB1410.namprd03.prod.outlook.com>
On Tue, Mar 15, 2016 at 11:11:34AM +0000, Dexuan Cui wrote:
> I'm wondering whether (and when) step 2 will happen in the next 2 weeks,
> that is, before the tag 4.6-rc1 is made.
> If not, I guess I'll miss 4.6?
You missed 4.6 as your patch was not in any of our trees a few days
before 4.5 was released, sorry.
greg k-h
^ permalink raw reply
* Re: [PATCH v7 net-next] ravb: Add dma queue interrupt support
From: Yoshihiro Kaneko @ 2016-03-15 15:03 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: netdev, David S. Miller, Simon Horman, Magnus Damm,
linux-renesas-soc
In-Reply-To: <56E72394.5030905@cogentembedded.com>
Hi,
2016-03-15 5:48 GMT+09:00 Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>:
> Hello.
>
>
> On 03/13/2016 09:11 PM, Yoshihiro Kaneko wrote:
>
>> From: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>>
>> This patch supports the following interrupts.
>>
>> - One interrupt for multiple (timestamp, error, gPTP)
>> - One interrupt for emac
>> - Four interrupts for dma queue (best effort rx/tx, network control rx/tx)
>>
>> This patch improve efficiency of the interrupt handler by adding the
>> interrupt handler corresponding to each interrupt source described
>> above. Additionally, it reduces the number of times of the access to
>> EthernetAVB IF.
>> Also this patch prevent this driver depends on the whim of a boot loader.
>>
>> [ykaneko0929@gmail.com: define bit names of registers]
>> [ykaneko0929@gmail.com: add comment for gen3 only registers]
>> [ykaneko0929@gmail.com: fix coding style]
>> [ykaneko0929@gmail.com: update changelog]
>> [ykaneko0929@gmail.com: gen3: fix initialization of interrupts]
>> [ykaneko0929@gmail.com: gen3: fix clearing interrupts]
>> [ykaneko0929@gmail.com: gen3: add helper function for request_irq()]
>> [ykaneko0929@gmail.com: gen3: remove IRQF_SHARED flag for request_irq()]
>> [ykaneko0929@gmail.com: revert ravb_close() and ravb_ptp_stop()]
>> [ykaneko0929@gmail.com: avoid calling free_irq() to non-hooked interrupts]
>> [ykaneko0929@gmail.com: make NC/BE interrupt handler a function]
>> [ykaneko0929@gmail.com: make timestamp interrupt handler a function]
>> [ykaneko0929@gmail.com: timestamp interrupt is handled in multiple
>> interrupt handler instead of dma queue interrupt handler]
>> Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
>
> [...]
>>
>> diff --git a/drivers/net/ethernet/renesas/ravb_main.c
>> b/drivers/net/ethernet/renesas/ravb_main.c
>> index 8f2c4fb..8fa8ffe 100644
>> --- a/drivers/net/ethernet/renesas/ravb_main.c
>> +++ b/drivers/net/ethernet/renesas/ravb_main.c
>
> [...]
>>
>> @@ -757,14 +806,73 @@ static irqreturn_t ravb_interrupt(int irq, void
>> *dev_id)
>> result = IRQ_HANDLED;
>> }
>>
>> - if (iss & ISS_CGIS)
>> - result = ravb_ptp_interrupt(ndev);
>> + /* gPTP interrupt status summary */
>> + if ((iss & ISS_CGIS) && ravb_ptp_interrupt(ndev) == IRQ_HANDLED)
>> + result = IRQ_HANDLED;
>
>
> Wait, this seems like a bug in the existing driver! Please do fix it with
> a separate patch against net.git. Sorry about missing (or even adding) it
> while cleaning up the driver before submission...
Thanks, I will do so.
>
> [...]
>
> Looks fine otherwise, however the new features and the fixes shouldn't be
> mixed together, so I couldn't ACK yet. I'll go test it on gen2...
Thanks in advance.
>
> MBR, Sergei
>
Thanks,
kaneko
^ permalink raw reply
* Re: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts
From: Alexey Brodkin @ 2016-03-15 14:50 UTC (permalink / raw)
To: sergei.shtylyov@cogentembedded.com
Cc: robh@kernel.org, preid@electromag.com.au, davem@davemloft.net,
linux-kernel@vger.kernel.org, linux-snps-arc@lists.infradead.org,
netdev@vger.kernel.org
In-Reply-To: <56E81E66.6080706@cogentembedded.com>
Hi Sergei,
On Tue, 2016-03-15 at 17:38 +0300, Sergei Shtylyov wrote:
> Hello.
>
> On 3/15/2016 12:29 PM, Alexey Brodkin wrote:
>
> >
> > Following commit broke DW GMAC functionality on AXS10x boards:
> > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
> >
> > That's what happens on eth0 up:
> > --------------------------->8------------------------
> > libphy: PHY stmmac-0:ffffffff not found
> > eth0: Could not attach to PHY
> > stmmac_open: Cannot attach to PHY (error: -19)
> > --------------------------->8------------------------
> >
> > Simplest solution is to add PHY description in board's .dts.
> > And so we do here.
> >
> > Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> > Cc: Rob Herring <robh@kernel.org>
> > Cc: Phil Reid <preid@electromag.com.au>
> > Cc: David S. Miller <davem@davemloft.net>
> > Cc: linux-kernel@vger.kernel.org
> > Cc: netdev@vger.kernel.org
> > Cc: stable@vger.kernel.org # 4.5.x
> > ---
> > arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
> > 1 file changed, 8 insertions(+)
> >
> > diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
> > index 44a578c..04b999e 100644
> > --- a/arch/arc/boot/dts/axs10x_mb.dtsi
> > +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
> > @@ -47,6 +47,14 @@
> > clocks = <&apbclk>;
> > clock-names = "stmmaceth";
> > max-speed = <100>;
> > + mdio0 {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + compatible = "snps,dwmac-mdio";
> > + phy0: ethernet-phy@0 {
> The naming is inconsistent with the "reg" prop specified, should be @1.
Makes sense.
Will re-send it with mentioned fix.
-Alexey
^ permalink raw reply
* [patch iproute2 2/2] add devlink tool
From: Jiri Pirko @ 2016-03-15 14:43 UTC (permalink / raw)
To: netdev
Cc: stephen, davem, idosch, eladr, yotamg, ogerlitz, yishaih,
dledford, sean.hefty, hal.rosenstock, eugenia, roopa, nikolay,
hadarh, jhs, john.fastabend, jeffrey.t.kirsher, brouer, ivecera,
rami.rosen, hannes, gospo
In-Reply-To: <1458053029-7725-1-git-send-email-jiri@resnulli.us>
From: Jiri Pirko <jiri@mellanox.com>
Add new tool called devlink which is userspace counterpart of devlink
Netlink socket.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
Makefile | 2 +-
devlink/Makefile | 20 +
devlink/devlink.c | 979 +++++++++++++++++++++++++++++++++++++++++++++
devlink/mnlg.c | 274 +++++++++++++
devlink/mnlg.h | 27 ++
include/linux/devlink.h | 72 ++++
man/man8/devlink-dev.8 | 58 +++
man/man8/devlink-monitor.8 | 36 ++
man/man8/devlink-port.8 | 126 ++++++
man/man8/devlink.8 | 83 ++++
10 files changed, 1676 insertions(+), 1 deletion(-)
create mode 100644 devlink/Makefile
create mode 100644 devlink/devlink.c
create mode 100644 devlink/mnlg.c
create mode 100644 devlink/mnlg.h
create mode 100644 include/linux/devlink.h
create mode 100644 man/man8/devlink-dev.8
create mode 100644 man/man8/devlink-monitor.8
create mode 100644 man/man8/devlink-port.8
create mode 100644 man/man8/devlink.8
diff --git a/Makefile b/Makefile
index 67176be..0190aa0 100644
--- a/Makefile
+++ b/Makefile
@@ -41,7 +41,7 @@ WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2
CFLAGS := $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) $(CFLAGS)
YACCFLAGS = -d -t -v
-SUBDIRS=lib ip tc bridge misc netem genl tipc man
+SUBDIRS=lib ip tc bridge misc netem genl tipc devlink man
LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
LDLIBS += $(LIBNETLINK)
diff --git a/devlink/Makefile b/devlink/Makefile
new file mode 100644
index 0000000..3fdaa69
--- /dev/null
+++ b/devlink/Makefile
@@ -0,0 +1,20 @@
+include ../Config
+ifeq ($(HAVE_MNL),y)
+
+DEVLINKOBJ = devlink.o mnlg.o
+TARGETS=devlink
+
+CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
+LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
+
+endif
+
+all: $(TARGETS) $(LIBS)
+
+devlink: $(DEVLINKOBJ)
+
+install: all
+ install -m 0755 $(TARGETS) $(DESTDIR)$(SBINDIR)
+
+clean:
+ rm -f $(DEVLINKOBJ) $(TARGETS)
diff --git a/devlink/devlink.c b/devlink/devlink.c
new file mode 100644
index 0000000..1d9ca8b
--- /dev/null
+++ b/devlink/devlink.c
@@ -0,0 +1,979 @@
+/*
+ * devlink.c Devlink tool
+ *
+ * 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: Jiri Pirko <jiri@mellanox.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <limits.h>
+#include <errno.h>
+#include <linux/genetlink.h>
+#include <linux/devlink.h>
+#include <libmnl/libmnl.h>
+
+#include "SNAPSHOT.h"
+#include "list.h"
+#include "mnlg.h"
+
+#define pr_err(args...) fprintf(stderr, ##args)
+#define pr_out(args...) fprintf(stdout, ##args)
+
+static int _mnlg_socket_recv_run(struct mnlg_socket *nlg,
+ mnl_cb_t data_cb, void *data)
+{
+ int err;
+
+ err = mnlg_socket_recv_run(nlg, data_cb, data);
+ if (err < 0) {
+ pr_err("devlink answers: %s\n", strerror(errno));
+ return -errno;
+ }
+ return 0;
+}
+
+static int _mnlg_socket_sndrcv(struct mnlg_socket *nlg,
+ const struct nlmsghdr *nlh,
+ mnl_cb_t data_cb, void *data)
+{
+ int err;
+
+ err = mnlg_socket_send(nlg, nlh);
+ if (err < 0) {
+ pr_err("Failed to call mnlg_socket_send\n");
+ return -errno;
+ }
+ return _mnlg_socket_recv_run(nlg, data_cb, data);
+}
+
+static int _mnlg_socket_group_add(struct mnlg_socket *nlg,
+ const char *group_name)
+{
+ int err;
+
+ err = mnlg_socket_group_add(nlg, group_name);
+ if (err < 0) {
+ pr_err("Failed to call mnlg_socket_group_add\n");
+ return -errno;
+ }
+ return 0;
+}
+
+struct ifname_map {
+ struct list_head list;
+ char *bus_name;
+ char *dev_name;
+ uint32_t port_index;
+ char *ifname;
+};
+
+static struct ifname_map *ifname_map_alloc(const char *bus_name,
+ const char *dev_name,
+ uint32_t port_index,
+ const char *ifname)
+{
+ struct ifname_map *ifname_map;
+
+ ifname_map = calloc(1, sizeof(*ifname_map));
+ if (!ifname_map)
+ return NULL;
+ ifname_map->bus_name = strdup(bus_name);
+ ifname_map->dev_name = strdup(dev_name);
+ ifname_map->port_index = port_index;
+ ifname_map->ifname = strdup(ifname);
+ if (!ifname_map->bus_name || !ifname_map->dev_name ||
+ !ifname_map->ifname) {
+ free(ifname_map->ifname);
+ free(ifname_map->dev_name);
+ free(ifname_map->bus_name);
+ free(ifname_map);
+ return NULL;
+ }
+ return ifname_map;
+}
+
+static void ifname_map_free(struct ifname_map *ifname_map)
+{
+ free(ifname_map->ifname);
+ free(ifname_map->dev_name);
+ free(ifname_map->bus_name);
+ free(ifname_map);
+}
+
+struct dl {
+ struct mnlg_socket *nlg;
+ struct list_head ifname_map_list;
+ int argc;
+ char **argv;
+};
+
+static int dl_argc(struct dl *dl)
+{
+ return dl->argc;
+}
+
+static char *dl_argv(struct dl *dl)
+{
+ if (dl_argc(dl) == 0)
+ return NULL;
+ return *dl->argv;
+}
+
+static void dl_arg_inc(struct dl *dl)
+{
+ if (dl_argc(dl) == 0)
+ return;
+ dl->argc--;
+ dl->argv++;
+}
+
+static char *dl_argv_next(struct dl *dl)
+{
+ char *ret;
+
+ if (dl_argc(dl) == 0)
+ return NULL;
+
+ ret = *dl->argv;
+ dl_arg_inc(dl);
+ return ret;
+}
+
+static char *dl_argv_index(struct dl *dl, unsigned int index)
+{
+ if (index >= dl_argc(dl))
+ return NULL;
+ return dl->argv[index];
+}
+
+static int strcmpx(const char *str1, const char *str2)
+{
+ if (strlen(str1) > strlen(str2))
+ return -1;
+ return strncmp(str1, str2, strlen(str1));
+}
+
+static bool dl_argv_match(struct dl *dl, const char *pattern)
+{
+ if (dl_argc(dl) == 0)
+ return false;
+ return strcmpx(dl_argv(dl), pattern) == 0;
+}
+
+static bool dl_no_arg(struct dl *dl)
+{
+ return dl_argc(dl) == 0;
+}
+
+static int attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type;
+
+ type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, DEVLINK_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
+
+ if (type == DEVLINK_ATTR_BUS_NAME &&
+ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_DEV_NAME &&
+ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_INDEX &&
+ mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_TYPE &&
+ mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_DESIRED_TYPE &&
+ mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_NETDEV_IFINDEX &&
+ mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_NETDEV_NAME &&
+ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+ return MNL_CB_ERROR;
+ if (type == DEVLINK_ATTR_PORT_IBDEV_NAME &&
+ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+ return MNL_CB_ERROR;
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static int ifname_map_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+ struct dl *dl = data;
+ struct ifname_map *ifname_map;
+
+ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
+ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] ||
+ !tb[DEVLINK_ATTR_PORT_INDEX])
+ return MNL_CB_ERROR;
+
+ if (!tb[DEVLINK_ATTR_PORT_NETDEV_NAME])
+ return MNL_CB_OK;
+
+ ifname_map = ifname_map_alloc(mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
+ mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]),
+ mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX]),
+ mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_NETDEV_NAME]));
+ if (!ifname_map)
+ return MNL_CB_ERROR;
+ list_add(&ifname_map->list, &dl->ifname_map_list);
+
+ return MNL_CB_OK;
+}
+
+static void ifname_map_fini(struct dl *dl)
+{
+ struct ifname_map *ifname_map, *tmp;
+
+ list_for_each_entry_safe(ifname_map, tmp,
+ &dl->ifname_map_list, list) {
+ list_del(&ifname_map->list);
+ ifname_map_free(ifname_map);
+ }
+}
+
+static int ifname_map_init(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ int err;
+
+ INIT_LIST_HEAD(&dl->ifname_map_list);
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_GET,
+ NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
+
+ err = _mnlg_socket_sndrcv(dl->nlg, nlh, ifname_map_cb, dl);
+ if (err) {
+ ifname_map_fini(dl);
+ return err;
+ }
+ return 0;
+}
+
+static int ifname_map_lookup(struct dl *dl, const char *ifname,
+ char **p_bus_name, char **p_dev_name,
+ uint32_t *p_port_index)
+{
+ struct ifname_map *ifname_map;
+
+ list_for_each_entry(ifname_map, &dl->ifname_map_list, list) {
+ if (strcmp(ifname, ifname_map->ifname) == 0) {
+ *p_bus_name = ifname_map->bus_name;
+ *p_dev_name = ifname_map->dev_name;
+ *p_port_index = ifname_map->port_index;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+static unsigned int strslashcount(char *str)
+{
+ unsigned int count = 0;
+ char *pos = str;
+
+ while ((pos = strchr(pos, '/'))) {
+ count++;
+ pos++;
+ }
+ return count;
+}
+
+static int strslashrsplit(char *str, char **before, char **after)
+{
+ char *slash;
+
+ slash = strrchr(str, '/');
+ if (!slash)
+ return -EINVAL;
+ *slash = '\0';
+ *before = str;
+ *after = slash + 1;
+ return 0;
+}
+
+static int strtouint32_t(const char *str, uint32_t *p_val)
+{
+ char *endptr;
+ unsigned long int val;
+
+ val = strtoul(str, &endptr, 10);
+ if (endptr == str || *endptr != '\0')
+ return -EINVAL;
+ if (val > UINT_MAX)
+ return -ERANGE;
+ *p_val = val;
+ return 0;
+}
+
+static int dl_argv_put_handle(struct nlmsghdr *nlh, struct dl *dl)
+{
+ char *str = dl_argv_next(dl);
+ char *bus_name = bus_name;
+ char *dev_name = dev_name;
+
+ if (!str) {
+ pr_err("Devlink identification (\"bus_name/dev_name\") expected\n");
+ return -EINVAL;
+ }
+ if (strslashcount(str) != 1) {
+ pr_err("Wrong devlink identification string format.\n");
+ pr_err("Expected \"bus_name/dev_name\".\n");
+ return -EINVAL;
+ }
+
+ strslashrsplit(str, &bus_name, &dev_name);
+ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name);
+ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name);
+ return 0;
+}
+
+static int dl_argv_put_handle_port(struct nlmsghdr *nlh, struct dl *dl)
+{
+ char *str = dl_argv_next(dl);
+ unsigned int slash_count;
+ char *bus_name = bus_name;
+ char *dev_name = dev_name;
+ uint32_t port_index = port_index;
+ int err;
+
+ if (!str) {
+ pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n");
+ return -EINVAL;
+ }
+ slash_count = strslashcount(str);
+ if (slash_count != 2 && slash_count != 0) {
+ pr_err("Wrong port identification string format.\n");
+ pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n");
+ return -EINVAL;
+ }
+
+ if (slash_count == 2) {
+ char *handlestr = handlestr;
+ char *portstr = portstr;
+
+ err = strslashrsplit(str, &handlestr, &portstr);
+ err = strtouint32_t(portstr, &port_index);
+ if (err) {
+ pr_err("Port index \"%s\" is not a number or not within range\n", portstr);
+ return err;
+ }
+ strslashrsplit(handlestr, &bus_name, &dev_name);
+ } else if (slash_count == 0) {
+ err = ifname_map_lookup(dl, str, &bus_name, &dev_name,
+ &port_index);
+ if (err) {
+ pr_err("Netdevice \"%s\" not found\n", str);
+ return err;
+ }
+ }
+ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name);
+ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name);
+ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, port_index);
+ return 0;
+}
+
+static int dl_argv_uint32_t(struct dl *dl, uint32_t *p_val)
+{
+ char *str = dl_argv_next(dl);
+ int err;
+
+ if (!str) {
+ pr_err("Unsigned number argument expected\n");
+ return -EINVAL;
+ }
+
+ err = strtouint32_t(str, p_val);
+ if (err) {
+ pr_err("\"%s\" is not a number or not within range\n", str);
+ return err;
+ }
+ return 0;
+}
+
+static int dl_argv_str(struct dl *dl, const char **p_str)
+{
+ const char *str = dl_argv_next(dl);
+
+ if (!str) {
+ pr_err("String parameter expected\n");
+ return -EINVAL;
+ }
+ *p_str = str;
+ return 0;
+}
+
+static int port_type_get(const char *typestr, enum devlink_port_type *p_type)
+{
+ if (strcmp(typestr, "auto") == 0) {
+ *p_type = DEVLINK_PORT_TYPE_AUTO;
+ } else if (strcmp(typestr, "eth") == 0) {
+ *p_type = DEVLINK_PORT_TYPE_ETH;
+ } else if (strcmp(typestr, "ib") == 0) {
+ *p_type = DEVLINK_PORT_TYPE_IB;
+ } else {
+ pr_err("Unknown port type \"%s\"\n", typestr);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#define BIT(nr) (1UL << (nr))
+#define DL_OPT_HANDLE BIT(0)
+#define DL_OPT_HANDLEP BIT(1)
+#define DL_OPT_PORT_TYPE BIT(2)
+#define DL_OPT_PORT_COUNT BIT(3)
+
+static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
+ uint32_t o_required, uint32_t o_optional)
+{
+ uint32_t o_all = o_required | o_optional;
+ uint32_t o_found = 0;
+ int err;
+
+ if (o_required & DL_OPT_HANDLE) {
+ err = dl_argv_put_handle(nlh, dl);
+ if (err)
+ return err;
+ } else if (o_required & DL_OPT_HANDLEP) {
+ err = dl_argv_put_handle_port(nlh, dl);
+ if (err)
+ return err;
+ }
+
+ while (dl_argc(dl)) {
+ if (dl_argv_match(dl, "type") &&
+ (o_all & DL_OPT_PORT_TYPE)) {
+ enum devlink_port_type port_type;
+ const char *typestr;
+
+ dl_arg_inc(dl);
+ err = dl_argv_str(dl, &typestr);
+ if (err)
+ return err;
+ err = port_type_get(typestr, &port_type);
+ if (err)
+ return err;
+ mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_TYPE,
+ port_type);
+ o_found |= DL_OPT_PORT_TYPE;
+ } else if (dl_argv_match(dl, "count") &&
+ (o_all & DL_OPT_PORT_COUNT)) {
+ uint32_t count;
+
+ dl_arg_inc(dl);
+ err = dl_argv_uint32_t(dl, &count);
+ if (err)
+ return err;
+ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, count);
+ o_found |= DL_OPT_PORT_COUNT;
+ } else {
+ pr_err("Unknown option \"%s\"\n", dl_argv(dl));
+ return -EINVAL;
+ }
+ }
+
+ if ((o_required & DL_OPT_PORT_TYPE) && !(o_found & DL_OPT_PORT_TYPE)) {
+ pr_err("Port type option expected.\n");
+ return -EINVAL;
+ }
+
+ if ((o_required & DL_OPT_PORT_COUNT) && !(o_found & DL_OPT_PORT_COUNT)) {
+ pr_err("Port split count option expected.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void cmd_dev_help(void) {
+ pr_out("Usage: devlink dev show [ DEV ]\n");
+}
+
+static void pr_out_handle(struct nlattr **tb)
+{
+ pr_out("%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]),
+ mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]));
+}
+
+static void pr_out_dev(struct nlattr **tb)
+{
+ pr_out_handle(tb);
+ pr_out("\n");
+}
+
+static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+
+ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
+ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME])
+ return MNL_CB_ERROR;
+ pr_out_dev(tb);
+ return MNL_CB_OK;
+}
+
+static int cmd_dev_show(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
+ int err;
+
+ if (dl_argc(dl) == 0)
+ flags |= NLM_F_DUMP;
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_GET, flags);
+
+ if (dl_argc(dl) > 0) {
+ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
+ }
+
+ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dev_show_cb, NULL);
+}
+
+static int cmd_dev(struct dl *dl)
+{
+ if (dl_argv_match(dl, "help")) {
+ cmd_dev_help();
+ return 0;
+ } else if (dl_argv_match(dl, "show") ||
+ dl_argv_match(dl, "list") || dl_no_arg(dl)) {
+ dl_arg_inc(dl);
+ return cmd_dev_show(dl);
+ } else {
+ pr_err("Command \"%s\" not found\n", dl_argv(dl));
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static void cmd_port_help(void) {
+ pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n");
+ pr_out(" dl port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
+ pr_out(" dl port split DEV/PORT_INDEX count COUNT\n");
+ pr_out(" dl port unsplit DEV/PORT_INDEX\n");
+}
+
+static const char *port_type_name(uint32_t type)
+{
+ switch (type) {
+ case DEVLINK_PORT_TYPE_NOTSET: return "notset";
+ case DEVLINK_PORT_TYPE_AUTO: return "auto";
+ case DEVLINK_PORT_TYPE_ETH: return "eth";
+ case DEVLINK_PORT_TYPE_IB: return "ib";
+ default: return "<unknown type>";
+ }
+}
+
+static void pr_out_port(struct nlattr **tb)
+{
+ pr_out_handle(tb);
+ pr_out("/%d:", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX]));
+ if (tb[DEVLINK_ATTR_PORT_TYPE]) {
+ uint16_t port_type = mnl_attr_get_u16(tb[DEVLINK_ATTR_PORT_TYPE]);
+
+ pr_out(" type %s", port_type_name(port_type));
+ if (tb[DEVLINK_ATTR_PORT_DESIRED_TYPE]) {
+ uint16_t des_port_type = mnl_attr_get_u16(tb[DEVLINK_ATTR_PORT_DESIRED_TYPE]);
+
+ if (port_type != des_port_type)
+ pr_out("(%s)", port_type_name(des_port_type));
+ }
+ }
+ if (tb[DEVLINK_ATTR_PORT_NETDEV_NAME])
+ pr_out(" netdev %s",
+ mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_NETDEV_NAME]));
+ if (tb[DEVLINK_ATTR_PORT_IBDEV_NAME])
+ pr_out(" ibdev %s",
+ mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_IBDEV_NAME]));
+ if (tb[DEVLINK_ATTR_PORT_SPLIT_GROUP])
+ pr_out(" split_group %u",
+ mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_SPLIT_GROUP]));
+ pr_out("\n");
+}
+
+static int cmd_port_show_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+
+ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
+ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] ||
+ !tb[DEVLINK_ATTR_PORT_INDEX])
+ return MNL_CB_ERROR;
+ pr_out_port(tb);
+ return MNL_CB_OK;
+}
+
+static int cmd_port_show(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
+ int err;
+
+ if (dl_argc(dl) == 0)
+ flags |= NLM_F_DUMP;
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_GET, flags);
+
+ if (dl_argc(dl) > 0) {
+ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0);
+ if (err)
+ return err;
+ }
+
+ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_port_show_cb, NULL);
+}
+
+static int cmd_port_set(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ int err;
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SET,
+ NLM_F_REQUEST | NLM_F_ACK);
+
+ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_TYPE, 0);
+ if (err)
+ return err;
+
+ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
+}
+
+static int cmd_port_split(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ int err;
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SPLIT,
+ NLM_F_REQUEST | NLM_F_ACK);
+
+ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_COUNT, 0);
+ if (err)
+ return err;
+
+ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
+}
+
+static int cmd_port_unsplit(struct dl *dl)
+{
+ struct nlmsghdr *nlh;
+ int err;
+
+ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_UNSPLIT,
+ NLM_F_REQUEST | NLM_F_ACK);
+
+ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0);
+ if (err)
+ return err;
+
+ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
+}
+
+static int cmd_port(struct dl *dl)
+{
+ if (dl_argv_match(dl, "help")) {
+ cmd_port_help();
+ return 0;
+ } else if (dl_argv_match(dl, "show") ||
+ dl_argv_match(dl, "list") || dl_no_arg(dl)) {
+ dl_arg_inc(dl);
+ return cmd_port_show(dl);
+ } else if (dl_argv_match(dl, "set")) {
+ dl_arg_inc(dl);
+ return cmd_port_set(dl);
+ } else if (dl_argv_match(dl, "split")) {
+ dl_arg_inc(dl);
+ return cmd_port_split(dl);
+ } else if (dl_argv_match(dl, "unsplit")) {
+ dl_arg_inc(dl);
+ return cmd_port_unsplit(dl);
+ } else {
+ pr_err("Command \"%s\" not found\n", dl_argv(dl));
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static const char *cmd_name(uint8_t cmd)
+{
+ switch (cmd) {
+ case DEVLINK_CMD_UNSPEC: return "unspec";
+ case DEVLINK_CMD_GET: return "get";
+ case DEVLINK_CMD_SET: return "set";
+ case DEVLINK_CMD_NEW: return "new";
+ case DEVLINK_CMD_DEL: return "del";
+ case DEVLINK_CMD_PORT_GET: return "get";
+ case DEVLINK_CMD_PORT_SET: return "set";
+ case DEVLINK_CMD_PORT_NEW: return "net";
+ case DEVLINK_CMD_PORT_DEL: return "del";
+ default: return "<unknown cmd>";
+ }
+}
+
+static const char *cmd_obj(uint8_t cmd)
+{
+ switch (cmd) {
+ case DEVLINK_CMD_UNSPEC: return "unspec";
+ case DEVLINK_CMD_GET:
+ case DEVLINK_CMD_SET:
+ case DEVLINK_CMD_NEW:
+ case DEVLINK_CMD_DEL:
+ return "dev";
+ case DEVLINK_CMD_PORT_GET:
+ case DEVLINK_CMD_PORT_SET:
+ case DEVLINK_CMD_PORT_NEW:
+ case DEVLINK_CMD_PORT_DEL:
+ return "port";
+ default: return "<unknown obj>";
+ }
+}
+
+static void pr_out_mon_header(uint8_t cmd)
+{
+ pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd));
+}
+
+static bool cmd_filter_check(struct dl *dl, uint8_t cmd)
+{
+ const char *obj = cmd_obj(cmd);
+ unsigned index = 0;
+ const char *cur_obj;
+
+ if (dl_no_arg(dl))
+ return true;
+ while ((cur_obj = dl_argv_index(dl, index++))) {
+ if (strcmp(cur_obj, obj) == 0 || strcmp(cur_obj, "all") == 0)
+ return true;
+ }
+ return false;
+}
+
+static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct dl *dl = data;
+ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+ uint8_t cmd = genl->cmd;
+
+ if (!cmd_filter_check(dl, cmd))
+ return MNL_CB_OK;
+
+ switch (cmd) {
+ case DEVLINK_CMD_GET: /* fall through */
+ case DEVLINK_CMD_SET: /* fall through */
+ case DEVLINK_CMD_NEW: /* fall through */
+ case DEVLINK_CMD_DEL:
+ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
+ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME])
+ return MNL_CB_ERROR;
+ pr_out_mon_header(genl->cmd);
+ pr_out_dev(tb);
+ break;
+ case DEVLINK_CMD_PORT_GET: /* fall through */
+ case DEVLINK_CMD_PORT_SET: /* fall through */
+ case DEVLINK_CMD_PORT_NEW: /* fall through */
+ case DEVLINK_CMD_PORT_DEL:
+ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
+ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] ||
+ !tb[DEVLINK_ATTR_PORT_INDEX])
+ return MNL_CB_ERROR;
+ pr_out_mon_header(genl->cmd);
+ pr_out_port(tb);
+ break;
+ }
+ return MNL_CB_OK;
+}
+
+static int cmd_mon_show(struct dl *dl)
+{
+ int err;
+ unsigned index = 0;
+ const char *cur_obj;
+
+ while ((cur_obj = dl_argv_index(dl, index++))) {
+ if (strcmp(cur_obj, "all") != 0 &&
+ strcmp(cur_obj, "dev") != 0 &&
+ strcmp(cur_obj, "port") != 0) {
+ pr_err("Unknown object \"%s\"\n", cur_obj);
+ return -EINVAL;
+ }
+ }
+ err = _mnlg_socket_group_add(dl->nlg, DEVLINK_GENL_MCGRP_CONFIG_NAME);
+ if (err)
+ return err;
+ err = _mnlg_socket_recv_run(dl->nlg, cmd_mon_show_cb, dl);
+ if (err)
+ return err;
+ return 0;
+}
+
+static void cmd_mon_help(void) {
+ pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n"
+ "where OBJECT-LIST := { dev | port }\n");
+}
+
+static int cmd_mon(struct dl *dl)
+{
+ if (dl_argv_match(dl, "help")) {
+ cmd_mon_help();
+ return 0;
+ } else if (dl_no_arg(dl)) {
+ dl_arg_inc(dl);
+ return cmd_mon_show(dl);
+ } else {
+ pr_err("Command \"%s\" not found\n", dl_argv(dl));
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static void help(void) {
+ pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
+ "where OBJECT := { dev | port | monitor }\n"
+ " OPTIONS := { -V[ersion] }\n");
+}
+
+static int dl_cmd(struct dl *dl)
+{
+ if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
+ help();
+ return 0;
+ } else if (dl_argv_match(dl, "dev")) {
+ dl_arg_inc(dl);
+ return cmd_dev(dl);
+ } else if (dl_argv_match(dl, "port")) {
+ dl_arg_inc(dl);
+ return cmd_port(dl);
+ } else if (dl_argv_match(dl, "monitor")) {
+ dl_arg_inc(dl);
+ return cmd_mon(dl);
+ } else {
+ pr_err("Object \"%s\" not found\n", dl_argv(dl));
+ return -ENOENT;
+ }
+ return 0;
+}
+
+static int dl_init(struct dl *dl, int argc, char **argv)
+{
+ int err;
+
+ dl->argc = argc;
+ dl->argv = argv;
+
+ dl->nlg = mnlg_socket_open(DEVLINK_GENL_NAME, DEVLINK_GENL_VERSION);
+ if (!dl->nlg) {
+ pr_err("Failed to connect to devlink Netlink\n");
+ return -errno;
+ }
+
+ err = ifname_map_init(dl);
+ if (err) {
+ pr_err("Failed to create index map\n");
+ goto err_ifname_map_create;
+ }
+ return 0;
+
+err_ifname_map_create:
+ mnlg_socket_close(dl->nlg);
+ return err;
+}
+
+static void dl_fini(struct dl *dl)
+{
+ ifname_map_fini(dl);
+ mnlg_socket_close(dl->nlg);
+}
+
+static struct dl *dl_alloc(void)
+{
+ struct dl *dl;
+
+ dl = calloc(1, sizeof(*dl));
+ if (!dl)
+ return NULL;
+ return dl;
+}
+
+static void dl_free(struct dl *dl)
+{
+ free(dl);
+}
+
+int main(int argc, char **argv)
+{
+ static const struct option long_options[] = {
+ { "Version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+ struct dl *dl;
+ int opt;
+ int err;
+ int ret;
+
+ while ((opt = getopt_long(argc, argv, "V",
+ long_options, NULL)) >= 0) {
+
+ switch(opt) {
+ case 'V':
+ printf("devlink utility, iproute2-ss%s\n", SNAPSHOT);
+ return EXIT_SUCCESS;
+ default:
+ pr_err("Unknown option.\n");
+ help();
+ return EXIT_FAILURE;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ dl = dl_alloc();
+ if (!dl) {
+ pr_err("Failed to allocate memory for devlink\n");
+ return EXIT_FAILURE;
+ }
+
+ err = dl_init(dl, argc, argv);
+ if (err) {
+ ret = EXIT_FAILURE;
+ goto dl_free;
+ }
+
+ err = dl_cmd(dl);
+ if (err) {
+ ret = EXIT_FAILURE;
+ goto dl_fini;
+ }
+
+ ret = EXIT_SUCCESS;
+
+dl_fini:
+ dl_fini(dl);
+dl_free:
+ dl_free(dl);
+
+ return ret;
+}
+
diff --git a/devlink/mnlg.c b/devlink/mnlg.c
new file mode 100644
index 0000000..6d8cb94
--- /dev/null
+++ b/devlink/mnlg.c
@@ -0,0 +1,274 @@
+/*
+ * mnlg.c Generic Netlink helpers for libmnl
+ *
+ * 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: Jiri Pirko <jiri@mellanox.com>
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <libmnl/libmnl.h>
+#include <linux/genetlink.h>
+
+#include "mnlg.h"
+
+struct mnlg_socket {
+ struct mnl_socket *nl;
+ char *buf;
+ uint32_t id;
+ uint8_t version;
+ unsigned int seq;
+ unsigned int portid;
+};
+
+static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
+ uint16_t flags, uint32_t id,
+ uint8_t version)
+{
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *genl;
+
+ nlh = mnl_nlmsg_put_header(nlg->buf);
+ nlh->nlmsg_type = id;
+ nlh->nlmsg_flags = flags;
+ nlg->seq = time(NULL);
+ nlh->nlmsg_seq = nlg->seq;
+
+ genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
+ genl->cmd = cmd;
+ genl->version = version;
+
+ return nlh;
+}
+
+struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
+ uint16_t flags)
+{
+ return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
+}
+
+int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
+{
+ return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
+}
+
+int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
+{
+ int err;
+
+ do {
+ err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
+ MNL_SOCKET_BUFFER_SIZE);
+ if (err <= 0)
+ break;
+ err = mnl_cb_run(nlg->buf, err, nlg->seq, nlg->portid,
+ data_cb, data);
+ } while (err > 0);
+
+ return err;
+}
+
+struct group_info {
+ bool found;
+ uint32_t id;
+ const char *name;
+};
+
+static int parse_mc_grps_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, CTRL_ATTR_MCAST_GRP_MAX) < 0)
+ return MNL_CB_OK;
+
+ switch(type) {
+ case CTRL_ATTR_MCAST_GRP_ID:
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ return MNL_CB_ERROR;
+ break;
+ case CTRL_ATTR_MCAST_GRP_NAME:
+ if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
+ return MNL_CB_ERROR;
+ break;
+ }
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static void parse_genl_mc_grps(struct nlattr *nested,
+ struct group_info *group_info)
+{
+ struct nlattr *pos;
+ const char *name;
+
+ mnl_attr_for_each_nested(pos, nested) {
+ struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1] = {};
+
+ mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb);
+ if (!tb[CTRL_ATTR_MCAST_GRP_NAME] ||
+ !tb[CTRL_ATTR_MCAST_GRP_ID])
+ continue;
+
+ name = mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]);
+ if (strcmp(name, group_info->name) != 0)
+ continue;
+
+ group_info->id = mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]);
+ group_info->found = true;
+ }
+}
+
+static int get_group_id_attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
+
+ if (type == CTRL_ATTR_MCAST_GROUPS &&
+ mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
+ return MNL_CB_ERROR;
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static int get_group_id_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct group_info *group_info = data;
+ struct nlattr *tb[CTRL_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+
+ mnl_attr_parse(nlh, sizeof(*genl), get_group_id_attr_cb, tb);
+ if (!tb[CTRL_ATTR_MCAST_GROUPS])
+ return MNL_CB_ERROR;
+ parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS], group_info);
+ return MNL_CB_OK;
+}
+
+int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name)
+{
+ struct nlmsghdr *nlh;
+ struct group_info group_info;
+ int err;
+
+ nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
+ NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
+ mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, nlg->id);
+
+ err = mnlg_socket_send(nlg, nlh);
+ if (err < 0)
+ return err;
+
+ group_info.found = false;
+ group_info.name = group_name;
+ err = mnlg_socket_recv_run(nlg, get_group_id_cb, &group_info);
+ if (err < 0)
+ return err;
+
+ if (!group_info.found) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ err = mnl_socket_setsockopt(nlg->nl, NETLINK_ADD_MEMBERSHIP,
+ &group_info.id, sizeof(group_info.id));
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
+
+ if (type == CTRL_ATTR_FAMILY_ID &&
+ mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ return MNL_CB_ERROR;
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
+{
+ uint32_t *p_id = data;
+ struct nlattr *tb[CTRL_ATTR_MAX + 1] = {};
+ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
+
+ mnl_attr_parse(nlh, sizeof(*genl), get_family_id_attr_cb, tb);
+ if (!tb[CTRL_ATTR_FAMILY_ID])
+ return MNL_CB_ERROR;
+ *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
+ return MNL_CB_OK;
+}
+
+struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
+{
+ struct mnlg_socket *nlg;
+ struct nlmsghdr *nlh;
+ int err;
+
+ nlg = malloc(sizeof(*nlg));
+ if (!nlg)
+ return NULL;
+
+ nlg->buf = malloc(MNL_SOCKET_BUFFER_SIZE);
+ if (!nlg->buf)
+ goto err_buf_alloc;
+
+ nlg->nl = mnl_socket_open(NETLINK_GENERIC);
+ if (!nlg->nl)
+ goto err_mnl_socket_open;
+
+ err = mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID);
+ if (err < 0)
+ goto err_mnl_socket_bind;
+
+ nlg->portid = mnl_socket_get_portid(nlg->nl);
+
+ nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
+ NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
+ mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
+
+ err = mnlg_socket_send(nlg, nlh);
+ if (err < 0)
+ goto err_mnlg_socket_send;
+
+ err = mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id);
+ if (err < 0)
+ goto err_mnlg_socket_recv_run;
+
+ nlg->version = version;
+ return nlg;
+
+err_mnlg_socket_recv_run:
+err_mnlg_socket_send:
+err_mnl_socket_bind:
+ mnl_socket_close(nlg->nl);
+err_mnl_socket_open:
+ free(nlg->buf);
+err_buf_alloc:
+ free(nlg);
+ return NULL;
+}
+
+void mnlg_socket_close(struct mnlg_socket *nlg)
+{
+ mnl_socket_close(nlg->nl);
+ free(nlg->buf);
+ free(nlg);
+}
diff --git a/devlink/mnlg.h b/devlink/mnlg.h
new file mode 100644
index 0000000..4d1babf
--- /dev/null
+++ b/devlink/mnlg.h
@@ -0,0 +1,27 @@
+/*
+ * mnlg.h Generic Netlink helpers for libmnl
+ *
+ * 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: Jiri Pirko <jiri@mellanox.com>
+ */
+
+#ifndef _MNLG_H_
+#define _MNLG_H_
+
+#include <libmnl/libmnl.h>
+
+struct mnlg_socket;
+
+struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
+ uint16_t flags);
+int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh);
+int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data);
+int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name);
+struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version);
+void mnlg_socket_close(struct mnlg_socket *nlg);
+
+#endif /* _MNLG_H_ */
diff --git a/include/linux/devlink.h b/include/linux/devlink.h
new file mode 100644
index 0000000..c9fee57
--- /dev/null
+++ b/include/linux/devlink.h
@@ -0,0 +1,72 @@
+/*
+ * include/uapi/linux/devlink.h - Network physical device Netlink interface
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
+ *
+ * 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.
+ */
+
+#ifndef _UAPI_LINUX_DEVLINK_H_
+#define _UAPI_LINUX_DEVLINK_H_
+
+#define DEVLINK_GENL_NAME "devlink"
+#define DEVLINK_GENL_VERSION 0x1
+#define DEVLINK_GENL_MCGRP_CONFIG_NAME "config"
+
+enum devlink_command {
+ /* don't change the order or add anything between, this is ABI! */
+ DEVLINK_CMD_UNSPEC,
+
+ DEVLINK_CMD_GET, /* can dump */
+ DEVLINK_CMD_SET,
+ DEVLINK_CMD_NEW,
+ DEVLINK_CMD_DEL,
+
+ DEVLINK_CMD_PORT_GET, /* can dump */
+ DEVLINK_CMD_PORT_SET,
+ DEVLINK_CMD_PORT_NEW,
+ DEVLINK_CMD_PORT_DEL,
+
+ DEVLINK_CMD_PORT_SPLIT,
+ DEVLINK_CMD_PORT_UNSPLIT,
+
+ /* add new commands above here */
+
+ __DEVLINK_CMD_MAX,
+ DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
+};
+
+enum devlink_port_type {
+ DEVLINK_PORT_TYPE_NOTSET,
+ DEVLINK_PORT_TYPE_AUTO,
+ DEVLINK_PORT_TYPE_ETH,
+ DEVLINK_PORT_TYPE_IB,
+};
+
+enum devlink_attr {
+ /* don't change the order or add anything between, this is ABI! */
+ DEVLINK_ATTR_UNSPEC,
+
+ /* bus name + dev name together are a handle for devlink entity */
+ DEVLINK_ATTR_BUS_NAME, /* string */
+ DEVLINK_ATTR_DEV_NAME, /* string */
+
+ DEVLINK_ATTR_PORT_INDEX, /* u32 */
+ DEVLINK_ATTR_PORT_TYPE, /* u16 */
+ DEVLINK_ATTR_PORT_DESIRED_TYPE, /* u16 */
+ DEVLINK_ATTR_PORT_NETDEV_IFINDEX, /* u32 */
+ DEVLINK_ATTR_PORT_NETDEV_NAME, /* string */
+ DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */
+ DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */
+ DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */
+
+ /* add new attributes above here, update the policy in devlink.c */
+
+ __DEVLINK_ATTR_MAX,
+ DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1
+};
+
+#endif /* _UAPI_LINUX_DEVLINK_H_ */
diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8
new file mode 100644
index 0000000..7878d89
--- /dev/null
+++ b/man/man8/devlink-dev.8
@@ -0,0 +1,58 @@
+.TH DEVLINK\-DEV 8 "14 Mar 2016" "iproute2" "Linux"
+.SH NAME
+devlink-dev \- devlink device configuration
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B devlink
+.RI "[ " OPTIONS " ]"
+.B dev
+.RI " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+
+.ti -8
+.B devlink dev show
+.RI "[ " DEV " ]"
+
+.ti -8
+.B devlink dev help
+
+.SH "DESCRIPTION"
+.SS devlink dev show - display devlink device attributes
+
+.PP
+.I "DEV"
+- specifies the devlink device to show.
+If this argument is omitted all devices are listed.
+
+.in +4
+Format is:
+.in +2
+BUS_NAME/BUS_ADDRESS
+
+.SH "EXAMPLES"
+.PP
+devlink dev show
+.RS 4
+Shows the state of all devlink devices on the system.
+.RE
+.PP
+devlink dev show pci/0000:01:00.0
+.RS 4
+Shows the state of specified devlink device.
+
+.SH SEE ALSO
+.BR devlink (8),
+.BR devlink-port (8),
+.BR devlink-monitor (8),
+.br
+
+.SH AUTHOR
+Jiri Pirko <jiri@mellanox.com>
diff --git a/man/man8/devlink-monitor.8 b/man/man8/devlink-monitor.8
new file mode 100644
index 0000000..98134c3
--- /dev/null
+++ b/man/man8/devlink-monitor.8
@@ -0,0 +1,36 @@
+.TH DEVLINK\-MONITOR 8 "14 Mar 2016" "iproute2" "Linux"
+.SH "NAME"
+devlink-monitor \- state monitoring
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.BR "devlink monitor" " [ " all " |"
+.IR OBJECT-LIST " ]"
+.sp
+
+.SH DESCRIPTION
+The
+.B devlink
+utility can monitor the state of devlink devices and ports
+continuously. This option has a slightly different format. Namely, the
+.B monitor
+command is the first in the command line and then the object list.
+
+.I OBJECT-LIST
+is the list of object types that we want to monitor.
+It may contain
+.BR dev ", " port ".
+
+.B devlink
+opens Devlink Netlink socket, listens on it and dumps state changes.
+
+.SH SEE ALSO
+.BR devlink (8),
+.BR devlink-dev (8),
+.BR devlink-port (8),
+.br
+
+.SH AUTHOR
+Jiri Pirko <jiri@mellanox.com>
diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8
new file mode 100644
index 0000000..173de75
--- /dev/null
+++ b/man/man8/devlink-port.8
@@ -0,0 +1,126 @@
+.TH DEVLINK\-PORT 8 "14 Mar 2016" "iproute2" "Linux"
+.SH NAME
+devlink-port \- devlink port configuration
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B devlink
+.RI "[ " OPTIONS " ]"
+.B port
+.RI " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+
+.ti -8
+.BR "devlink port set "
+.IR DEV/PORT_INDEX
+.RI "[ "
+.BR type " { " eth " | " ib " | " auto " }"
+.RI "]"
+
+.ti -8
+.BR "devlink port split "
+.IR DEV/PORT_INDEX
+.BR count
+.IR COUNT
+
+.ti -8
+.BR "devlink port unsplit "
+.IR DEV/PORT_INDEX
+
+.ti -8
+.B devlink port show
+.RI "[ " DEV/PORT_INDEX " ]"
+
+.ti -8
+.B devlink port help
+
+.SH "DESCRIPTION"
+.SS devlink port set - change devlink port attributes
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to operate on.
+
+.in +4
+Format is:
+.in +2
+BUS_NAME/BUS_ADDRESS/PORT_INDEX
+
+.TP
+.BR type " { " eth " | " ib " | " auto " } "
+set port type
+
+.I eth
+- Ethernet
+
+.I ib
+- Infiniband
+
+.I auto
+- autoselect
+
+.SS devlink port split - split devlink port into more
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to operate on.
+
+.TP
+.BI count " COUNT"
+number of ports to split to.
+
+.SS devlink port unsplit - unsplit previously splitted devlink port
+Could be performed on any splitted port of the same split group.
+
+.PP
+.B "DEV/PORT_INDEX"
+- specifies the devlink port to operate on.
+
+.SS devlink port show - display devlink port attributes
+
+.PP
+.I "DEV/PORT_INDEX"
+- specifies the devlink port to show.
+If this argument is omitted all ports are listed.
+
+.SH "EXAMPLES"
+.PP
+devlink port show
+.RS 4
+Shows the state of all devlink ports on the system.
+.RE
+.PP
+devlink port show pci/0000:01:00.0/1
+.RS 4
+Shows the state of specified devlink port.
+.RE
+.PP
+devlink port set pci/0000:01:00.0/1 type eth
+.RS 4
+Set type of specified devlink port to Ethernet.
+.RE
+.PP
+devlink port split pci/0000:01:00.0/1 count 4
+.RS 4
+Split the specified devlink port into four ports.
+.RE
+.PP
+devlink port unsplit pci/0000:01:00.0/1
+.RS 4
+Unplit the specified previously splitted devlink port.
+
+.SH SEE ALSO
+.BR devlink (8),
+.BR devlink-dev (8),
+.BR devlink-monitor (8),
+.br
+
+.SH AUTHOR
+Jiri Pirko <jiri@mellanox.com>
diff --git a/man/man8/devlink.8 b/man/man8/devlink.8
new file mode 100644
index 0000000..f608ccc
--- /dev/null
+++ b/man/man8/devlink.8
@@ -0,0 +1,83 @@
+.TH DEVLINK 8 "14 Mar 2016" "iproute2" "Linux"
+.SH NAME
+devlink \- Devlink tool
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B devlink
+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OBJECT " := { "
+.BR dev " | " port " | " monitor " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-V\fR[\fIersion\fR] |
+
+.SH OPTIONS
+
+.TP
+.BR "\-V" , " -Version"
+Print the version of the
+.B devlink
+utility and exit.
+
+.SS
+.I OBJECT
+
+.TP
+.B dev
+- devlink device.
+
+.TP
+.B port
+- devlink port.
+
+.TP
+.B monitor
+- watch for netlink messages.
+
+.SS
+.I COMMAND
+
+Specifies the action to perform on the object.
+The set of possible actions depends on the object type.
+As a rule, it is possible to
+.B show
+(or
+.B list
+) objects, but some objects do not allow all of these operations
+or have some additional commands. The
+.B help
+command is available for all objects. It prints
+out a list of available commands and argument syntax conventions.
+.sp
+If no command is given, some default command is assumed.
+Usually it is
+.B list
+or, if the objects of this class cannot be listed,
+.BR "help" .
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR devlink-dev (8),
+.BR devlink-port (8),
+.BR devlink-monitor (8),
+.br
+
+.SH REPORTING BUGS
+Report any bugs to the Network Developers mailing list
+.B <netdev@vger.kernel.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Jiri Pirko <jiri@mellanox.com>
--
2.5.0
^ permalink raw reply related
* [patch iproute2 1/2] include: add linked list implementation from kernel
From: Jiri Pirko @ 2016-03-15 14:43 UTC (permalink / raw)
To: netdev
Cc: stephen, davem, idosch, eladr, yotamg, ogerlitz, yishaih,
dledford, sean.hefty, hal.rosenstock, eugenia, roopa, nikolay,
hadarh, jhs, john.fastabend, jeffrey.t.kirsher, brouer, ivecera,
rami.rosen, hannes, gospo
From: Jiri Pirko <jiri@mellanox.com>
Rename hlist.h to list.h while adding it to be aligned with kernel
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/hlist.h | 56 ----------------------------
include/list.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ip/ipnetns.c | 2 +-
lib/ll_map.c | 2 +-
tc/tc_class.c | 2 +-
5 files changed, 115 insertions(+), 59 deletions(-)
delete mode 100644 include/hlist.h
create mode 100644 include/list.h
diff --git a/include/hlist.h b/include/hlist.h
deleted file mode 100644
index 4e8de9e..0000000
--- a/include/hlist.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef __HLIST_H__
-#define __HLIST_H__ 1
-/* Hash list stuff from kernel */
-
-#include <stddef.h>
-
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-
-static inline void hlist_del(struct hlist_node *n)
-{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
- *pprev = next;
- if (next)
- next->pprev = pprev;
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
- n->next = first;
- if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
-}
-
-#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos ; pos = pos->next)
-
-
-#define hlist_for_each_safe(pos, n, head) \
- for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
- pos = n)
-
-#define hlist_entry_safe(ptr, type, member) \
- ({ typeof(ptr) ____ptr = (ptr); \
- ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
- })
-
-#define hlist_for_each_entry(pos, head, member) \
- for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
- pos; \
- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
-
-#endif /* __HLIST_H__ */
diff --git a/include/list.h b/include/list.h
new file mode 100644
index 0000000..efffd83
--- /dev/null
+++ b/include/list.h
@@ -0,0 +1,112 @@
+#ifndef __LIST_H__
+#define __LIST_H__ 1
+/* List and hash list stuff from kernel */
+
+#include <stddef.h>
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member), \
+ n = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = n, n = list_next_entry(n, member))
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos ; pos = pos->next)
+
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+#define hlist_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+ })
+
+#define hlist_for_each_entry(pos, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+#endif /* __LIST_H__ */
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 4ce5989..0596b2c 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -18,7 +18,7 @@
#include <linux/net_namespace.h>
#include "utils.h"
-#include "hlist.h"
+#include "list.h"
#include "ip_common.h"
#include "namespace.h"
diff --git a/lib/ll_map.c b/lib/ll_map.c
index c6f7027..fa14a77 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -22,7 +22,7 @@
#include "libnetlink.h"
#include "ll_map.h"
-#include "hlist.h"
+#include "list.h"
struct ll_cache {
struct hlist_node idx_hash;
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 3acd030..7d3b009 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -24,7 +24,7 @@
#include "utils.h"
#include "tc_util.h"
#include "tc_common.h"
-#include "hlist.h"
+#include "list.h"
struct graph_node {
struct hlist_node hlist;
--
2.5.0
^ permalink raw reply related
* Re: [PATCH] ARC: axs10x - add Ethernet PHY description in .dts
From: Sergei Shtylyov @ 2016-03-15 14:38 UTC (permalink / raw)
To: Alexey Brodkin, linux-snps-arc
Cc: Rob Herring, Phil Reid, David S. Miller, linux-kernel, netdev,
stable, #, 4.5.x
In-Reply-To: <1458034150-10766-1-git-send-email-abrodkin@synopsys.com>
Hello.
On 3/15/2016 12:29 PM, Alexey Brodkin wrote:
> Following commit broke DW GMAC functionality on AXS10x boards:
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=e34d65696d2ef13dc32f2a162556c86c461ed763
>
> That's what happens on eth0 up:
> --------------------------->8------------------------
> libphy: PHY stmmac-0:ffffffff not found
> eth0: Could not attach to PHY
> stmmac_open: Cannot attach to PHY (error: -19)
> --------------------------->8------------------------
>
> Simplest solution is to add PHY description in board's .dts.
> And so we do here.
>
> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Phil Reid <preid@electromag.com.au>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: stable@vger.kernel.org # 4.5.x
> ---
> arch/arc/boot/dts/axs10x_mb.dtsi | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
> index 44a578c..04b999e 100644
> --- a/arch/arc/boot/dts/axs10x_mb.dtsi
> +++ b/arch/arc/boot/dts/axs10x_mb.dtsi
> @@ -47,6 +47,14 @@
> clocks = <&apbclk>;
> clock-names = "stmmaceth";
> max-speed = <100>;
> + mdio0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "snps,dwmac-mdio";
> + phy0: ethernet-phy@0 {
The naming is inconsistent with the "reg" prop specified, should be @1.
MBR, Sergei
^ permalink raw reply
* Re: [PATCH] af_unix: closed SOCK_SEQPACKET socketpair must get SIGPIPE
From: Alexander Potapenko @ 2016-03-15 14:35 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Eric Dumazet, rweikusat, David Miller, LKML, netdev
In-Reply-To: <1458048051.31401.32.camel@edumazet-glaptop3.roam.corp.google.com>
On Tue, Mar 15, 2016 at 2:20 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Tue, 2016-03-15 at 10:03 +0100, Alexander Potapenko wrote:
>> According to IEEE Std 1003.1, 2013, sending data to a SOCK_SEQPACKET
>> socketpair with MSG_NOSIGNAL flag set must result in a SIGPIPE if the
>> socket is no longer connected.
>
> I find this sentence slightly confusing ?
>
> If MSG_NOSIGNAL is set, then SIGPIPE should not be generated.
>
> s/with/without/ maybe ?
>
Agreed. I've rewritten this a couple of times and failed to proof-read
it for the last time.
--
Alexander Potapenko
Software Engineer
Google Germany GmbH
Erika-Mann-Straße, 33
80636 München
Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
^ permalink raw reply
* RE: [PATCH v3] can: rcar_canfd: Add Renesas R-Car CAN FD driver
From: Ramesh Shanmugasundaram @ 2016-03-15 14:26 UTC (permalink / raw)
To: Marc Kleine-Budde, wg@grandegger.com, robh+dt@kernel.org,
pawel.moll@arm.com, mark.rutland@arm.com,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
corbet@lwn.net
Cc: linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-can@vger.kernel.org, netdev@vger.kernel.org,
linux-doc@vger.kernel.org, geert+renesas@glider.be,
Chris Paterson
In-Reply-To: <56E80567.9060201@pengutronix.de>
Hi Marc,
> Subject: Re: [PATCH v3] can: rcar_canfd: Add Renesas R-Car CAN FD driver
>
> On 03/15/2016 10:48 AM, Ramesh Shanmugasundaram wrote:
> > This patch adds support for the CAN FD controller found in Renesas
> > R-Car SoCs. The controller operates in CAN FD only mode by default.
> >
> > CAN FD mode supports both Classical CAN & CAN FD frame formats. The
> > controller supports ISO 11898-1:2015 CAN FD format only.
> >
> > This controller supports two channels and the driver can enable either
> > or both of the channels.
> >
> > Driver uses Rx FIFOs (one per channel) for reception & Common FIFOs
> > (one per channel) for transmission. Rx filter rules are configured to
> > the minimum (one per channel) and it accepts Standard, Extended, Data
> > & Remote Frame combinations.
> >
> > Note: There are few documentation errors in R-Car Gen3 Hardware User
> > Manual v0.5E with respect to CAN FD controller. They are listed below:
> >
> > 1. CAN FD interrupt numbers 29 & 30 are listed as per channel
> > interrupts. However, they are common to both channels (i.e.) they are
> > global and channel interrupts respectively.
> >
> > 2. CANFD clock is derived from PLL1. This is not documented.
> >
> > 3. CANFD clock is further divided by (1/2) within the CAN FD controller.
> > This is not documented.
> >
> > 4. The minimum value of NTSEG1 in RSCFDnCFDCmNCFG register is 2 Tq. It
> > is specified 4 Tq in the manual.
> >
> > 5. The maximum number of message RAM area the controller can use is
> > 3584 bytes. It is specified 10752 bytes in the manual.
> >
> > Signed-off-by: Ramesh Shanmugasundaram
> > <ramesh.shanmugasundaram@bp.renesas.com>
> > ---
> > Hi All,
> >
> > Thanks for the review comments.
> >
> > This updated patch is based on linux-can-next tag (linux-can-next-
> for-4.6-20160310).
> >
> > This patch depends on
> >
> > [RFC] [PATCH v3] can: fix handling of unmodifiable configuration
> options
> > (http://comments.gmane.org/gmane.linux.can/9126)
> >
> > Changes since v2:
> > * Rebased to latest tag (linux-can-next-for-4.6-20160310)
> > * Cleaned up leftover debugfs code (Thanks Oliver H)
> > * Revised devicetree documentation text (as suggested by Rob H)
> > (https://www.mail-archive.com/linux-renesas-
> soc@vger.kernel.org/msg01597.html)
> > * Used new can subsystem api to set static configuration & removed
> check in rcar_canfd_start (as suggested by Oliver H)
> > (Refer: http://comments.gmane.org/gmane.linux.can/9126 &
> > https://www.mail-archive.com/linux-renesas-
> soc@vger.kernel.org/msg01867.html)
> > * Clubbed Renesas controller drivers to driver/net/can/rcar dir (as
> > suggested by Oliver H)
>
> Please make moving of the existing drivers a separate patch.
OK. I'll submit new patch with CAN FD driver in new "rcar" dir and will provide a separate patch on top that will move the CAN driver to "rcar" dir.
Thanks,
Ramesh
^ permalink raw reply
* Re: [RFC PATCH kernel] Revert "net/mlx4_core: Set UAR page size to 4KB regardless of system page size"
From: Or Gerlitz @ 2016-03-15 14:23 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Alexey Kardashevskiy, Huy Nguyen, Doug Ledford, Eugenia Emantayev,
Hal Rosenstock, Sean Hefty, Yishai Hadas, Linux Kernel,
linux-rdma@vger.kernel.org, Linux Netdev List, Paul Mackerras,
Carol L Soto, Yevgeny Petrilin, Daniel Jurgens, Eli Cohen
In-Reply-To: <20160315121832.GA4741@infradead.org>
On Tue, Mar 15, 2016 at 2:18 PM, Christoph Hellwig <hch@infradead.org> wrote:
> On Tue, Mar 15, 2016 at 12:40:06PM +0200, Or Gerlitz wrote:
>> "[..] Regarding backward compatibility in SR-IOV, if hypervisor has
>> this new code, the virtual OS must be updated. [...]"
> Which is broken, we can't break user or guest VM ABIs ever.
Let us check. I was under (the maybe wrong) impression, that before this
patch both PF/VF drivers were not operative on some systems, so on those
systems it's fair to require the VF driver to be patched too.
Or.
^ permalink raw reply
* Re: [PATCH net-next v2 3/3] macsec: introduce IEEE 802.1AE driver
From: Johannes Berg @ 2016-03-15 14:03 UTC (permalink / raw)
To: Sabrina Dubroca, netdev
Cc: Hannes Frederic Sowa, Florian Westphal, Paolo Abeni, stephen
In-Reply-To: <3d7ef45fa74b3bde47dabee3f23c8b8d04b546aa.1457714618.git.sd@queasysnail.net>
Hi,
> +struct macsec_rx_sa_stats {
> + __u32 InPktsOK;
> + __u32 InPktsInvalid;
> + __u32 InPktsNotValid;
> + __u32 InPktsNotUsingSA;
> + __u32 InPktsUnusedSA;
> +};
> +
> +struct macsec_tx_sa_stats {
> + __u32 OutPktsProtected;
> + __u32 OutPktsEncrypted;
> +};
Just noticed this: is there a particular reason for using only __u32
here? The others all seem to use __u64.
> +static int macsec_dump_txsc(struct sk_buff *skb, struct
> netlink_callback *cb)
> +{
> + struct net *net = sock_net(skb->sk);
> + struct net_device *dev;
> + int dev_idx, d;
> +
> + dev_idx = cb->args[0];
> +
> + d = 0;
> + for_each_netdev(net, dev) {
> + struct macsec_secy *secy;
> +
> + if (d < dev_idx)
> + goto next;
> +
> + if (!netif_is_macsec(dev))
> + goto next;
> +
> + secy = &macsec_priv(dev)->secy;
> + if (dump_secy(secy, dev, skb, cb) < 0)
> + goto done;
> +next:
> + d++;
> + }
> +
> +done:
> + cb->args[0] = d;
> + return skb->len;
> +}
Maybe you should consider adding genl_dump_check_consistent() support
here, so userspace can figure out if the dump was really consistent, if
necessary.
To do this, you have to keep a global generation counter that changes
whenever this list changes (adding/removing macsec interfaces, I think)
and then set
cb->seq = macsec_generation_counter;
at the beginning of this function, and call
genl_dump_check_consistent() for each message in the loop.
Btw, aren't you missing locking here for for_each_netdev()?
johannes
^ permalink raw reply
* RE: [PATCH] af_unix: closed SOCK_SEQPACKET socketpair must get SIGPIPE
From: David Laight @ 2016-03-15 13:46 UTC (permalink / raw)
To: 'Alexander Potapenko', edumazet@google.com,
rweikusat@mobileactivedefense.com, davem@davemloft.net
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
In-Reply-To: <1458032624-139688-1-git-send-email-glider@google.com>
From: Alexander Potapenko
> Sent: 15 March 2016 09:04
> According to IEEE Std 1003.1, 2013, sending data to a SOCK_SEQPACKET
> socketpair with MSG_NOSIGNAL flag set must result in a SIGPIPE if the
> socket is no longer connected.
...
> Without the below patch the behavior is as follows:
>
> $ ./sock seqpacket
> sendmsg: Broken pipe
...
> The behavior of the patched kernel complies with POSIX:
>
> $ ./sock seqpacket
> Killed by SIGPIPE
...
While POSIX might specify this behaviour, changing the behaviour
could easily break applications.
Basically this change (more or less) require every application that
uses SOCK_SEQPACKED to be audited to ensure that MSG_NOSIGNAL is set
on ever send/write to the socket.
Personally I think the whole SIGPIPE on sockets should never have been
allowed to get into the standard.
I don't remember MSG_NOSIGNAL being present in SYSV.
The only time you want a write into a pipe to generate SIGPIPE is
for pipes generates by the shell that feed stdout to stdin of the
next process in the pipeline.
If pipes are implemented as unix-domain socketpairs (no one does that
any more) then it would require the SIGPIPE for write().
David
^ permalink raw reply
* Re: [PATCH] af_unix: closed SOCK_SEQPACKET socketpair must get SIGPIPE
From: Eric Dumazet @ 2016-03-15 13:20 UTC (permalink / raw)
To: Alexander Potapenko; +Cc: edumazet, rweikusat, davem, linux-kernel, netdev
In-Reply-To: <1458032624-139688-1-git-send-email-glider@google.com>
On Tue, 2016-03-15 at 10:03 +0100, Alexander Potapenko wrote:
> According to IEEE Std 1003.1, 2013, sending data to a SOCK_SEQPACKET
> socketpair with MSG_NOSIGNAL flag set must result in a SIGPIPE if the
> socket is no longer connected.
I find this sentence slightly confusing ?
If MSG_NOSIGNAL is set, then SIGPIPE should not be generated.
s/with/without/ maybe ?
^ permalink raw reply
* Re: [PATCH v3] can: rcar_canfd: Add Renesas R-Car CAN FD driver
From: Marc Kleine-Budde @ 2016-03-15 12:51 UTC (permalink / raw)
To: Ramesh Shanmugasundaram, wg, robh+dt, pawel.moll, mark.rutland,
ijc+devicetree, galak, corbet
Cc: linux-renesas-soc, devicetree, linux-can, netdev, linux-doc,
geert+renesas, chris.paterson2
In-Reply-To: <1458035294-8150-1-git-send-email-ramesh.shanmugasundaram@bp.renesas.com>
[-- Attachment #1.1: Type: text/plain, Size: 2875 bytes --]
On 03/15/2016 10:48 AM, Ramesh Shanmugasundaram wrote:
> This patch adds support for the CAN FD controller found in Renesas R-Car
> SoCs. The controller operates in CAN FD only mode by default.
>
> CAN FD mode supports both Classical CAN & CAN FD frame formats. The
> controller supports ISO 11898-1:2015 CAN FD format only.
>
> This controller supports two channels and the driver can enable either
> or both of the channels.
>
> Driver uses Rx FIFOs (one per channel) for reception & Common FIFOs (one
> per channel) for transmission. Rx filter rules are configured to the
> minimum (one per channel) and it accepts Standard, Extended, Data &
> Remote Frame combinations.
>
> Note: There are few documentation errors in R-Car Gen3 Hardware User
> Manual v0.5E with respect to CAN FD controller. They are listed below:
>
> 1. CAN FD interrupt numbers 29 & 30 are listed as per channel
> interrupts. However, they are common to both channels (i.e.) they are
> global and channel interrupts respectively.
>
> 2. CANFD clock is derived from PLL1. This is not documented.
>
> 3. CANFD clock is further divided by (1/2) within the CAN FD controller.
> This is not documented.
>
> 4. The minimum value of NTSEG1 in RSCFDnCFDCmNCFG register is 2 Tq. It
> is specified 4 Tq in the manual.
>
> 5. The maximum number of message RAM area the controller can use is 3584
> bytes. It is specified 10752 bytes in the manual.
>
> Signed-off-by: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
> ---
> Hi All,
>
> Thanks for the review comments.
>
> This updated patch is based on linux-can-next tag (linux-can-next-for-4.6-20160310).
>
> This patch depends on
>
> [RFC] [PATCH v3] can: fix handling of unmodifiable configuration options
> (http://comments.gmane.org/gmane.linux.can/9126)
>
> Changes since v2:
> * Rebased to latest tag (linux-can-next-for-4.6-20160310)
> * Cleaned up leftover debugfs code (Thanks Oliver H)
> * Revised devicetree documentation text (as suggested by Rob H)
> (https://www.mail-archive.com/linux-renesas-soc@vger.kernel.org/msg01597.html)
> * Used new can subsystem api to set static configuration & removed check in rcar_canfd_start (as suggested by Oliver H)
> (Refer: http://comments.gmane.org/gmane.linux.can/9126 &
> https://www.mail-archive.com/linux-renesas-soc@vger.kernel.org/msg01867.html)
> * Clubbed Renesas controller drivers to driver/net/can/rcar dir (as suggested by Oliver H)
Please make moving of the existing drivers a separate patch.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
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