* Re: [PATCH net] bpf: disallow arithmetic operations on context pointer
From: Jakub Kicinski @ 2017-10-16 16:30 UTC (permalink / raw)
To: Edward Cree; +Cc: netdev, oss-drivers, alexei.starovoitov, daniel
In-Reply-To: <44a8fb95-298b-8715-ce4e-60df60c86343@solarflare.com>
On Mon, 16 Oct 2017 17:16:24 +0100, Edward Cree wrote:
> On 16/10/17 16:45, Jakub Kicinski wrote:
> > Commit f1174f77b50c ("bpf/verifier: rework value tracking")
> > removed the crafty selection of which pointer types are
> > allowed to be modified. This is OK for most pointer types
> > since adjust_ptr_min_max_vals() will catch operations on
> > immutable pointers. One exception is PTR_TO_CTX which is
> > now allowed to be offseted freely.
> >
> > The intent of aforementioned commit was to allow context
> > access via modified registers. The offset passed to
> > ->is_valid_access() verifier callback has been adjusted
> > by the value of the variable offset.
> >
> > What is missing, however, is taking the variable offset
> > into account when the context register is used. Or in terms
> > of the code adding the offset to the value passed to the
> > ->convert_ctx_access() callback. This leads to the following
> Good catch.
> So the problem is just that convert_ctx_access() can't deal
> with it, yes? Assuming that the offset is constant, because
> otherwise we'd reject it anyway, we _could_ stash that offset
> in insn_aux_data, and reject any paths that tried to change it
> subsequently; and then convert_ctx_access() could be given the
> total (off + reg->off) and then the reg->off could be subtracted
> from the result, giving the right 'converted' insn offset.
> That would then mean that your example,
> > eBPF user code:
> >
> > r1 += 68
> > r0 = *(u32 *)(r1 + 8)
> > exit
> >
> > being translated to this in kernel space:
> >
> > 0: (07) r1 += 68
> > 1: (61) r0 = *(u32 *)(r1 +180)
> > 2: (95) exit
> would instead convert offset 76 to something else, let's say
> 200 just for the sake of argument, and produce
> 1: (61) r0 = *(u32 *)(r1 + 132)
> which would then do the right thing at run time.
>
> However, I don't know whether anyone would actually want this
> to be supported for their programs, and so I'm happy to
> disallow this for net and then maybe we can follow up in
> net-next with the change I describe above if it's useful.
That was my thinking too. We would have to stash the offset and make
sure that it doesn't change on different paths, but it's probably not
suitable for -net, and nobody uses that today (although Alexei
mentioned there may be valid use cases, especially in tracing).
> > Offset 8 is corresponding to 180 in the kernel, but offset
> > 76 is valid too. Verifier will "accept" access to offset
> > 68+8=76 but then "convert" access to offset 8 as 180.
> > Effective access to offset 248 is beyond the kernel context.
> > (This is a __sk_buff example on a debug-heavy kernel -
> > packet mark is 8 -> 180, 76 would be data.)
> >
> > Dereferencing the modified context pointer is not as easy
> > as dereferencing other types, because we have to translate
> > the access to reading a field in kernel structures which is
> > usually at a different offset and often of a different size.
> > To allow modifying the pointer we would have to make sure
> > that given eBPF instruction will always access the same
> > field or the fields accessed are "compatible" in terms of
> > offset and size...
> >
> > Disallow dereferencing modified context pointers and add
> > to selftests the test case described here.
> >
> > Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
> > Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> > ---
> > Dave, a merge note - in net-next this will need env to be passed
> > to verbose().
> >
> > kernel/bpf/verifier.c | 8 ++++++--
> > tools/testing/selftests/bpf/test_verifier.c | 14 ++++++++++++++
> > 2 files changed, 20 insertions(+), 2 deletions(-)
> >
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 8b8d6ba39e23..8499759d0c7a 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -1116,7 +1116,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
> > /* ctx accesses must be at a fixed offset, so that we can
> > * determine what type of data were returned.
> > */
> > - if (!tnum_is_const(reg->var_off)) {
> > + if (reg->off) {
> > + verbose("derefence of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
> This is slightly unclear, it's not that two adds is bad (e.g. r1 += 8;
> r0 = *(u32 *)r1 is bad too), it's that the offset must be in the load,
> not the register; your message might be accurate for some compilers but
> not in full generality (especially for assemblers without compiling).
I'm happy to hear better suggestions :) I've spent quite a bit of time
scratching my head thinking how to phrase this best. The first
part of the message is general enough IMHO, the second is targeted
mostly at C developers.
> Also, sp. "dereference".
Argh. aspell doesn't know that word, added to local dict now.
^ permalink raw reply
* [PATCH v2 net-next 0/5] mlxsw: spectrum_router: Add extack messages for RIF and VRF overflow
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
Currently, exceeding the number of VRF instances or the number of router
interfaces either fails with a non-intuitive EBUSY:
$ ip li set swp1s1.6 vrf vrf-1s1-6 up
RTNETLINK answers: Device or resource busy
or fails silently (IPv6) since the checks are done in a work queue. This
set adds support for the address validator notifier to spectrum which
allows ext-ack based messages to be returned on failure.
To make that happen the IPv6 version needs to be converted from atomic
to blocking (patch 2), and then support for extack needs to be added
to the notifier (patch 3). Patch 1 reworks the locking in ipv6_add_addr
to work better in the atomic and non-atomic code paths. Patches 4 and 5
add the validator notifier to spectrum and then plumb the extack argument
through spectrum_router.
With this set, VRF overflows fail with:
$ ip li set swp1s1.6 vrf vrf-1s1-6 up
Error: spectrum: Exceeded number of supported VRF.
and RIF overflows fail with:
$ ip addr add dev swp1s2.191 10.12.191.1/24
Error: spectrum: Exceeded number of supported router interfaces.
v1 -> v2
- fix error path in ipv6_add_addr: reset rt to NULL (Ido comment) and
add in6_dev_put on ifa once the hold has been done
RFC -> v1
- addressed various comments from Ido
- refactored ipv6_add_addr to allow ifa's to be allocated with
GFP_KERNEL as requested by DaveM
David Ahern (5):
ipv6: addrconf: cleanup locking in ipv6_add_addr
net: ipv6: Make inet6addr_validator a blocking notifier
net: Add extack to validator_info structs used for address notifier
mlxsw: spectrum: router: Add support for address validator notifier
mlxsw: spectrum_router: Add extack message for RIF and VRF overflow
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 15 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 +
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 162 +++++++++++++++------
drivers/net/ipvlan/ipvlan_main.c | 14 +-
include/linux/inetdevice.h | 1 +
include/net/addrconf.h | 1 +
net/ipv4/devinet.c | 8 +-
net/ipv6/addrconf.c | 129 +++++++++-------
net/ipv6/addrconf_core.c | 9 +-
9 files changed, 234 insertions(+), 109 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH v2 net-next 1/5] ipv6: addrconf: cleanup locking in ipv6_add_addr
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
In-Reply-To: <1508171814-16713-1-git-send-email-dsahern@gmail.com>
ipv6_add_addr is called in process context with rtnl lock held
(e.g., manual config of an address) or during softirq processing
(e.g., autoconf and address from a router advertisement).
Currently, ipv6_add_addr calls rcu_read_lock_bh shortly after entry
and does not call unlock until exit, minus the call around the address
validator notifier. Similarly, addrconf_hash_lock is taken after the
validator notifier and held until exit. This forces the allocation of
inet6_ifaddr to always be atomic.
Refactor ipv6_add_addr as follows:
1. add an input boolean to discriminate the call path (process context
or softirq). This new flag controls whether the alloc can be done
with GFP_KERNEL or GFP_ATOMIC.
2. Move the rcu_read_lock_bh and unlock calls only around functions that
do rcu updates.
3. Remove the in6_dev_hold and put added by 3ad7d2468f79f ("Ipvlan should
return an error when an address is already in use."). This was done
presumably because rcu_read_unlock_bh needs to be called before calling
the validator. Since rcu_read_lock is not needed before the validator
runs revert the hold and put added by 3ad7d2468f79f and only do the
hold when setting ifp->idev.
4. move duplicate address check and insertion of new address in the global
address hash into a helper. The helper is called after an ifa is
allocated and filled in.
This allows the ifa for manually configured addresses to be done with
GFP_KERNEL and reduces the overall amount of time with rcu_read_lock held
and hash table spinlock held.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv6/addrconf.c | 104 ++++++++++++++++++++++++++++++----------------------
1 file changed, 60 insertions(+), 44 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4603aa488f4f..a8d202b1b919 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -957,18 +957,43 @@ static u32 inet6_addr_hash(const struct in6_addr *addr)
return hash_32(ipv6_addr_hash(addr), IN6_ADDR_HSIZE_SHIFT);
}
+static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa)
+{
+ unsigned int hash;
+ int err = 0;
+
+ spin_lock(&addrconf_hash_lock);
+
+ /* Ignore adding duplicate addresses on an interface */
+ if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev)) {
+ ADBG("ipv6_add_addr: already assigned\n");
+ err = -EEXIST;
+ goto out;
+ }
+
+ /* Add to big hash table */
+ hash = inet6_addr_hash(&ifa->addr);
+ hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]);
+
+out:
+ spin_unlock(&addrconf_hash_lock);
+
+ return err;
+}
+
/* On success it returns ifp with increased reference count */
static struct inet6_ifaddr *
ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
const struct in6_addr *peer_addr, int pfxlen,
- int scope, u32 flags, u32 valid_lft, u32 prefered_lft)
+ int scope, u32 flags, u32 valid_lft, u32 prefered_lft,
+ bool can_block)
{
+ gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
struct net *net = dev_net(idev->dev);
struct inet6_ifaddr *ifa = NULL;
- struct rt6_info *rt;
+ struct rt6_info *rt = NULL;
struct in6_validator_info i6vi;
- unsigned int hash;
int err = 0;
int addr_type = ipv6_addr_type(addr);
@@ -978,42 +1003,24 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
addr_type & IPV6_ADDR_LOOPBACK))
return ERR_PTR(-EADDRNOTAVAIL);
- rcu_read_lock_bh();
-
- in6_dev_hold(idev);
-
if (idev->dead) {
err = -ENODEV; /*XXX*/
- goto out2;
+ goto out;
}
if (idev->cnf.disable_ipv6) {
err = -EACCES;
- goto out2;
+ goto out;
}
i6vi.i6vi_addr = *addr;
i6vi.i6vi_dev = idev;
- rcu_read_unlock_bh();
-
err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
-
- rcu_read_lock_bh();
err = notifier_to_errno(err);
- if (err)
- goto out2;
-
- spin_lock(&addrconf_hash_lock);
-
- /* Ignore adding duplicate addresses on an interface */
- if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) {
- ADBG("ipv6_add_addr: already assigned\n");
- err = -EEXIST;
+ if (err < 0)
goto out;
- }
-
- ifa = kzalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
+ ifa = kzalloc(sizeof(*ifa), gfp_flags);
if (!ifa) {
ADBG("ipv6_add_addr: malloc failed\n");
err = -ENOBUFS;
@@ -1023,6 +1030,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
rt = addrconf_dst_alloc(idev, addr, false);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
+ rt = NULL;
goto out;
}
@@ -1053,16 +1061,21 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
ifa->rt = rt;
ifa->idev = idev;
+ in6_dev_hold(idev);
+
/* For caller */
refcount_set(&ifa->refcnt, 1);
- /* Add to big hash table */
- hash = inet6_addr_hash(addr);
+ rcu_read_lock_bh();
- hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]);
- spin_unlock(&addrconf_hash_lock);
+ err = ipv6_add_addr_hash(idev->dev, ifa);
+ if (err < 0) {
+ rcu_read_unlock_bh();
+ goto out;
+ }
write_lock(&idev->lock);
+
/* Add to inet6_dev unicast addr list. */
ipv6_link_dev_addr(idev, ifa);
@@ -1073,21 +1086,23 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
in6_ifa_hold(ifa);
write_unlock(&idev->lock);
-out2:
+
rcu_read_unlock_bh();
- if (likely(err == 0))
- inet6addr_notifier_call_chain(NETDEV_UP, ifa);
- else {
- kfree(ifa);
- in6_dev_put(idev);
+ inet6addr_notifier_call_chain(NETDEV_UP, ifa);
+out:
+ if (unlikely(err < 0)) {
+ if (rt)
+ ip6_rt_put(rt);
+ if (ifa) {
+ if (ifa->idev)
+ in6_dev_put(ifa->idev);
+ kfree(ifa);
+ }
ifa = ERR_PTR(err);
}
return ifa;
-out:
- spin_unlock(&addrconf_hash_lock);
- goto out2;
}
enum cleanup_prefix_rt_t {
@@ -1334,7 +1349,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
ipv6_addr_scope(&addr), addr_flags,
- tmp_valid_lft, tmp_prefered_lft);
+ tmp_valid_lft, tmp_prefered_lft, true);
if (IS_ERR(ift)) {
in6_ifa_put(ifp);
in6_dev_put(idev);
@@ -2018,7 +2033,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen,
scope, flags, valid_lft,
- preferred_lft);
+ preferred_lft, false);
if (IS_ERR(ifp2))
goto lock_errdad;
@@ -2476,7 +2491,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
pinfo->prefix_len,
addr_type&IPV6_ADDR_SCOPE_MASK,
addr_flags, valid_lft,
- prefered_lft);
+ prefered_lft, false);
if (IS_ERR_OR_NULL(ifp))
return -1;
@@ -2845,7 +2860,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
}
ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
- valid_lft, prefered_lft);
+ valid_lft, prefered_lft, true);
if (!IS_ERR(ifp)) {
if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
@@ -2960,7 +2975,8 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
ifp = ipv6_add_addr(idev, addr, NULL, plen,
scope, IFA_F_PERMANENT,
- INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME,
+ true);
if (!IS_ERR(ifp)) {
spin_lock_bh(&ifp->lock);
ifp->flags &= ~IFA_F_TENTATIVE;
@@ -3060,7 +3076,7 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
#endif
ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
- INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true);
if (!IS_ERR(ifp)) {
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
addrconf_dad_start(ifp);
--
2.1.4
^ permalink raw reply related
* [PATCH v2 net-next 2/5] net: ipv6: Make inet6addr_validator a blocking notifier
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
In-Reply-To: <1508171814-16713-1-git-send-email-dsahern@gmail.com>
inet6addr_validator chain was added by commit 3ad7d2468f79f ("Ipvlan
should return an error when an address is already in use") to allow
address validation before changes are committed and to be able to
fail the address change with an error back to the user. The address
validation is not done for addresses received from router
advertisements.
Handling RAs in softirq context is the only reason for the notifier
chain to be atomic versus blocking. Since the only current user, ipvlan,
of the validator chain ignores softirq context, the notifier can be made
blocking and simply not invoked for softirq path.
The blocking option is needed by spectrum for example to validate
resources for an adding an address to an interface.
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
---
drivers/net/ipvlan/ipvlan_main.c | 4 ----
net/ipv6/addrconf.c | 21 ++++++++++++++-------
net/ipv6/addrconf_core.c | 9 +++++----
3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 3cf67db513e2..6842739b6679 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -808,10 +808,6 @@ static int ipvlan_addr6_event(struct notifier_block *unused,
struct net_device *dev = (struct net_device *)if6->idev->dev;
struct ipvl_dev *ipvlan = netdev_priv(dev);
- /* FIXME IPv6 autoconf calls us from bh without RTNL */
- if (in_softirq())
- return NOTIFY_DONE;
-
if (!netif_is_ipvlan(dev))
return NOTIFY_DONE;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a8d202b1b919..dd9c0c435f71 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -993,7 +993,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
struct net *net = dev_net(idev->dev);
struct inet6_ifaddr *ifa = NULL;
struct rt6_info *rt = NULL;
- struct in6_validator_info i6vi;
int err = 0;
int addr_type = ipv6_addr_type(addr);
@@ -1013,12 +1012,20 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
goto out;
}
- i6vi.i6vi_addr = *addr;
- i6vi.i6vi_dev = idev;
- err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
- err = notifier_to_errno(err);
- if (err < 0)
- goto out;
+ /* validator notifier needs to be blocking;
+ * do not call in atomic context
+ */
+ if (can_block) {
+ struct in6_validator_info i6vi = {
+ .i6vi_addr = *addr,
+ .i6vi_dev = idev,
+ };
+
+ err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
+ err = notifier_to_errno(err);
+ if (err < 0)
+ goto out;
+ }
ifa = kzalloc(sizeof(*ifa), gfp_flags);
if (!ifa) {
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index 9e3488d50b15..32b564dfd02a 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -88,7 +88,7 @@ int __ipv6_addr_type(const struct in6_addr *addr)
EXPORT_SYMBOL(__ipv6_addr_type);
static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
-static ATOMIC_NOTIFIER_HEAD(inet6addr_validator_chain);
+static BLOCKING_NOTIFIER_HEAD(inet6addr_validator_chain);
int register_inet6addr_notifier(struct notifier_block *nb)
{
@@ -110,19 +110,20 @@ EXPORT_SYMBOL(inet6addr_notifier_call_chain);
int register_inet6addr_validator_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_register(&inet6addr_validator_chain, nb);
+ return blocking_notifier_chain_register(&inet6addr_validator_chain, nb);
}
EXPORT_SYMBOL(register_inet6addr_validator_notifier);
int unregister_inet6addr_validator_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_unregister(&inet6addr_validator_chain, nb);
+ return blocking_notifier_chain_unregister(&inet6addr_validator_chain,
+ nb);
}
EXPORT_SYMBOL(unregister_inet6addr_validator_notifier);
int inet6addr_validator_notifier_call_chain(unsigned long val, void *v)
{
- return atomic_notifier_call_chain(&inet6addr_validator_chain, val, v);
+ return blocking_notifier_call_chain(&inet6addr_validator_chain, val, v);
}
EXPORT_SYMBOL(inet6addr_validator_notifier_call_chain);
--
2.1.4
^ permalink raw reply related
* [PATCH v2 net-next 3/5] net: Add extack to validator_info structs used for address notifier
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
In-Reply-To: <1508171814-16713-1-git-send-email-dsahern@gmail.com>
Add extack to in_validator_info and in6_validator_info. Update the one
user of each, ipvlan, to return an error message for failures.
Only manual configuration of an address is plumbed in the IPv6 code path.
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
---
drivers/net/ipvlan/ipvlan_main.c | 10 ++++++++--
include/linux/inetdevice.h | 1 +
include/net/addrconf.h | 1 +
net/ipv4/devinet.c | 8 +++++---
net/ipv6/addrconf.c | 22 ++++++++++++----------
5 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 6842739b6679..f0ab55df57f1 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -847,8 +847,11 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused,
switch (event) {
case NETDEV_UP:
- if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true))
+ if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) {
+ NL_SET_ERR_MSG(i6vi->extack,
+ "Address already assigned to an ipvlan device");
return notifier_from_errno(-EADDRINUSE);
+ }
break;
}
@@ -917,8 +920,11 @@ static int ipvlan_addr4_validator_event(struct notifier_block *unused,
switch (event) {
case NETDEV_UP:
- if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false))
+ if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) {
+ NL_SET_ERR_MSG(ivi->extack,
+ "Address already assigned to an ipvlan device");
return notifier_from_errno(-EADDRINUSE);
+ }
break;
}
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 751d051f0bc7..681dff30940b 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -154,6 +154,7 @@ struct in_ifaddr {
struct in_validator_info {
__be32 ivi_addr;
struct in_device *ivi_dev;
+ struct netlink_ext_ack *extack;
};
int register_inetaddr_notifier(struct notifier_block *nb);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 87981cd63180..b8b16437c6d5 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -55,6 +55,7 @@ struct prefix_info {
struct in6_validator_info {
struct in6_addr i6vi_addr;
struct inet6_dev *i6vi_dev;
+ struct netlink_ext_ack *extack;
};
#define IN6_ADDR_HSIZE_SHIFT 4
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7ce22a2c07ce..93773e5a80c7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -444,7 +444,7 @@ static void check_lifetime(struct work_struct *work);
static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime);
static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
- u32 portid)
+ u32 portid, struct netlink_ext_ack *extack)
{
struct in_device *in_dev = ifa->ifa_dev;
struct in_ifaddr *ifa1, **ifap, **last_primary;
@@ -489,6 +489,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
*/
ivi.ivi_addr = ifa->ifa_address;
ivi.ivi_dev = ifa->ifa_dev;
+ ivi.extack = extack;
ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
NETDEV_UP, &ivi);
ret = notifier_to_errno(ret);
@@ -521,7 +522,7 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
static int inet_insert_ifa(struct in_ifaddr *ifa)
{
- return __inet_insert_ifa(ifa, NULL, 0);
+ return __inet_insert_ifa(ifa, NULL, 0, NULL);
}
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
@@ -902,7 +903,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
return ret;
}
}
- return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid);
+ return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid,
+ extack);
} else {
inet_free_ifa(ifa);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index dd9c0c435f71..93f9c0a61911 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -987,7 +987,7 @@ static struct inet6_ifaddr *
ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
const struct in6_addr *peer_addr, int pfxlen,
int scope, u32 flags, u32 valid_lft, u32 prefered_lft,
- bool can_block)
+ bool can_block, struct netlink_ext_ack *extack)
{
gfp_t gfp_flags = can_block ? GFP_KERNEL : GFP_ATOMIC;
struct net *net = dev_net(idev->dev);
@@ -1019,6 +1019,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
struct in6_validator_info i6vi = {
.i6vi_addr = *addr,
.i6vi_dev = idev,
+ .extack = extack,
};
err = inet6addr_validator_notifier_call_chain(NETDEV_UP, &i6vi);
@@ -1356,7 +1357,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift = ipv6_add_addr(idev, &addr, NULL, tmp_plen,
ipv6_addr_scope(&addr), addr_flags,
- tmp_valid_lft, tmp_prefered_lft, true);
+ tmp_valid_lft, tmp_prefered_lft, true, NULL);
if (IS_ERR(ift)) {
in6_ifa_put(ifp);
in6_dev_put(idev);
@@ -2040,7 +2041,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
ifp2 = ipv6_add_addr(idev, &new_addr, NULL, pfxlen,
scope, flags, valid_lft,
- preferred_lft, false);
+ preferred_lft, false, NULL);
if (IS_ERR(ifp2))
goto lock_errdad;
@@ -2498,7 +2499,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
pinfo->prefix_len,
addr_type&IPV6_ADDR_SCOPE_MASK,
addr_flags, valid_lft,
- prefered_lft, false);
+ prefered_lft, false, NULL);
if (IS_ERR_OR_NULL(ifp))
return -1;
@@ -2808,7 +2809,8 @@ static int inet6_addr_add(struct net *net, int ifindex,
const struct in6_addr *pfx,
const struct in6_addr *peer_pfx,
unsigned int plen, __u32 ifa_flags,
- __u32 prefered_lft, __u32 valid_lft)
+ __u32 prefered_lft, __u32 valid_lft,
+ struct netlink_ext_ack *extack)
{
struct inet6_ifaddr *ifp;
struct inet6_dev *idev;
@@ -2867,7 +2869,7 @@ static int inet6_addr_add(struct net *net, int ifindex,
}
ifp = ipv6_add_addr(idev, pfx, peer_pfx, plen, scope, ifa_flags,
- valid_lft, prefered_lft, true);
+ valid_lft, prefered_lft, true, extack);
if (!IS_ERR(ifp)) {
if (!(ifa_flags & IFA_F_NOPREFIXROUTE)) {
@@ -2952,7 +2954,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
rtnl_lock();
err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
ireq.ifr6_prefixlen, IFA_F_PERMANENT,
- INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, NULL);
rtnl_unlock();
return err;
}
@@ -2983,7 +2985,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
ifp = ipv6_add_addr(idev, addr, NULL, plen,
scope, IFA_F_PERMANENT,
INFINITY_LIFE_TIME, INFINITY_LIFE_TIME,
- true);
+ true, NULL);
if (!IS_ERR(ifp)) {
spin_lock_bh(&ifp->lock);
ifp->flags &= ~IFA_F_TENTATIVE;
@@ -3083,7 +3085,7 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
#endif
ifp = ipv6_add_addr(idev, addr, NULL, 64, IFA_LINK, addr_flags,
- INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true);
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME, true, NULL);
if (!IS_ERR(ifp)) {
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
addrconf_dad_start(ifp);
@@ -4586,7 +4588,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
*/
return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
ifm->ifa_prefixlen, ifa_flags,
- preferred_lft, valid_lft);
+ preferred_lft, valid_lft, extack);
}
if (nlh->nlmsg_flags & NLM_F_EXCL ||
--
2.1.4
^ permalink raw reply related
* [PATCH v2 net-next 4/5] mlxsw: spectrum: router: Add support for address validator notifier
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
In-Reply-To: <1508171814-16713-1-git-send-email-dsahern@gmail.com>
Add support for inetaddr_validator and inet6addr_validator. The
notifiers provide a means for validating ipv4 and ipv6 addresses
before the addresses are installed and on failure the error
is propagated back to the user.
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 15 ++++++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 ++
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 52 ++++++++++++++++++++++
3 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 321988ac57cc..d51402f98f97 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4505,9 +4505,16 @@ static struct notifier_block mlxsw_sp_netdevice_nb __read_mostly = {
.notifier_call = mlxsw_sp_netdevice_event,
};
+static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = {
+ .notifier_call = mlxsw_sp_inetaddr_valid_event,
+};
+
static struct notifier_block mlxsw_sp_inetaddr_nb __read_mostly = {
.notifier_call = mlxsw_sp_inetaddr_event,
- .priority = 10, /* Must be called before FIB notifier block */
+};
+
+static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = {
+ .notifier_call = mlxsw_sp_inet6addr_valid_event,
};
static struct notifier_block mlxsw_sp_inet6addr_nb __read_mostly = {
@@ -4533,7 +4540,9 @@ static int __init mlxsw_sp_module_init(void)
int err;
register_netdevice_notifier(&mlxsw_sp_netdevice_nb);
+ register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
register_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
+ register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
register_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
register_netevent_notifier(&mlxsw_sp_router_netevent_nb);
@@ -4552,7 +4561,9 @@ static int __init mlxsw_sp_module_init(void)
err_core_driver_register:
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
+ unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
+ unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
return err;
}
@@ -4563,7 +4574,9 @@ static void __exit mlxsw_sp_module_exit(void)
mlxsw_core_driver_unregister(&mlxsw_sp_driver);
unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
unregister_inet6addr_notifier(&mlxsw_sp_inet6addr_nb);
+ unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb);
unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
+ unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb);
unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 8e45183dc9bb..4865a6f58c83 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -390,8 +390,12 @@ int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
int mlxsw_sp_netdevice_router_port_event(struct net_device *dev);
int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
unsigned long event, void *ptr);
+int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr);
int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
unsigned long event, void *ptr);
+int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr);
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
struct netdev_notifier_changeupper_info *info);
void
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 6a356f4b99a3..2a7f066dfab5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -5656,6 +5656,32 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
struct mlxsw_sp_rif *rif;
int err = 0;
+ /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
+ if (event == NETDEV_UP)
+ goto out;
+
+ mlxsw_sp = mlxsw_sp_lower_get(dev);
+ if (!mlxsw_sp)
+ goto out;
+
+ rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
+ if (!mlxsw_sp_rif_should_config(rif, dev, event))
+ goto out;
+
+ err = __mlxsw_sp_inetaddr_event(dev, event);
+out:
+ return notifier_from_errno(err);
+}
+
+int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct in_validator_info *ivi = (struct in_validator_info *) ptr;
+ struct net_device *dev = ivi->ivi_dev->dev;
+ struct mlxsw_sp *mlxsw_sp;
+ struct mlxsw_sp_rif *rif;
+ int err = 0;
+
mlxsw_sp = mlxsw_sp_lower_get(dev);
if (!mlxsw_sp)
goto out;
@@ -5708,6 +5734,10 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
struct net_device *dev = if6->idev->dev;
+ /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
+ if (event == NETDEV_UP)
+ return NOTIFY_DONE;
+
if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
return NOTIFY_DONE;
@@ -5724,6 +5754,28 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
return NOTIFY_DONE;
}
+int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
+ struct net_device *dev = i6vi->i6vi_dev->dev;
+ struct mlxsw_sp *mlxsw_sp;
+ struct mlxsw_sp_rif *rif;
+ int err = 0;
+
+ mlxsw_sp = mlxsw_sp_lower_get(dev);
+ if (!mlxsw_sp)
+ goto out;
+
+ rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
+ if (!mlxsw_sp_rif_should_config(rif, dev, event))
+ goto out;
+
+ err = __mlxsw_sp_inetaddr_event(dev, event);
+out:
+ return notifier_from_errno(err);
+}
+
static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
const char *mac, int mtu)
{
--
2.1.4
^ permalink raw reply related
* Re: [PATCH] can: check for null sk before deferencing it via the call to sock_net
From: Josh Boyer @ 2017-10-16 16:37 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: Colin King, Marc Kleine-Budde, David S . Miller, linux-can,
netdev, kernel-janitors, Linux-Kernel@Vger. Kernel. Org
In-Reply-To: <f5ce1047-eb37-151a-c7b7-9b47b70789f7@hartkopp.net>
On Fri, Sep 8, 2017 at 1:46 PM, Oliver Hartkopp <socketcan@hartkopp.net> wrote:
>
>
> On 09/08/2017 05:02 PM, Colin King wrote:
>>
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> The assignment of net via call sock_net will dereference sk. This
>> is performed before a sanity null check on sk, so there could be
>> a potential null dereference on the sock_net call if sk is null.
>> Fix this by assigning net after the sk null check. Also replace
>> the sk == NULL with the more usual !sk idiom.
>>
>> Detected by CoverityScan CID#1431862 ("Dereference before null check")
>>
>> Fixes: 384317ef4187 ("can: network namespace support for CAN_BCM
>> protocol")
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>
>
> Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
I don't see this one queued up in the net or net-next trees. Did it
fall through the cracks or did it get queued up elsewhere? Seems like
it's a good candidate to get into 4.14?
josh
>
>
> Thanks Collin!
>
>
>> ---
>> net/can/bcm.c | 5 +++--
>> 1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/can/bcm.c b/net/can/bcm.c
>> index 47a8748d953a..a3791674b8ce 100644
>> --- a/net/can/bcm.c
>> +++ b/net/can/bcm.c
>> @@ -1493,13 +1493,14 @@ static int bcm_init(struct sock *sk)
>> static int bcm_release(struct socket *sock)
>> {
>> struct sock *sk = sock->sk;
>> - struct net *net = sock_net(sk);
>> + struct net *net;
>> struct bcm_sock *bo;
>> struct bcm_op *op, *next;
>> - if (sk == NULL)
>> + if (!sk)
>> return 0;
>> + net = sock_net(sk);
>> bo = bcm_sk(sk);
>> /* remove bcm_ops, timer, rx_unregister(), etc. */
>>
>
^ permalink raw reply
* [PATCH v2 net-next 5/5] mlxsw: spectrum_router: Add extack message for RIF and VRF overflow
From: David Ahern @ 2017-10-16 16:36 UTC (permalink / raw)
To: netdev; +Cc: jiri, idosch, kjlx, davem, yoshfuji, David Ahern
In-Reply-To: <1508171814-16713-1-git-send-email-dsahern@gmail.com>
Add extack argument down to mlxsw_sp_rif_create and mlxsw_sp_vr_create
to set an error message on RIF or VR overflow. Now on overflow of
either resource the user gets an informative message as opposed to
failing with EBUSY.
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 114 +++++++++++++--------
1 file changed, 69 insertions(+), 45 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 2a7f066dfab5..9e0b46513ca7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -731,14 +731,17 @@ static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
}
static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
- u32 tb_id)
+ u32 tb_id,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_vr *vr;
int err;
vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
- if (!vr)
+ if (!vr) {
+ NL_SET_ERR_MSG(extack, "spectrum: Exceeded number of supported virtual routers");
return ERR_PTR(-EBUSY);
+ }
vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4);
if (IS_ERR(vr->fib4))
return ERR_CAST(vr->fib4);
@@ -775,14 +778,15 @@ static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr *vr)
vr->fib4 = NULL;
}
-static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id)
+static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_vr *vr;
tb_id = mlxsw_sp_fix_tb_id(tb_id);
vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
if (!vr)
- vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id);
+ vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id, extack);
return vr;
}
@@ -948,7 +952,8 @@ static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
static struct mlxsw_sp_rif *
mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
- const struct mlxsw_sp_rif_params *params);
+ const struct mlxsw_sp_rif_params *params,
+ struct netlink_ext_ack *extack);
static struct mlxsw_sp_rif_ipip_lb *
mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
@@ -966,7 +971,7 @@ mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
.lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
};
- rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common);
+ rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common, NULL);
if (IS_ERR(rif))
return ERR_CAST(rif);
return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
@@ -3711,7 +3716,7 @@ mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
struct mlxsw_sp_vr *vr;
int err;
- vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id);
+ vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, NULL);
if (IS_ERR(vr))
return ERR_CAST(vr);
fib = mlxsw_sp_vr_fib(vr, proto);
@@ -4750,7 +4755,7 @@ static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp->router->aborted)
return 0;
- vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id);
+ vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id, NULL);
if (IS_ERR(vr))
return PTR_ERR(vr);
@@ -4783,7 +4788,7 @@ mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp,
if (mlxsw_sp->router->aborted)
return 0;
- vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id);
+ vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id, NULL);
if (IS_ERR(vr))
return PTR_ERR(vr);
@@ -5346,7 +5351,8 @@ const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
static struct mlxsw_sp_rif *
mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
- const struct mlxsw_sp_rif_params *params)
+ const struct mlxsw_sp_rif_params *params,
+ struct netlink_ext_ack *extack)
{
u32 tb_id = l3mdev_fib_table(params->dev);
const struct mlxsw_sp_rif_ops *ops;
@@ -5360,14 +5366,16 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
ops = mlxsw_sp->router->rif_ops_arr[type];
- vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
+ vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack);
if (IS_ERR(vr))
return ERR_CAST(vr);
vr->rif_count++;
err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
- if (err)
+ if (err) {
+ NL_SET_ERR_MSG(extack, "spectrum: Exceeded number of supported router interfaces");
goto err_rif_index_alloc;
+ }
rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
if (!rif) {
@@ -5454,7 +5462,8 @@ mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
static int
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev)
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
@@ -5470,7 +5479,7 @@ mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
};
mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan);
- rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms);
+ rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack);
if (IS_ERR(rif))
return PTR_ERR(rif);
}
@@ -5525,7 +5534,8 @@ mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
struct net_device *port_dev,
- unsigned long event, u16 vid)
+ unsigned long event, u16 vid,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
@@ -5537,7 +5547,7 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
switch (event) {
case NETDEV_UP:
return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
- l3_dev);
+ l3_dev, extack);
case NETDEV_DOWN:
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
break;
@@ -5547,19 +5557,22 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
}
static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
- unsigned long event)
+ unsigned long event,
+ struct netlink_ext_ack *extack)
{
if (netif_is_bridge_port(port_dev) ||
netif_is_lag_port(port_dev) ||
netif_is_ovs_port(port_dev))
return 0;
- return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1);
+ return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1,
+ extack);
}
static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
struct net_device *lag_dev,
- unsigned long event, u16 vid)
+ unsigned long event, u16 vid,
+ struct netlink_ext_ack *extack)
{
struct net_device *port_dev;
struct list_head *iter;
@@ -5569,7 +5582,8 @@ static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
if (mlxsw_sp_port_dev_check(port_dev)) {
err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
port_dev,
- event, vid);
+ event, vid,
+ extack);
if (err)
return err;
}
@@ -5579,16 +5593,19 @@ static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
}
static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
- unsigned long event)
+ unsigned long event,
+ struct netlink_ext_ack *extack)
{
if (netif_is_bridge_port(lag_dev))
return 0;
- return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1);
+ return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1,
+ extack);
}
static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
- unsigned long event)
+ unsigned long event,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
struct mlxsw_sp_rif_params params = {
@@ -5598,7 +5615,7 @@ static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
switch (event) {
case NETDEV_UP:
- rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms);
+ rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack);
if (IS_ERR(rif))
return PTR_ERR(rif);
break;
@@ -5612,7 +5629,8 @@ static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
}
static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
- unsigned long event)
+ unsigned long event,
+ struct netlink_ext_ack *extack)
{
struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
u16 vid = vlan_dev_vlan_id(vlan_dev);
@@ -5622,27 +5640,28 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
if (mlxsw_sp_port_dev_check(real_dev))
return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
- event, vid);
+ event, vid, extack);
else if (netif_is_lag_master(real_dev))
return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
- vid);
+ vid, extack);
else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
- return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event);
+ return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event, extack);
return 0;
}
static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
- unsigned long event)
+ unsigned long event,
+ struct netlink_ext_ack *extack)
{
if (mlxsw_sp_port_dev_check(dev))
- return mlxsw_sp_inetaddr_port_event(dev, event);
+ return mlxsw_sp_inetaddr_port_event(dev, event, extack);
else if (netif_is_lag_master(dev))
- return mlxsw_sp_inetaddr_lag_event(dev, event);
+ return mlxsw_sp_inetaddr_lag_event(dev, event, extack);
else if (netif_is_bridge_master(dev))
- return mlxsw_sp_inetaddr_bridge_event(dev, event);
+ return mlxsw_sp_inetaddr_bridge_event(dev, event, extack);
else if (is_vlan_dev(dev))
- return mlxsw_sp_inetaddr_vlan_event(dev, event);
+ return mlxsw_sp_inetaddr_vlan_event(dev, event, extack);
else
return 0;
}
@@ -5668,7 +5687,7 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
if (!mlxsw_sp_rif_should_config(rif, dev, event))
goto out;
- err = __mlxsw_sp_inetaddr_event(dev, event);
+ err = __mlxsw_sp_inetaddr_event(dev, event, NULL);
out:
return notifier_from_errno(err);
}
@@ -5690,7 +5709,7 @@ int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
if (!mlxsw_sp_rif_should_config(rif, dev, event))
goto out;
- err = __mlxsw_sp_inetaddr_event(dev, event);
+ err = __mlxsw_sp_inetaddr_event(dev, event, ivi->extack);
out:
return notifier_from_errno(err);
}
@@ -5719,7 +5738,7 @@ static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
if (!mlxsw_sp_rif_should_config(rif, dev, event))
goto out;
- __mlxsw_sp_inetaddr_event(dev, event);
+ __mlxsw_sp_inetaddr_event(dev, event, NULL);
out:
rtnl_unlock();
dev_put(dev);
@@ -5771,7 +5790,7 @@ int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
if (!mlxsw_sp_rif_should_config(rif, dev, event))
goto out;
- err = __mlxsw_sp_inetaddr_event(dev, event);
+ err = __mlxsw_sp_inetaddr_event(dev, event, i6vi->extack);
out:
return notifier_from_errno(err);
}
@@ -5848,7 +5867,8 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
}
static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
- struct net_device *l3_dev)
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_rif *rif;
@@ -5857,9 +5877,9 @@ static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
*/
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
if (rif)
- __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
+ __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN, extack);
- return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
+ return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP, extack);
}
static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
@@ -5870,7 +5890,7 @@ static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
if (!rif)
return;
- __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
+ __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN, NULL);
}
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
@@ -5886,10 +5906,14 @@ int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
case NETDEV_PRECHANGEUPPER:
return 0;
case NETDEV_CHANGEUPPER:
- if (info->linking)
- err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
- else
+ if (info->linking) {
+ struct netlink_ext_ack *extack;
+
+ extack = netdev_notifier_info_to_extack(&info->info);
+ err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev, extack);
+ } else {
mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
+ }
break;
}
@@ -6196,7 +6220,7 @@ mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
struct mlxsw_sp_vr *ul_vr;
int err;
- ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id);
+ ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL);
if (IS_ERR(ul_vr))
return PTR_ERR(ul_vr);
--
2.1.4
^ permalink raw reply related
* Re: [PATCH net-next] virtio_net: implement VIRTIO_CONFIG_S_NEEDS_RESET
From: Michael S. Tsirkin @ 2017-10-16 16:38 UTC (permalink / raw)
To: Willem de Bruijn
Cc: Network Development, David Miller, Jason Wang, virtualization,
Willem de Bruijn
In-Reply-To: <CAF=yD-LW7f30V8Ci1SQUPZ-WBihqr93cWQP2QBFg2oQtytvAPg@mail.gmail.com>
On Mon, Oct 16, 2017 at 12:04:57PM -0400, Willem de Bruijn wrote:
> On Mon, Oct 16, 2017 at 11:31 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Mon, Oct 16, 2017 at 11:03:18AM -0400, Willem de Bruijn wrote:
> >> >> +static int virtnet_reset(struct virtnet_info *vi)
> >> >> +{
> >> >> + struct virtio_device *dev = vi->vdev;
> >> >> + int ret;
> >> >> +
> >> >> + virtio_config_disable(dev);
> >> >> + dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
> >> >> + virtnet_freeze_down(dev, true);
> >> >> + remove_vq_common(vi);
> >> >> +
> >> >> + virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
> >> >> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
> >> >> +
> >> >> + ret = virtio_finalize_features(dev);
> >> >> + if (ret)
> >> >> + goto err;
> >> >> +
> >> >> + ret = virtnet_restore_up(dev);
> >> >> + if (ret)
> >> >> + goto err;
> >> >> +
> >> >> + ret = virtnet_set_queues(vi, vi->curr_queue_pairs);
> >> >> + if (ret)
> >> >> + goto err;
> >> >> +
> >> >> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> >> >> + virtio_config_enable(dev);
> >> >> + return 0;
> >> >> +
> >> >> +err:
> >> >> + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
> >> >> + return ret;
> >> >> +}
> >> >> +
> >> >> static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
> >> >> {
> >> >> struct scatterlist sg;
> >> >
> >> > I have a question here though. How do things like MAC address
> >> > get restored?
> >> >
> >> > What about the rx mode?
> >> >
> >> > vlans?
> >>
> >> The function as is releases and reinitializes only ring state.
> >> Device configuration such as mac and vlan persist across
> >> the reset.
> >
> > What gave you this impression? Take a look at e.g. this
> > code in qemu:
> >
> > static void virtio_net_reset(VirtIODevice *vdev)
> > {
> > VirtIONet *n = VIRTIO_NET(vdev);
> >
> > /* Reset back to compatibility mode */
> > n->promisc = 1;
> > n->allmulti = 0;
> > n->alluni = 0;
> > n->nomulti = 0;
> > n->nouni = 0;
> > n->nobcast = 0;
> > /* multiqueue is disabled by default */
> > n->curr_queues = 1;
> > timer_del(n->announce_timer);
> > n->announce_counter = 0;
> > n->status &= ~VIRTIO_NET_S_ANNOUNCE;
> >
> > /* Flush any MAC and VLAN filter table state */
> > n->mac_table.in_use = 0;
> > n->mac_table.first_multi = 0;
> > n->mac_table.multi_overflow = 0;
> > n->mac_table.uni_overflow = 0;
> > memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
> > memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
> > qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
> > memset(n->vlans, 0, MAX_VLAN >> 3);
> > }
> >
> > So device seems to lose all state, you have to re-program it.
>
> Oh, indeed! The guest does not reset its state, so it might
> be out of sync with the host after the operation. Was this not
> an issue when previously resetting in the context of xdp?
I suspect it was broken back then, too.
> >> > Also, it seems that LINK_ANNOUNCE requests will get ignored
> >> > even if they got set before the reset, leading to downtime.
> >>
> >> Do you mean act on VIRTIO_NET_F_GUEST_ANNOUNCE
> >> requests? That flag is tested and netdev_notify_peers
> >> called before resetting virtio ring state.
> >
> > Yes but I wonder if there's a race where announce
> > is set after it is read but before NEED_RESET is read.
> >
> > Re-reading status from the config before reset
> > might be necessary.
>
> Thanks, I'll have a look. Perhaps a host should simply not
> request a reset while it is waiting for an announce ack.
It's one option though we can't make this change for existing hosts.
We also have the reverse condition where announce is requested after
NEED_RESET is set.
--
MST
^ permalink raw reply
* Re: [PATCH net-next v3 0/5] net: dsa: remove .set_addr
From: Andrew Lunn @ 2017-10-16 16:44 UTC (permalink / raw)
To: David Laight
Cc: Rodney Cummings, Vivien Didelot, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, kernel@savoirfairelinux.com,
David S. Miller, Florian Fainelli
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6DD00980E8@AcuExch.aculab.com>
On Mon, Oct 16, 2017 at 04:30:34PM +0000, David Laight wrote:
> From: Andrew Lunn
> > Sent: 16 October 2017 17:10
> ...
> > So, received Pause frames never leave the MAC. They don't get bridged,
> > nor do they get passed up for host processing. They are purely point
> > to point between two MAC peers. The destination is unambiguous. It is
> > simple the other MAC peer. The destination address makes it clear it
> > is a pause frame, the the source address seems to be unneeded.
> >
> > In this context, a random MAC addresses are safe.
>
> Is there any reason why a fixed value (say 00:00:00:00:00:00)
> can't be used?
I was going to suggest 42:42:42:42:42:42 :-)
Andrew
^ permalink raw reply
* Re: [PATCH net-next v3 0/5] net: dsa: remove .set_addr
From: Andrew Lunn @ 2017-10-16 16:47 UTC (permalink / raw)
To: Rodney Cummings
Cc: Vivien Didelot, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, kernel@savoirfairelinux.com,
David S. Miller, Florian Fainelli, David Laight
In-Reply-To: <CY1PR0401MB1536097366C596C42A8B225B924F0@CY1PR0401MB1536.namprd04.prod.outlook.com>
On Mon, Oct 16, 2017 at 04:28:04PM +0000, Rodney Cummings wrote:
> Hi Andrew,
>
> I may have misunderstood.
>
> If this MAC address is the destination
Nope. This is the source address, for Pause frames.
> My concern is that for a source MAC address, a local random MAC
> address is not safe in all networks, because it has the potential
> for duplication. That topic has been discussed quite a bit in IEEE
> 802.
Duplications don't matter, for pause frames. The source address
appears to be unused. And these frames don't get passed the direct
peers MAC layer.
Andrew
^ permalink raw reply
* Re: [PATCH net] bpf: disallow arithmetic operations on context pointer
From: Edward Cree @ 2017-10-16 16:47 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev, oss-drivers, alexei.starovoitov, daniel
In-Reply-To: <20171016093043.36fcfedc@cakuba.netronome.com>
On 16/10/17 17:30, Jakub Kicinski wrote:
> On Mon, 16 Oct 2017 17:16:24 +0100, Edward Cree wrote:
>> On 16/10/17 16:45, Jakub Kicinski wrote:
>>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>>> index 8b8d6ba39e23..8499759d0c7a 100644
>>> --- a/kernel/bpf/verifier.c
>>> +++ b/kernel/bpf/verifier.c
>>> @@ -1116,7 +1116,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
>>> /* ctx accesses must be at a fixed offset, so that we can
>>> * determine what type of data were returned.
>>> */
>>> - if (!tnum_is_const(reg->var_off)) {
>>> + if (reg->off) {
>>> + verbose("derefence of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
>> This is slightly unclear, it's not that two adds is bad (e.g. r1 += 8;
>> r0 = *(u32 *)r1 is bad too), it's that the offset must be in the load,
>> not the register; your message might be accurate for some compilers but
>> not in full generality (especially for assemblers without compiling).
> I'm happy to hear better suggestions :) I've spent quite a bit of time
> scratching my head thinking how to phrase this best. The first
> part of the message is general enough IMHO, the second is targeted
> mostly at C developers.
Hmm, what really bugs me is that if e.g. the compiler turned
*(ctx + 4 + 4)
or
ctx[4 + 4]
or even
ctx->arraymemb[4]
into this kind of arithmetic on ctx, arguably that would be a bug in the
compiler — if it's doing proper constexpr folding on its IR (or something
along those lines) it should be able to turn them all into good LDX. The
same even goes for if (ctx + 4) got stored in a local, because there's no
reason that has to map to a register.
So it's not even that "your C source breaks the rules", it's that "your C
compiler did something silly that we don't handle".
Maybe the message should be "compiler maybe mishandled ctx+const+const"?
-Ed
^ permalink raw reply
* RE: [PATCH net-next v3 0/5] net: dsa: remove .set_addr
From: Rodney Cummings @ 2017-10-16 16:52 UTC (permalink / raw)
To: Andrew Lunn
Cc: Vivien Didelot, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, kernel@savoirfairelinux.com,
David S. Miller, Florian Fainelli, David Laight
In-Reply-To: <20171016164737.GD13339@lunn.ch>
PAUSE is only one higher layer entity. The source MAC address may not matter there, but it definitely matters for other higher layer entities (like IEEE Std 1588).
The Marvell switch can run more than just PAUSE as a higher layer protocol.
How do you guarantee that this MAC address is used for PAUSE, and only for PAUSE?
> -----Original Message-----
> From: Andrew Lunn [mailto:andrew@lunn.ch]
> Sent: Monday, October 16, 2017 11:48 AM
> To: Rodney Cummings <rodney.cummings@ni.com>
> Cc: Vivien Didelot <vivien.didelot@savoirfairelinux.com>;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> kernel@savoirfairelinux.com; David S. Miller <davem@davemloft.net>;
> Florian Fainelli <f.fainelli@gmail.com>; David Laight
> <David.Laight@ACULAB.COM>
> Subject: Re: [PATCH net-next v3 0/5] net: dsa: remove .set_addr
>
> On Mon, Oct 16, 2017 at 04:28:04PM +0000, Rodney Cummings wrote:
> > Hi Andrew,
> >
> > I may have misunderstood.
> >
> > If this MAC address is the destination
>
> Nope. This is the source address, for Pause frames.
>
> > My concern is that for a source MAC address, a local random MAC
> > address is not safe in all networks, because it has the potential
> > for duplication. That topic has been discussed quite a bit in IEEE
> > 802.
>
> Duplications don't matter, for pause frames. The source address
> appears to be unused. And these frames don't get passed the direct
> peers MAC layer.
>
> Andrew
^ permalink raw reply
* Re: [PATCH net-next v3 0/5] net: dsa: remove .set_addr
From: Andrew Lunn @ 2017-10-16 16:57 UTC (permalink / raw)
To: Rodney Cummings
Cc: Vivien Didelot, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, kernel@savoirfairelinux.com,
David S. Miller, Florian Fainelli, David Laight
In-Reply-To: <CY1PR0401MB153605AD6262F8E25A41F913924F0@CY1PR0401MB1536.namprd04.prod.outlook.com>
> How do you guarantee that this MAC address is used for PAUSE, and only for PAUSE?
That is the only thing the data sheet says this MAC address is used
for.
Andrew
^ permalink raw reply
* Re: [patch net v2 1/4] net/sched: Change tc_action refcnt and bindcnt to atomic
From: Cong Wang @ 2017-10-16 17:06 UTC (permalink / raw)
To: Chris Mi
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Lucas Bates,
Jiri Pirko, David Miller
In-Reply-To: <1508152718-28726-2-git-send-email-chrism@mellanox.com>
On Mon, Oct 16, 2017 at 4:18 AM, Chris Mi <chrism@mellanox.com> wrote:
> If many filters share the same action. That action's refcnt and bindcnt
> could be manipulated by many RCU callbacks at the same time. This patch
> makes these operations atomic.
Actually I have been thinking about removing these RCU callbacks,
they are not necessary AFAIK, callers hold RTNL lock so they are
allowed to block. The only drawback is that adding a synchronize_rcu(),
but these are slow paths anyway...
I am not sure, it is arguable anyway, essentially it is:
synchronize_rcu() in slow path vs. multiple RCU callback races
>
> Fixes commit in pre-git era.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
This is not true, the action RCU callbacks were introduced
by:
commit c7de2cf053420d63bac85133469c965d4b1083e1
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed Jun 9 02:09:23 2010 +0000
pkt_sched: gen_kill_estimator() rcu fixes
and the filter RCU callbacks were introduced by the
patchset like this one:
commit 1ce87720d456e471de0fbd814dc5d1fe10fc1c44
Author: John Fastabend <john.fastabend@gmail.com>
Date: Fri Sep 12 20:09:16 2014 -0700
net: sched: make cls_u32 lockless
^ permalink raw reply
* Re: [PATCH net] bpf: disallow arithmetic operations on context pointer
From: Jakub Kicinski @ 2017-10-16 17:06 UTC (permalink / raw)
To: Edward Cree; +Cc: netdev, oss-drivers, alexei.starovoitov, daniel
In-Reply-To: <e2c4322a-301f-47f9-d102-725138d1bf67@solarflare.com>
On Mon, 16 Oct 2017 17:47:45 +0100, Edward Cree wrote:
> On 16/10/17 17:30, Jakub Kicinski wrote:
> > On Mon, 16 Oct 2017 17:16:24 +0100, Edward Cree wrote:
> >> On 16/10/17 16:45, Jakub Kicinski wrote:
> >>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> >>> index 8b8d6ba39e23..8499759d0c7a 100644
> >>> --- a/kernel/bpf/verifier.c
> >>> +++ b/kernel/bpf/verifier.c
> >>> @@ -1116,7 +1116,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
> >>> /* ctx accesses must be at a fixed offset, so that we can
> >>> * determine what type of data were returned.
> >>> */
> >>> - if (!tnum_is_const(reg->var_off)) {
> >>> + if (reg->off) {
> >>> + verbose("derefence of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
> >> This is slightly unclear, it's not that two adds is bad (e.g. r1 += 8;
> >> r0 = *(u32 *)r1 is bad too), it's that the offset must be in the load,
> >> not the register; your message might be accurate for some compilers but
> >> not in full generality (especially for assemblers without compiling).
> > I'm happy to hear better suggestions :) I've spent quite a bit of time
> > scratching my head thinking how to phrase this best. The first
> > part of the message is general enough IMHO, the second is targeted
> > mostly at C developers.
> Hmm, what really bugs me is that if e.g. the compiler turned
> *(ctx + 4 + 4)
> or
> ctx[4 + 4]
> or even
> ctx->arraymemb[4]
> into this kind of arithmetic on ctx, arguably that would be a bug in the
> compiler — if it's doing proper constexpr folding on its IR (or something
> along those lines) it should be able to turn them all into good LDX. The
> same even goes for if (ctx + 4) got stored in a local, because there's no
> reason that has to map to a register.
> So it's not even that "your C source breaks the rules", it's that "your C
> compiler did something silly that we don't handle".
> Maybe the message should be "compiler maybe mishandled ctx+const+const"?
Hm. We have no proof of compilers doing such things. It's probably
more likely that this will be hit if someone does:
struct xxx *X = &skb->cb;
X->field;
Or just tries to add a constant offset to ctx by hand... "Complier may
have done something silly" is probably implied in all verifier
messages :)
FWIW the pre-tnum error would be:
R%d invalid mem access 'inv'
So we are making this a lot more clear anyway.
^ permalink raw reply
* [PATCH net-next] tools: bpftool: use more common tag format
From: Jakub Kicinski @ 2017-10-16 17:12 UTC (permalink / raw)
To: netdev; +Cc: oss-drivers, alexei.starovoitov, daniel, Jakub Kicinski
Program tag is usually displayed as string of bytes without
any separators (e.g. as "aa5520b1090cfeb6" vs MAC addr-like
format bpftool uses currently: "aa:55:20:b1:09:0c:fe:b6").
Make bptfool use the more common format both for displaying
the tag and selecting the program by tag.
This was pointed out in review but I misunderstood the comment.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
---
tools/bpf/bpftool/Documentation/bpftool-prog.rst | 2 +-
tools/bpf/bpftool/main.h | 3 +--
tools/bpf/bpftool/prog.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index 04d12f768f06..3968f0bd37db 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -55,7 +55,7 @@ EXAMPLES
**# bpftool prog show**
::
- 10: xdp name some_prog tag 00:5a:3d:21:23:62:0c:8b
+ 10: xdp name some_prog tag 005a3d2123620c8b
loaded_at Sep 29/20:11 uid 0
xlated 528B jited 370B memlock 4096B map_ids 10
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 8e809b2bb311..844e4ef6db56 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -53,8 +53,7 @@
#define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
#define BAD_ARG() ({ err("what is '%s'?\n", *argv); -1; })
-#define BPF_TAG_FMT "%02hhx:%02hhx:%02hhx:%02hhx:" \
- "%02hhx:%02hhx:%02hhx:%02hhx"
+#define BPF_TAG_FMT "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
#define HELP_SPEC_PROGRAM \
"PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 9e2681c83717..d60f5307b6e2 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -224,7 +224,7 @@ static int show_prog(int fd)
printf("name %s ", info.name);
printf("tag ");
- print_hex(info.tag, BPF_TAG_SIZE, ":");
+ print_hex(info.tag, BPF_TAG_SIZE, "");
printf("\n");
if (info.load_time) {
--
2.14.1
^ permalink raw reply related
* Re: [PATCH] can: check for null sk before deferencing it via the call to sock_net
From: Oliver Hartkopp @ 2017-10-16 17:32 UTC (permalink / raw)
To: Josh Boyer
Cc: Colin King, Marc Kleine-Budde, David S . Miller, linux-can,
netdev, kernel-janitors, Linux-Kernel@Vger. Kernel. Org
In-Reply-To: <CA+5PVA7fJfZmN-XLuqARGkWL6eY54HaRAj19K_Und3K7vAVfpg@mail.gmail.com>
On 10/16/2017 06:37 PM, Josh Boyer wrote:
> On Fri, Sep 8, 2017 at 1:46 PM, Oliver Hartkopp <socketcan@hartkopp.net> wrote:
>>
>>
>> On 09/08/2017 05:02 PM, Colin King wrote:
>>>
>>> From: Colin Ian King <colin.king@canonical.com>
>>>
>>> The assignment of net via call sock_net will dereference sk. This
>>> is performed before a sanity null check on sk, so there could be
>>> a potential null dereference on the sock_net call if sk is null.
>>> Fix this by assigning net after the sk null check. Also replace
>>> the sk == NULL with the more usual !sk idiom.
>>>
>>> Detected by CoverityScan CID#1431862 ("Dereference before null check")
>>>
>>> Fixes: 384317ef4187 ("can: network namespace support for CAN_BCM
>>> protocol")
>>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>>
>>
>> Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
>
> I don't see this one queued up in the net or net-next trees. Did it
> fall through the cracks or did it get queued up elsewhere? Seems like
> it's a good candidate to get into 4.14?
It definitely is!
Marc is our responsible guy for CAN related upstreams - but he seems to
be busy as I already poked him here:
https://marc.info/?l=linux-can&m=150771819505097&w=2
If he doesn't send a pull request by beginning of next week, I would ask
Dave to grab these patches - to get them into 4.14.
Best regards,
Oliver
^ permalink raw reply
* Re: act_skbedit unable to check queue_mapping at init time
From: Cong Wang @ 2017-10-16 17:36 UTC (permalink / raw)
To: Florian Fainelli
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Jiri Pirko,
Alexander Duyck
In-Reply-To: <c48c8af5-d4c6-d2f7-cc0f-6cb50f2a865e@gmail.com>
Hi, Florian
On Wed, Oct 11, 2017 at 12:02 PM, Florian Fainelli <f.fainelli@gmail.com> wrote:
> Hi all,
>
> It is perfectly possible for the following to happen:
>
> # ls /sys/class/net/gphy/queues
> rx-0 tx-0 tx-1 tx-2 tx-3
> # tc qdisc add dev gphy root handle 1: multiq
> # tc filter add dev gphy parent 1: protocol ip prio 1 u32
> match ip dst 192.168.1.1 action skbedit queue_mapping 5
>
> that specifies a queue_mapping value that exceeds what the underlying
> device supports. There is a check for dev->real_num_tx_queue >
> d->queue_mapping in tcf_skbedit() which makes sure we won't overflow the
> queue space, but this will essentially render the action inactive.
>
> I can't find a way to get a reference on a network device from a
> tc_action_ops->init function in order to validate that the queue_mapping
> is valid at ->init() time and return an appropriate error if we are
> exceeding what the device does. This is an action chained to a match and
> a filter, so somehow one would think it would be possible to obtain a
> reference on the network device the filter was installed on...
>
> Any clues how we could fix that?
The problems is actions could be standalone and shared by multiple
filters, it is impossible to check it for this case. However, it is possible
to check it for non-standalone case, the parameter 'bind' indicates it.
You still need to find a way to get either the tp pointer or dev pointer.
Thanks.
^ permalink raw reply
* Re: [net-next RFC 3/4] openvswitch: Add meter infrastructure
From: Pravin Shelar @ 2017-10-16 17:49 UTC (permalink / raw)
To: Andy Zhou; +Cc: Linux Kernel Network Developers, Joe Stringer, Greg Rose
In-Reply-To: <CABKoBm2T6-BgecNr4RRkvtW2+Z4dXBrFo=Wn2TpsX=J+HTuXtg@mail.gmail.com>
On Mon, Oct 16, 2017 at 12:05 AM, Andy Zhou <azhou@ovn.org> wrote:
> On Fri, Oct 13, 2017 at 5:12 PM, Pravin Shelar <pshelar@ovn.org> wrote:
>> On Thu, Oct 12, 2017 at 3:38 PM, Andy Zhou <azhou@ovn.org> wrote:
>>> OVS kernel datapath so far does not support Openflow meter action.
>>> This is the first stab at adding kernel datapath meter support.
>>> This implementation supports only drop band type.
>>>
>>> Signed-off-by: Andy Zhou <azhou@ovn.org>
>>> ---
>>> net/openvswitch/Makefile | 1 +
>>> net/openvswitch/datapath.c | 14 +-
>>> net/openvswitch/datapath.h | 3 +
>>> net/openvswitch/meter.c | 611 +++++++++++++++++++++++++++++++++++++++++++++
>>> net/openvswitch/meter.h | 54 ++++
>>> 5 files changed, 681 insertions(+), 2 deletions(-)
>>> create mode 100644 net/openvswitch/meter.c
>>> create mode 100644 net/openvswitch/meter.h
>>>
>> ...
>>
>>> diff --git a/net/openvswitch/meter.c b/net/openvswitch/meter.c
>>> new file mode 100644
>>> index 000000000000..f24ebb5f7af4
>>> --- /dev/null
>>> +++ b/net/openvswitch/meter.c
>>
>> ....
>> ....
>>> +static int ovs_meter_cmd_features(struct sk_buff *skb, struct genl_info *info)
>>> +{
>>> + struct datapath *dp;
>>> + struct ovs_header *ovs_header = info->userhdr;
>>> + struct sk_buff *reply;
>>> + struct ovs_header *ovs_reply_header;
>>> + struct nlattr *nla, *band_nla;
>>> + int err;
>>> +
>>> + /* Check that the datapath exists */
>>> + ovs_lock();
>>> + dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
>>> + ovs_unlock();
>>> + if (!dp)
>>> + return -ENODEV;
>>> +
>> why dp check is required for this API?
> Is it possible for another core delete the dp, before ovs_lock()
> returns? Then, in theory, get_dp() can
> return NULL, no?
I do not see dp used anywhere in function. so the question was why is
dp lookup done here?
>>
>>> + reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_FEATURES,
>>> + &ovs_reply_header);
>>> + if (!reply)
>>> + return PTR_ERR(reply);
>>> +
>>> + if (nla_put_u32(reply, OVS_METER_ATTR_MAX_METERS, U32_MAX) ||
>>> + nla_put_u32(reply, OVS_METER_ATTR_MAX_BANDS, DP_MAX_BANDS))
>>> + goto nla_put_failure;
>>> +
>>> + nla = nla_nest_start(reply, OVS_METER_ATTR_BANDS);
>>> + if (!nla)
>>> + goto nla_put_failure;
>>> +
>>> + band_nla = nla_nest_start(reply, OVS_BAND_ATTR_UNSPEC);
>>> + if (!band_nla)
>>> + goto nla_put_failure;
>>> + /* Currently only DROP band type is supported. */
>>> + if (nla_put_u32(reply, OVS_BAND_ATTR_TYPE, OVS_METER_BAND_TYPE_DROP))
>>> + goto nla_put_failure;
>>> + nla_nest_end(reply, band_nla);
>>> + nla_nest_end(reply, nla);
>>> +
>>> + genlmsg_end(reply, ovs_reply_header);
>>> + return genlmsg_reply(reply, info);
>>> +
>>> +nla_put_failure:
>>> + nlmsg_free(reply);
>>> + err = -EMSGSIZE;
>>> + return err;
>>> +}
>>> +
>> ....
>>
>>> +static int ovs_meter_cmd_set(struct sk_buff *skb, struct genl_info *info)
>>> +{
>>> + struct nlattr **a = info->attrs;
>>> + struct dp_meter *meter, *old_meter;
>>> + struct sk_buff *reply;
>>> + struct ovs_header *ovs_reply_header;
>>> + struct ovs_header *ovs_header = info->userhdr;
>>> + struct datapath *dp;
>>> + int err;
>>> + u32 meter_id;
>>> + bool failed;
>>> +
>>> + meter = dp_meter_create(a);
>>> + if (IS_ERR_OR_NULL(meter))
>>> + return PTR_ERR(meter);
>>> +
>>> + reply = ovs_meter_cmd_reply_start(info, OVS_METER_CMD_SET,
>>> + &ovs_reply_header);
>>> + if (IS_ERR(reply)) {
>>> + err = PTR_ERR(reply);
>>> + goto exit_free_meter;
>>> + }
>>> +
>>> + ovs_lock();
>>> + dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
>>> + if (!dp) {
>>> + err = -ENODEV;
>>> + goto exit_unlock;
>>> + }
>>> +
>>> + if (!a[OVS_METER_ATTR_ID]) {
>>> + err = -ENODEV;
>>> + goto exit_unlock;
>>> + }
>>> +
>>> + meter_id = nla_get_u32(a[OVS_METER_ATTR_ID]);
>>> +
>>> + /* Cannot fail after this. */
>>> + old_meter = lookup_meter(dp, meter_id);
>>> + attach_meter(dp, meter);
>>> + ovs_unlock();
>>> +
>> After the unlock, it is not safe to keep the ref to old_meter. better
>> to release lock at the end. we could optimize it later if required.
>
> I see a problem here: the old_meter has not been removed from the list before
> unlock. The code should have been:
>
> old_meter = lookup_meter(dp, meter_id);
> detch_meter(dp, old_meter);
> attach_meter(dp, meter);
> ovs_unlock();
>
> Do you still see a problem w.r.t. unlock() here? Once detch_meter() is called,
> another thread should not have access to 'old_meter' any more. right?
looks good.
^ permalink raw reply
* Re: [PATCH] [net-next] net: systemport: add NET_DSA dependency
From: Florian Fainelli @ 2017-10-16 17:55 UTC (permalink / raw)
To: Arnd Bergmann
Cc: David S. Miller, Michael Chan, Sathya Perla, Nicolas Pitre,
netdev, linux-kernel
In-Reply-To: <20171016113258.3735473-1-arnd@arndb.de>
On 10/16/2017 04:32 AM, Arnd Bergmann wrote:
> The notifier cause a link error when NET_DSA is a loadable
> module:
>
> drivers/net/ethernet/broadcom/bcmsysport.o: In function `bcm_sysport_remove':
> bcmsysport.c:(.text+0x1582): undefined reference to `unregister_dsa_notifier'
> drivers/net/ethernet/broadcom/bcmsysport.o: In function `bcm_sysport_probe':
> bcmsysport.c:(.text+0x278d): undefined reference to `register_dsa_notifier'
>
> This adds a dependency that forces the systemport driver to be
> a loadable module as well when that happens, but otherwise
> allows it to be built normally when DSA is either built-in or
> completely disabled.
>
> Fixes: d156576362c0 ("net: systemport: Establish lower/upper queue mapping")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Thanks Arnd.
--
Florian
^ permalink raw reply
* Recent payment notice to Anita Cochran
From: Anita Cochran @ 2017-10-16 18:48 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 372 bytes --]
\rHi ,
\rYour payment of $2744.29 to Anita Cochran was sent.
\rAllow up to 10 minutes for this transaction to appear.
\rSee your transaction details below:
http://horseoz.com/7363-RMBK/Payment-Details/
\rRespectfully Yours,
Anita Cochran
Please do not reply to this email. \rThis mailbox is for notification purposes only and you will not receive a reply.
^ permalink raw reply
* Re: [PATCH net-next] tools: bpftool: use more common tag format
From: Daniel Borkmann @ 2017-10-16 18:02 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov
In-Reply-To: <20171016171254.26225-1-jakub.kicinski@netronome.com>
On 10/16/2017 07:12 PM, Jakub Kicinski wrote:
> Program tag is usually displayed as string of bytes without
> any separators (e.g. as "aa5520b1090cfeb6" vs MAC addr-like
> format bpftool uses currently: "aa:55:20:b1:09:0c:fe:b6").
> Make bptfool use the more common format both for displaying
> the tag and selecting the program by tag.
>
> This was pointed out in review but I misunderstood the comment.
>
> Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Reviewed-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH] sunrcp: make function _svc_create_xprt static
From: J . Bruce Fields @ 2017-10-16 18:06 UTC (permalink / raw)
To: Colin King
Cc: Jeff Layton, Trond Myklebust, Anna Schumaker, David S . Miller,
linux-nfs, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20171016134021.15702-1-colin.king@canonical.com>
Thanks, applied for 4.15.--b.
On Mon, Oct 16, 2017 at 02:40:21PM +0100, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The function _svc_create_xprt is local to the source and
> does not need to be in global scope, so make it static.
>
> Cleans up sparse warning:
> symbol '_svc_create_xprt' was not declared. Should it be static?
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> net/sunrpc/svc_xprt.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
> index d16a8b423c20..18e87791350f 100644
> --- a/net/sunrpc/svc_xprt.c
> +++ b/net/sunrpc/svc_xprt.c
> @@ -250,9 +250,9 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
> svc_xprt_received(new);
> }
>
> -int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
> - struct net *net, const int family,
> - const unsigned short port, int flags)
> +static int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
> + struct net *net, const int family,
> + const unsigned short port, int flags)
> {
> struct svc_xprt_class *xcl;
>
> --
> 2.14.1
^ permalink raw reply
* Re: Ethtool question
From: Ben Greear @ 2017-10-16 18:10 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: David Miller, John W. Linville, netdev@vger.kernel.org
In-Reply-To: <CAJieiUhsxPRPBBV1WJR6NRfzDKt-8c=QYRHhwoW33KchSb-gXg@mail.gmail.com>
On 10/12/2017 03:00 PM, Roopa Prabhu wrote:
> On Thu, Oct 12, 2017 at 2:45 PM, Ben Greear <greearb@candelatech.com> wrote:
>> On 10/11/2017 01:49 PM, David Miller wrote:
>>>
>>> From: "John W. Linville" <linville@tuxdriver.com>
>>> Date: Wed, 11 Oct 2017 16:44:07 -0400
>>>
>>>> On Wed, Oct 11, 2017 at 09:51:56AM -0700, Ben Greear wrote:
>>>>>
>>>>> I noticed today that setting some ethtool settings to the same value
>>>>> returns an error code. I would think this should silently return
>>>>> success instead? Makes it easier to call it from scripts this way:
>>>>>
>>>>> [root@lf0313-6477 lanforge]# ethtool -L eth3 combined 1
>>>>> combined unmodified, ignoring
>>>>> no channel parameters changed, aborting
>>>>> current values: tx 0 rx 0 other 1 combined 1
>>>>> [root@lf0313-6477 lanforge]# echo $?
>>>>> 1
>>>>
>>>>
>>>> I just had this discussion a couple of months ago with someone. My
>>>> initial feeling was like you, a no-op is not a failure. But someone
>>>> convinced me otherwise...I will now endeavour to remember who that
>>>> was and how they convinced me...
>>>>
>>>> Anyone else have input here?
>>>
>>>
>>> I guess this usually happens when drivers don't support changing the
>>> settings at all. So they just make their ethtool operation for the
>>> 'set' always return an error.
>>>
>>> We could have a generic ethtool helper that does "get" and then if the
>>> "set" request is identical just return zero.
>>>
>>> But from another perspective, the error returned from the "set" in this
>>> situation also indicates to the user that the driver does not support
>>> the "set" operation which has value and meaning in and of itself. And
>>> we'd lose that with the given suggestion.
>>
>>
>> In my case, the driver (igb) does support the set, my program just made the
>> same
>> ethtool call several times and it fails after the initial change (that
>> actually
>> changes something), as best as I can figure.
>
>
> This error is returned by ethtool user-space. It does a get, check and
> then set if user has requested changes.
>
So, should we fix ethtool to return 0 in this case instead of an error code?
I think so. If the driver itself returns an error, then probably return the
error code and/or fix the driver as seems appropriate.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ 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