* [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP
@ 2015-02-24 5:42 roopa
2015-02-24 14:01 ` Rosen, Rami
2015-02-24 21:03 ` David Miller
0 siblings, 2 replies; 5+ messages in thread
From: roopa @ 2015-02-24 5:42 UTC (permalink / raw)
To: hadi; +Cc: netdev, davem, hannes
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Today neigh adds and dels using the netlink RTM_NEWNEIGH/RTM_DELNEIGH
messages require dst device to be specified. The equivalent ipv4 neigh
entry add/del using SIOCSARP/SIOCDARP does not require a device. It finds
the dst dev by doing a route lookup (ip_route_output).
This patch tries to match netlink ipv4 neigh add/del behaviour with
SIOCSARP/SIOCDARP for the case where user does not specify a device.
If user has not specified a dst device, it looks for the device via a
route lookup. If the route lookup fails, the behaviour is unchanged,
the user will get an -EINVAL as before
(This can be changed to return -ENODEV if needed. This patch leaves it at
-EINVAL to match current behaviour).
Testing this change requires an iproute2 patch to make dev optional
during ipv4 neigh adds/dels.
Reported-by: Jamal Hadi Salim <hadi@mojatatu.com>
Suggested-by: Jamal Hadi Salim <hadi@mojatatu.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
net/core/neighbour.c | 54 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 36 insertions(+), 18 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 70fe9e1..3fa2602 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -29,6 +29,7 @@
#endif
#include <linux/times.h>
#include <net/net_namespace.h>
+#include <net/route.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/sock.h>
@@ -1622,6 +1623,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
struct neighbour *neigh;
struct net_device *dev = NULL;
int err = -EINVAL;
+ void *dst;
ASSERT_RTNL();
if (nlmsg_len(nlh) < sizeof(*ndm))
@@ -1632,30 +1634,39 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
goto out;
ndm = nlmsg_data(nlh);
+ tbl = neigh_find_table(ndm->ndm_family);
+ if (tbl == NULL)
+ return -EAFNOSUPPORT;
+
+ if (nla_len(dst_attr) < tbl->key_len)
+ goto out;
+
+ dst = nla_data(dst_attr);
if (ndm->ndm_ifindex) {
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (dev == NULL) {
err = -ENODEV;
goto out;
}
- }
+ } else if (ndm->ndm_family == AF_INET) {
+ struct rtable *rt;
- tbl = neigh_find_table(ndm->ndm_family);
- if (tbl == NULL)
- return -EAFNOSUPPORT;
-
- if (nla_len(dst_attr) < tbl->key_len)
- goto out;
+ rt = ip_route_output(net, *(__be32 *)dst, 0, RTO_ONLINK, 0);
+ if (!IS_ERR(rt)) {
+ dev = rt->dst.dev;
+ ip_rt_put(rt);
+ }
+ }
if (ndm->ndm_flags & NTF_PROXY) {
- err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
+ err = pneigh_delete(tbl, net, dst, dev);
goto out;
}
if (dev == NULL)
goto out;
- neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
+ neigh = neigh_lookup(tbl, dst, dev);
if (neigh == NULL) {
err = -ENOENT;
goto out;
@@ -1692,24 +1703,31 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
goto out;
ndm = nlmsg_data(nlh);
+ tbl = neigh_find_table(ndm->ndm_family);
+ if (tbl == NULL)
+ return -EAFNOSUPPORT;
+
+ if (nla_len(tb[NDA_DST]) < tbl->key_len)
+ goto out;
+
+ dst = nla_data(tb[NDA_DST]);
if (ndm->ndm_ifindex) {
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (dev == NULL) {
err = -ENODEV;
goto out;
}
+ } else if (ndm->ndm_family == AF_INET) {
+ struct rtable *rt;
- if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
- goto out;
+ rt = ip_route_output(net, *(__be32 *)dst, 0, RTO_ONLINK, 0);
+ if (!IS_ERR(rt)) {
+ dev = rt->dst.dev;
+ ip_rt_put(rt);
+ }
}
-
- tbl = neigh_find_table(ndm->ndm_family);
- if (tbl == NULL)
- return -EAFNOSUPPORT;
-
- if (nla_len(tb[NDA_DST]) < tbl->key_len)
+ if (dev && tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
goto out;
- dst = nla_data(tb[NDA_DST]);
lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
if (ndm->ndm_flags & NTF_PROXY) {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* RE: [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP
2015-02-24 5:42 [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP roopa
@ 2015-02-24 14:01 ` Rosen, Rami
2015-02-24 14:35 ` roopa
2015-02-24 14:38 ` Eric Dumazet
2015-02-24 21:03 ` David Miller
1 sibling, 2 replies; 5+ messages in thread
From: Rosen, Rami @ 2015-02-24 14:01 UTC (permalink / raw)
To: roopa@cumulusnetworks.com, hadi@mojatatu.com
Cc: netdev@vger.kernel.org, davem@davemloft.net,
hannes@stressinduktion.org
Hi,
@@ -1692,24 +1703,31 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
goto out;
ndm = nlmsg_data(nlh);
+ tbl = neigh_find_table(ndm->ndm_family);
+ if (tbl == NULL)
+ return -EAFNOSUPPORT;
+
+ if (nla_len(tb[NDA_DST]) < tbl->key_len)
+ goto out;
+
+ dst = nla_data(tb[NDA_DST]);
if (ndm->ndm_ifindex) {
dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (dev == NULL) {
err = -ENODEV;
goto out;
}
If ip_route_output() fails, then the neigh_add() method will return -EINVAL (as it was initialized thus); or, in cases when the NTF_PROXY flag is set, it can return 0 or ENOBUFS, according to the result of the pneigh_lookup(), which is called immediately subsequently in this path. But in fact __ip_route_output_key(), which is invoked by ip_route_output(), can return different error codes, like -EINVAL,-ENODEV, -ENETUNREACH and more, via ERR_PTR.
So maybe better is (in order to reflect the cause of the error):
+ if (!IS_ERR(rt)) {
+ dev = rt->dst.dev;
+ ip_rt_put(rt);
+ } else
return PTR_ERR(rt);
We can exit the method at this point with "return PTR_ERR(rt)" because we are assured at this point that dev is NULL.
Error handling in neigh_delete() method maybe also be better changed accordingly.
Regards,
Rami Rosen
Intel Corporation
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP
2015-02-24 14:01 ` Rosen, Rami
@ 2015-02-24 14:35 ` roopa
2015-02-24 14:38 ` Eric Dumazet
1 sibling, 0 replies; 5+ messages in thread
From: roopa @ 2015-02-24 14:35 UTC (permalink / raw)
To: Rosen, Rami
Cc: hadi@mojatatu.com, netdev@vger.kernel.org, davem@davemloft.net,
hannes@stressinduktion.org
On 2/24/15, 6:01 AM, Rosen, Rami wrote:
> Hi,
>
> @@ -1692,24 +1703,31 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
> goto out;
>
> ndm = nlmsg_data(nlh);
> + tbl = neigh_find_table(ndm->ndm_family);
> + if (tbl == NULL)
> + return -EAFNOSUPPORT;
> +
> + if (nla_len(tb[NDA_DST]) < tbl->key_len)
> + goto out;
> +
> + dst = nla_data(tb[NDA_DST]);
> if (ndm->ndm_ifindex) {
> dev = __dev_get_by_index(net, ndm->ndm_ifindex);
> if (dev == NULL) {
> err = -ENODEV;
> goto out;
> }
>
> If ip_route_output() fails, then the neigh_add() method will return -EINVAL (as it was initialized thus);
I was intentionally trying not to return any special error code if
ip_route_output() fails. So the patch tries to make the ip_route_output
failure same as the case where the user did not specify a device.
> or, in cases when the NTF_PROXY flag is set, it can return 0 or ENOBUFS, according to the result of the pneigh_lookup(), which is called immediately subsequently in this path. But in fact __ip_route_output_key(), which is invoked by ip_route_output(), can return different error codes, like -EINVAL,-ENODEV, -ENETUNREACH and more, via ERR_PTR.
>
> So maybe better is (in order to reflect the cause of the error):
> + if (!IS_ERR(rt)) {
> + dev = rt->dst.dev;
> + ip_rt_put(rt);
> + } else
> return PTR_ERR(rt);
I intentionally don't return here ..because from the original code, the
NTF_PROXY case seemed to be ok with the device being NULL. The device
NULL check was after the NTF_PROXY code.
>
> We can exit the method at this point with "return PTR_ERR(rt)" because we are assured at this point that dev is NULL.
>
> Error handling in neigh_delete() method maybe also be better changed accordingly.
I intend to do some testing for the NTF_PROXY case, however, AFAICT,
this patch should not have introduced any functional changes in that path.
Thanks!.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP
2015-02-24 14:01 ` Rosen, Rami
2015-02-24 14:35 ` roopa
@ 2015-02-24 14:38 ` Eric Dumazet
1 sibling, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2015-02-24 14:38 UTC (permalink / raw)
To: Rosen, Rami
Cc: roopa@cumulusnetworks.com, hadi@mojatatu.com,
netdev@vger.kernel.org, davem@davemloft.net,
hannes@stressinduktion.org
On Tue, 2015-02-24 at 14:01 +0000, Rosen, Rami wrote:
> We can exit the method at this point with "return PTR_ERR(rt)" because we are assured at this point that dev is NULL.
Not sure it matters if dev is NULL or not :
We hold RTNL, and we do not have to hold/release dev.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP
2015-02-24 5:42 [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP roopa
2015-02-24 14:01 ` Rosen, Rami
@ 2015-02-24 21:03 ` David Miller
1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2015-02-24 21:03 UTC (permalink / raw)
To: roopa; +Cc: hadi, netdev, hannes
From: roopa@cumulusnetworks.com
Date: Mon, 23 Feb 2015 21:42:52 -0800
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> Today neigh adds and dels using the netlink RTM_NEWNEIGH/RTM_DELNEIGH
> messages require dst device to be specified. The equivalent ipv4 neigh
> entry add/del using SIOCSARP/SIOCDARP does not require a device. It finds
> the dst dev by doing a route lookup (ip_route_output).
>
> This patch tries to match netlink ipv4 neigh add/del behaviour with
> SIOCSARP/SIOCDARP for the case where user does not specify a device.
> If user has not specified a dst device, it looks for the device via a
> route lookup. If the route lookup fails, the behaviour is unchanged,
> the user will get an -EINVAL as before
> (This can be changed to return -ENODEV if needed. This patch leaves it at
> -EINVAL to match current behaviour).
>
> Testing this change requires an iproute2 patch to make dev optional
> during ipv4 neigh adds/dels.
>
> Reported-by: Jamal Hadi Salim <hadi@mojatatu.com>
> Suggested-by: Jamal Hadi Salim <hadi@mojatatu.com>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
I think the horse has already exited the barn on this one.
If people start depending upon this new behavior, they will write apps
that do not work on %99.9999999 of the kernels out there.
We are therefore stuck with the current semantics, for good or for
bad.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-02-24 21:03 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-24 5:42 [PATCH net-next RFC] ipv4 neigh: match add/del dev lookup behaviour to SIOCSARP/SIOCDARP roopa
2015-02-24 14:01 ` Rosen, Rami
2015-02-24 14:35 ` roopa
2015-02-24 14:38 ` Eric Dumazet
2015-02-24 21:03 ` David Miller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.