[PATCH net-next v4 3/3] ipvs: log additional sync daemon parameters

2016-06-16 Thread Quentin Armitage
Add new multicast parameters to log messages when sync daemons start.

Commit e4ff67513096 ("ipvs: add sync_maxlen parameter for the sync
daemon") and commit d33288172e72 ("ipvs: add more mcast parameters for
the sync daemon") added additional multicast parameters, but didn't add
them to the log messages when the sync daemons started.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   28 ++--
 1 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 2be99b2..3d0fd99 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1669,9 +1669,17 @@ static int sync_thread_master(void *data)
struct sock *sk = tinfo->sock->sk;
struct ip_vs_sync_buff *sb;
 
-   pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid, tinfo->id);
+   pr_info("sync thread started: state = MASTER, mcast_ifn = %s, syncid = 
%d, id = %d, maxlen = %u\n",
+   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid,
+   tinfo->id, ipvs->mcfg.sync_maxlen);
+   if (ipvs->mcfg.mcast_af == AF_INET)
+   pr_info("group = %pI4, port = %u, ttl = %u\n",
+   >mcfg.mcast_group.in, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
+   else
+   pr_info("group = %pI6c, port = %u, ttl = %u\n",
+   >mcfg.mcast_group.in6, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
 
for (;;) {
sb = next_sync_buff(ipvs, ms);
@@ -1723,9 +1731,17 @@ static int sync_thread_backup(void *data)
struct netns_ipvs *ipvs = tinfo->ipvs;
int len;
 
-   pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
+   pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, syncid = 
%d, id = %d, maxlen = %u\n",
+   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid,
+   tinfo->id, ipvs->bcfg.sync_maxlen);
+   if (ipvs->bcfg.mcast_af == AF_INET)
+   pr_info("group = %pI4, port = %u, ttl = %u\n",
+   >bcfg.mcast_group.in, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
+   else
+   pr_info("group = %pI6c, port = %u, ttl = %u\n",
+   >bcfg.mcast_group.in6, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
 
while (!kthread_should_stop()) {
wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
-- 
1.7.7.6



[PATCH net-next v4 2/3] ipvs: Don't check result < 0 after setting result = 0

2016-06-16 Thread Quentin Armitage
Move the block testing result < 0 to avoid the test immediately
after setting result = 0

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   11 ++-
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index fbc5ba4..2be99b2 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1496,13 +1496,14 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id,
if (result > 0)
set_sock_size(sock->sk, 1, result);
 
-   if (AF_INET == ipvs->mcfg.mcast_af)
+   if (ipvs->mcfg.mcast_af == AF_INET) {
result = bind_mcastif_addr(sock, dev);
-   else
+   if (result < 0) {
+   pr_err("Error binding address of mcast interface\n");
+   goto error;
+   }
+   } else {
result = 0;
-   if (result < 0) {
-   pr_err("Error binding address of the mcast interface\n");
-   goto error;
}
 
get_mcast_sockaddr(_addr, , >mcfg, id);
-- 
1.7.7.6



[PATCH net-next v4 1/3] ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync daemon

2016-06-16 Thread Quentin Armitage
Optimise starting sync daemons by using the result of the first call to
__dev_get_by_name() and pass the result or ifindex to subsequent functions
to avoid them having to call __dev_get_by_name() again.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   60 +--
 1 files changed, 20 insertions(+), 40 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 1b07578..fbc5ba4 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1356,28 +1356,22 @@ static void set_mcast_pmtudisc(struct sock *sk, int val)
 /*
  *  Specifiy default interface for outgoing multicasts
  */
-static int set_mcast_if(struct sock *sk, char *ifname)
+static int set_mcast_if(struct sock *sk, int ifindex)
 {
-   struct net_device *dev;
struct inet_sock *inet = inet_sk(sk);
-   struct net *net = sock_net(sk);
-
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
 
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   inet->mc_index = dev->ifindex;
+   inet->mc_index = ifindex;
/*  inet->mc_addr  = 0; */
 #ifdef CONFIG_IP_VS_IPV6
if (sk->sk_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
 
/* IPV6_MULTICAST_IF */
-   np->mcast_oif = dev->ifindex;
+   np->mcast_oif = ifindex;
}
 #endif
release_sock(sk);
@@ -1392,23 +1386,18 @@ static int set_mcast_if(struct sock *sk, char *ifname)
  *  in the in_addr structure passed in as a parameter.
  */
 static int
-join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
+join_mcast_group(struct sock *sk, struct in_addr *addr, int ifindex)
 {
-   struct net *net = sock_net(sk);
struct ip_mreqn mreq;
-   struct net_device *dev;
int ret;
 
memset(, 0, sizeof(mreq));
memcpy(_multiaddr, addr, sizeof(struct in_addr));
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
-   mreq.imr_ifindex = dev->ifindex;
+   mreq.imr_ifindex = ifindex;
 
lock_sock(sk);
ret = ip_mc_join_group(sk, );
@@ -1419,44 +1408,33 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, 
char *ifname)
 
 #ifdef CONFIG_IP_VS_IPV6
 static int join_mcast_group6(struct sock *sk, struct in6_addr *addr,
-char *ifname)
+int ifindex)
 {
-   struct net *net = sock_net(sk);
-   struct net_device *dev;
int ret;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   ret = ipv6_sock_mc_join(sk, dev->ifindex, addr);
+   ret = ipv6_sock_mc_join(sk, ifindex, addr);
release_sock(sk);
 
return ret;
 }
 #endif
 
-static int bind_mcastif_addr(struct socket *sock, char *ifname)
+static int bind_mcastif_addr(struct socket *sock, struct net_device *dev)
 {
-   struct net *net = sock_net(sock->sk);
-   struct net_device *dev;
__be32 addr;
struct sockaddr_in sin;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-
addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
if (!addr)
pr_err("You probably need to specify IP address on "
   "multicast interface.\n");
 
IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
- ifname, );
+ dev->name, );
 
/* Now bind the socket with the address of multicast interface */
sin.sin_family   = AF_INET;
@@ -1489,7 +1467,8 @@ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, 
int *salen,
 /*
  *  Set up sending multicast socket over UDP
  */
-static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id,
+struct net_device *dev)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1503,7 +1482,7 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id)
pr_err("Error during creation of socket; terminating\

[PATCH v4 net] ipvs: fix bind to link-local mcast IPv6 address in backup

2016-06-16 Thread Quentin Armitage
When using HEAD from
https://git.kernel.org/cgit/utils/kernel/ipvsadm/ipvsadm.git/,
the command:
ipvsadm --start-daemon backup --mcast-interface eth0.60 \
--mcast-group ff02::1:81
fails with the error message:
Argument list too long

whereas both:
ipvsadm --start-daemon master --mcast-interface eth0.60 \
--mcast-group ff02::1:81
and:
ipvsadm --start-daemon backup --mcast-interface eth0.60 \
--mcast-group 224.0.0.81
are successful.

The error message "Argument list too long" isn't helpful. The error occurs
because an IPv6 address is given in backup mode.

The error is in make_receive_sock() in net/netfilter/ipvs/ip_vs_sync.c,
since it fails to set the interface on the address or the socket before
calling inet6_bind() (via sock->ops->bind), where the test
'if (!sk->sk_bound_dev_if)' failed.

Setting sock->sk->sk_bound_dev_if on the socket before calling
inet6_bind() resolves the issue.

Fixes: d33288172e72 ("ipvs: add more mcast parameters for the sync daemon")
Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 803001a..1b07578 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1545,7 +1545,8 @@ error:
 /*
  *  Set up receiving multicast socket over UDP
  */
-static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id,
+   int ifindex)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1566,6 +1567,7 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id)
set_sock_size(sock->sk, 0, result);
 
get_mcast_sockaddr(_addr, , >bcfg, id);
+   sock->sk->sk_bound_dev_if = ifindex;
result = sock->ops->bind(sock, (struct sockaddr *)_addr, salen);
if (result < 0) {
pr_err("Error binding to the multicast addr\n");
@@ -1868,7 +1870,7 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct 
ipvs_sync_daemon_cfg *c,
if (state == IP_VS_STATE_MASTER)
sock = make_send_sock(ipvs, id);
else
-   sock = make_receive_sock(ipvs, id);
+   sock = make_receive_sock(ipvs, id, dev->ifindex);
if (IS_ERR(sock)) {
result = PTR_ERR(sock);
goto outtinfo;
-- 
1.7.7.6



[PATCH v3 3/4] ipvs: Don't check result < 0 after setting result = 0

2016-06-15 Thread Quentin Armitage
Move the block testing result < 0 to avoid the test immediately
after setting result = 0

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   11 ++-
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index fbc5ba4..2be99b2 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1496,13 +1496,14 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id,
if (result > 0)
set_sock_size(sock->sk, 1, result);
 
-   if (AF_INET == ipvs->mcfg.mcast_af)
+   if (ipvs->mcfg.mcast_af == AF_INET) {
result = bind_mcastif_addr(sock, dev);
-   else
+   if (result < 0) {
+   pr_err("Error binding address of mcast interface\n");
+   goto error;
+   }
+   } else {
result = 0;
-   if (result < 0) {
-   pr_err("Error binding address of the mcast interface\n");
-   goto error;
}
 
get_mcast_sockaddr(_addr, , >mcfg, id);
-- 
1.7.7.6



[PATCH v3 4/4] ipvs: log additional sync daemon parameters

2016-06-15 Thread Quentin Armitage
Add new multicast parameters to log messages when sync daemons start.

Commit e4ff67513096 ("ipvs: add sync_maxlen parameter for the sync
daemon") and commit d33288172e72 ("ipvs: add more mcast parameters for
the sync daemon") added additional multicast parameters, but didn't add
them to the log messages when the sync daemons started.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   28 ++--
 1 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 2be99b2..a52c4be 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1669,9 +1669,17 @@ static int sync_thread_master(void *data)
struct sock *sk = tinfo->sock->sk;
struct ip_vs_sync_buff *sb;
 
-   pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid, tinfo->id);
+   pr_info("sync thread started: state = MASTER, mcast_ifn = %s, syncid = 
%d, id = %d, maxlen = %d\n",
+   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid,
+   tinfo->id, ipvs->mcfg.sync_maxlen);
+   if (ipvs->mcfg.mcast_af == AF_INET)
+   pr_info("group = %pI4, port = %d, ttl = %d\n",
+   >mcfg.mcast_group.in, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
+   else
+   pr_info("group = %pI6c, port = %d, ttl = %d\n",
+   >mcfg.mcast_group.in6, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
 
for (;;) {
sb = next_sync_buff(ipvs, ms);
@@ -1723,9 +1731,17 @@ static int sync_thread_backup(void *data)
struct netns_ipvs *ipvs = tinfo->ipvs;
int len;
 
-   pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
+   pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, syncid = 
%d, id = %d, maxlen = %d\n",
+   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid,
+   tinfo->id, ipvs->bcfg.sync_maxlen);
+   if (ipvs->bcfg.mcast_af == AF_INET)
+   pr_info("group = %pI4, port = %d, ttl = %d\n",
+   >bcfg.mcast_group.in, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
+   else
+   pr_info("group = %pI6c, port = %d, ttl = %d\n",
+   >bcfg.mcast_group.in6, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
 
while (!kthread_should_stop()) {
wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
-- 
1.7.7.6



[PATCH v3 2/4] ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync daemon

2016-06-15 Thread Quentin Armitage
Optimise starting sync daemons by using the result of the first call to
__dev_get_by_name() and pass the result or ifindex to subsequent functions
to avoid them having to call __dev_get_by_name() again.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   60 +--
 1 files changed, 20 insertions(+), 40 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 1b07578..fbc5ba4 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1356,28 +1356,22 @@ static void set_mcast_pmtudisc(struct sock *sk, int val)
 /*
  *  Specifiy default interface for outgoing multicasts
  */
-static int set_mcast_if(struct sock *sk, char *ifname)
+static int set_mcast_if(struct sock *sk, int ifindex)
 {
-   struct net_device *dev;
struct inet_sock *inet = inet_sk(sk);
-   struct net *net = sock_net(sk);
-
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
 
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   inet->mc_index = dev->ifindex;
+   inet->mc_index = ifindex;
/*  inet->mc_addr  = 0; */
 #ifdef CONFIG_IP_VS_IPV6
if (sk->sk_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
 
/* IPV6_MULTICAST_IF */
-   np->mcast_oif = dev->ifindex;
+   np->mcast_oif = ifindex;
}
 #endif
release_sock(sk);
@@ -1392,23 +1386,18 @@ static int set_mcast_if(struct sock *sk, char *ifname)
  *  in the in_addr structure passed in as a parameter.
  */
 static int
-join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
+join_mcast_group(struct sock *sk, struct in_addr *addr, int ifindex)
 {
-   struct net *net = sock_net(sk);
struct ip_mreqn mreq;
-   struct net_device *dev;
int ret;
 
memset(, 0, sizeof(mreq));
memcpy(_multiaddr, addr, sizeof(struct in_addr));
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
-   mreq.imr_ifindex = dev->ifindex;
+   mreq.imr_ifindex = ifindex;
 
lock_sock(sk);
ret = ip_mc_join_group(sk, );
@@ -1419,44 +1408,33 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, 
char *ifname)
 
 #ifdef CONFIG_IP_VS_IPV6
 static int join_mcast_group6(struct sock *sk, struct in6_addr *addr,
-char *ifname)
+int ifindex)
 {
-   struct net *net = sock_net(sk);
-   struct net_device *dev;
int ret;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   ret = ipv6_sock_mc_join(sk, dev->ifindex, addr);
+   ret = ipv6_sock_mc_join(sk, ifindex, addr);
release_sock(sk);
 
return ret;
 }
 #endif
 
-static int bind_mcastif_addr(struct socket *sock, char *ifname)
+static int bind_mcastif_addr(struct socket *sock, struct net_device *dev)
 {
-   struct net *net = sock_net(sock->sk);
-   struct net_device *dev;
__be32 addr;
struct sockaddr_in sin;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-
addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
if (!addr)
pr_err("You probably need to specify IP address on "
   "multicast interface.\n");
 
IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
- ifname, );
+ dev->name, );
 
/* Now bind the socket with the address of multicast interface */
sin.sin_family   = AF_INET;
@@ -1489,7 +1467,8 @@ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, 
int *salen,
 /*
  *  Set up sending multicast socket over UDP
  */
-static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id,
+struct net_device *dev)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1503,7 +1482,7 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id)
pr_err("Error during creation of socket; terminating\

[PATCH v3 1/4] ipvs: Enable setting IPv6 multicast address for ipvs

2016-06-15 Thread Quentin Armitage
When using HEAD from
https://git.kernel.org/cgit/utils/kernel/ipvsadm/ipvsadm.git/,
the command:
ipvsadm --start-daemon backup --mcast-interface eth0.60 \
--mcast-group ff02::1:81
fails with the error message:
Argument list too long

whereas both:
ipvsadm --start-daemon master --mcast-interface eth0.60 \
--mcast-group ff02::1:81
and:
ipvsadm --start-daemon backup --mcast-interface eth0.60 \
--mcast-group 224.0.0.81
are successful.

The error message "Argument list too long" isn't helpful. The error occurs
because an IPv6 address is given in backup mode.

The error is in make_receive_sock() in net/netfilter/ipvs/ip_vs_sync.c,
since it fails to set the interface on the address or the socket before
calling inet6_bind() (via sock->ops->bind), where the test
'if (!sk->sk_bound_dev_if)' failed.

Setting sock->sk->sk_bound_dev_if on the socket before calling
inet6_bind() resolves the issue.

Fixes: d33288172e72 ("ipvs: add more mcast parameters for the sync daemon")

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 803001a..1b07578 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1545,7 +1545,8 @@ error:
 /*
  *  Set up receiving multicast socket over UDP
  */
-static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id,
+   int ifindex)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1566,6 +1567,7 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id)
set_sock_size(sock->sk, 0, result);
 
get_mcast_sockaddr(_addr, , >bcfg, id);
+   sock->sk->sk_bound_dev_if = ifindex;
result = sock->ops->bind(sock, (struct sockaddr *)_addr, salen);
if (result < 0) {
pr_err("Error binding to the multicast addr\n");
@@ -1868,7 +1870,7 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct 
ipvs_sync_daemon_cfg *c,
if (state == IP_VS_STATE_MASTER)
sock = make_send_sock(ipvs, id);
else
-   sock = make_receive_sock(ipvs, id);
+   sock = make_receive_sock(ipvs, id, dev->ifindex);
if (IS_ERR(sock)) {
result = PTR_ERR(sock);
goto outtinfo;
-- 
1.7.7.6



[PATCH v3 0/4] ipvs: fix backup sync daemon with IPv6, and minor updates

2016-06-15 Thread Quentin Armitage
This series of patches arise from discovering that:
ipvsadm --start-daemon backup --mcast-group IPv6_address ...
would always fail.

The first patch resolves the problem. The second and third patches are
optimizations that were noticed while investigating the original problem.
The fourth patch adds a lock which appears to have been omitted, and the
final patch adds the recently added sync daemon multicast parameters to
the log messages that are written when the sync daemons start.

v2 fixes a compile error in a debug message identified by kbuild test
robot. Now compiles with CONFIG_IP_VS_DEBUG enabled. Patch 2/5 is modified
to correct the problem, and patch 3/5 is modifed to apply with the
modified patch 2/5.

v3 incorporates changes suggested by Julian Anastasov.
Patch 1 now sets 'sock->sk->sk_bound_dev_if = ifindex' rather than setting
sin6_scope_id. Also remove the locks since unnecessary.
Patch 3 shortens the logged message in order not to exceed 80-char limit.
Patch 4 Removed, the locks aren't necessary
Patch 5 No longer changes indentation of existing pr_info. Also removes <>
around commit IDs in commit description.
Patches 1, 2, 3, 5 are updated to resolve coding style warnings, and all
pass with 0 errors, warnings and checks.
Patch 5 now becomes patch 4.

The changes have all been tested and work as expected.

Quentin Armitage (4):
  ipvs: Enable setting IPv6 multicast address for ipvs
  ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync
daemon
  ipvs: Don't check result < 0 after setting result = 0
  ipvs: log additional sync daemon parameters

 net/netfilter/ipvs/ip_vs_sync.c |  105 +++
 1 files changed, 52 insertions(+), 53 deletions(-)

-- 
1.7.7.6



[PATCH v2 1/5] ipvs: Enable setting IPv6 multicast address for ipvs sync daemon backup

2016-06-14 Thread Quentin Armitage
When using HEAD from 
https://git.kernel.org/cgit/utils/kernel/ipvsadm/ipvsadm.git/,
the command:
ipvsadm --start-daemon backup --mcast-interface eth0.60 --mcast-group ff01::1:81
fails with the error message:
Argument list too long

whereas both:
ipvsadm --start-daemon master --mcast-interface eth0.60 --mcast-group ff01::1:81
and:
ipvsadm --start-daemon backup --mcast-interface eth0.60 --mcast-group 224.0.0.81
are successful.

The error message "Argument list too long" isn't helpful. The error occurs
because an IPv6 address is given in backup mode.

The error is in make_receive_sock() in net/netfilter/ipvs/ip_vs_sync.c, since
it fails to set the interface on the address or the socket before calling
inet6_bind() (via sock->ops->bind), where the test 'if (!sk->sk_bound_dev_if)'
failed.

Setting sin6_scope_id on the sockaddr before calling inet6_bind() resolves
the issue.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 803001a..85b48f1 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1545,7 +1545,7 @@ error:
 /*
  *  Set up receiving multicast socket over UDP
  */
-static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id, int 
ifindex)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1566,6 +1566,7 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id)
set_sock_size(sock->sk, 0, result);
 
get_mcast_sockaddr(_addr, , >bcfg, id);
+   ((struct sockaddr_in6 *)_addr)->sin6_scope_id = ifindex;
result = sock->ops->bind(sock, (struct sockaddr *)_addr, salen);
if (result < 0) {
pr_err("Error binding to the multicast addr\n");
@@ -1868,7 +1869,7 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct 
ipvs_sync_daemon_cfg *c,
if (state == IP_VS_STATE_MASTER)
sock = make_send_sock(ipvs, id);
else
-   sock = make_receive_sock(ipvs, id);
+   sock = make_receive_sock(ipvs, id, dev->ifindex);
if (IS_ERR(sock)) {
result = PTR_ERR(sock);
goto outtinfo;
-- 
1.7.7.6



[PATCH v2 0/5] ipvs: fix backup sync daemon with IPv6, and minor updates

2016-06-14 Thread Quentin Armitage
This series of patches arise from discovering that:
ipvsadm --start-daemon backup --mcast-group IPv6_address ...
would always fail.

The first patch resolves the problem. The second and third patches are
optimizations that were noticed while investigating the original problem.
The fourth patch adds a lock which appears to have been omitted, and the
final patch adds the recently added sync daemon multicast parameters to
the log messages that are written when the sync daemons start.

v2 fixes a compile error in a debug message identified by kbuild test robot.
Now compiles with CONFIG_IP_VS_DEBUG enabled. Patch 2/5 is modified to correct
the problem, and patch 3/5 is modifed to apply with the modified patch 2/5.

Quentin Armitage (5):
  ipvs: Enable setting IPv6 multicast address for ipvs sync daemon
backup
  ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync
daemon
  ipvs: Don't check result < 0 after setting result = 0
  ipvs: Lock socket before setting SK_CAN_REUSE
  ipvs: log additional sync daemon parameters

 net/netfilter/ipvs/ip_vs_sync.c |  104 +++---
 1 files changed, 52 insertions(+), 52 deletions(-)

-- 
1.7.7.6



[PATCH v2 4/5] ipvs: Lock socket before setting SK_CAN_REUSE

2016-06-14 Thread Quentin Armitage
When other settings are changed in the socket it is locked, so
lock the socket before setting SK_CAN_REUSE.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 0ca937a..734335a 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1539,7 +1539,9 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id, int ifi
}
 
/* it is equivalent to the REUSEADDR option in user-space */
+   lock_sock(sock->sk);
sock->sk->sk_reuse = SK_CAN_REUSE;
+   release_sock(sock->sk);
result = sysctl_sync_sock_size(ipvs);
if (result > 0)
set_sock_size(sock->sk, 0, result);
-- 
1.7.7.6



[PATCH v2 2/5] ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync daemon

2016-06-14 Thread Quentin Armitage
Optimise starting sync daemons by using the result of the first call to
__dev_get_by_name() and pass the result or ifindex to subsequent functions
to avoid them having to call __dev_get_by_name() again.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   59 --
 1 files changed, 19 insertions(+), 40 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 85b48f1..d52cc25 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1356,28 +1356,22 @@ static void set_mcast_pmtudisc(struct sock *sk, int val)
 /*
  *  Specifiy default interface for outgoing multicasts
  */
-static int set_mcast_if(struct sock *sk, char *ifname)
+static int set_mcast_if(struct sock *sk, int ifindex)
 {
-   struct net_device *dev;
struct inet_sock *inet = inet_sk(sk);
-   struct net *net = sock_net(sk);
-
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
 
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   inet->mc_index = dev->ifindex;
+   inet->mc_index = ifindex;
/*  inet->mc_addr  = 0; */
 #ifdef CONFIG_IP_VS_IPV6
if (sk->sk_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
 
/* IPV6_MULTICAST_IF */
-   np->mcast_oif = dev->ifindex;
+   np->mcast_oif = ifindex;
}
 #endif
release_sock(sk);
@@ -1392,23 +1386,18 @@ static int set_mcast_if(struct sock *sk, char *ifname)
  *  in the in_addr structure passed in as a parameter.
  */
 static int
-join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
+join_mcast_group(struct sock *sk, struct in_addr *addr, int ifindex)
 {
-   struct net *net = sock_net(sk);
struct ip_mreqn mreq;
-   struct net_device *dev;
int ret;
 
memset(, 0, sizeof(mreq));
memcpy(_multiaddr, addr, sizeof(struct in_addr));
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
-   mreq.imr_ifindex = dev->ifindex;
+   mreq.imr_ifindex = ifindex;
 
lock_sock(sk);
ret = ip_mc_join_group(sk, );
@@ -1419,44 +1408,33 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, 
char *ifname)
 
 #ifdef CONFIG_IP_VS_IPV6
 static int join_mcast_group6(struct sock *sk, struct in6_addr *addr,
-char *ifname)
+int ifindex)
 {
-   struct net *net = sock_net(sk);
-   struct net_device *dev;
int ret;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   ret = ipv6_sock_mc_join(sk, dev->ifindex, addr);
+   ret = ipv6_sock_mc_join(sk, ifindex, addr);
release_sock(sk);
 
return ret;
 }
 #endif
 
-static int bind_mcastif_addr(struct socket *sock, char *ifname)
+static int bind_mcastif_addr(struct socket *sock, struct net_device *dev)
 {
-   struct net *net = sock_net(sock->sk);
-   struct net_device *dev;
__be32 addr;
struct sockaddr_in sin;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-
addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
if (!addr)
pr_err("You probably need to specify IP address on "
   "multicast interface.\n");
 
IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
- ifname, );
+ dev->name, );
 
/* Now bind the socket with the address of multicast interface */
sin.sin_family   = AF_INET;
@@ -1489,7 +1467,7 @@ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, 
int *salen,
 /*
  *  Set up sending multicast socket over UDP
  */
-static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id, struct 
net_device *dev)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1503,7 +1481,7 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id)
pr_err("Error during creation of socket; terminating\n");
   

[PATCH v2 3/5] ipvs: Don't check result < 0 after setting result = 0

2016-06-14 Thread Quentin Armitage
Move the block testing result < 0 to avoid the test immediately
after setting result = 0

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   12 ++--
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index d52cc25..0ca937a 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1495,14 +1495,14 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id, struct net
if (result > 0)
set_sock_size(sock->sk, 1, result);
 
-   if (AF_INET == ipvs->mcfg.mcast_af)
+   if (AF_INET == ipvs->mcfg.mcast_af) {
result = bind_mcastif_addr(sock, dev);
-   else
+   if (result < 0) {
+   pr_err("Error binding address of the mcast 
interface\n");
+   goto error;
+   }
+   } else
result = 0;
-   if (result < 0) {
-   pr_err("Error binding address of the mcast interface\n");
-   goto error;
-   }
 
get_mcast_sockaddr(_addr, , >mcfg, id);
result = sock->ops->connect(sock, (struct sockaddr *) _addr,
-- 
1.7.7.6



[PATCH v2 5/5] ipvs: log additional sync daemon parameters

2016-06-14 Thread Quentin Armitage
Add new multicast parameters to log messages when sync daemons start.

Commits  ("ipvs: add sync_maxlen parameter for the sync
daemon") and  ("ipvs: add more mcast parameters for the
sync daemon") added additional multicast parameters, but didn't add
them to the log messages when the sync daemons started.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   26 ++
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 734335a..bb59b84 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1669,8 +1669,17 @@ static int sync_thread_master(void *data)
struct ip_vs_sync_buff *sb;
 
pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid, tinfo->id);
+   "syncid = %d, id = %d, maxlen = %d\n",
+   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid,
+   tinfo->id, ipvs->mcfg.sync_maxlen);
+   if (ipvs->mcfg.mcast_af == AF_INET)
+   pr_info("   : group = %pI4, port = %d, ttl = 
%d\n",
+   >mcfg.mcast_group.in, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
+   else
+   pr_info("   : group = %pI6c, port = %d, ttl = 
%d\n",
+   >mcfg.mcast_group.in6, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
 
for (;;) {
sb = next_sync_buff(ipvs, ms);
@@ -1723,8 +1732,17 @@ static int sync_thread_backup(void *data)
int len;
 
pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
+   "syncid = %d, id = %d, maxlen = %d\n",
+   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid,
+   tinfo->id, ipvs->bcfg.sync_maxlen);
+   if (ipvs->bcfg.mcast_af == AF_INET)
+   pr_info("   : group = %pI4, port = %d, ttl = 
%d\n",
+   >bcfg.mcast_group.in, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
+   else
+   pr_info("   : group = %pI6c, port = %d, ttl = 
%d\n",
+   >bcfg.mcast_group.in6, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
 
while (!kthread_should_stop()) {
wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
-- 
1.7.7.6



[PATCH 0/5] ipvs: fix backup sync daemon with IPv6, and minor updates

2016-06-13 Thread Quentin Armitage
This series of patches arise from discovering that:
ipvsadm --start-daemon backup --mcast-group IPv6_address ...
would always fail.

The first patch resolves the problem. The second and third patches are
optimizations that were noticed while investigating the original problem.
The fourth patch adds a lock which appears to have been omitted, and the
final patch adds the recently added sync daemon multicast parameters to
the log messages that are written when the sync daemons start.

Quentin Armitage (5):
  ipvs: Enable setting IPv6 multicast address for ipvs sync daemon
backup
  ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync
daemon
  ipvs: Don't check result < 0 after setting result = 0
  ipvs: Lock socket before setting SK_CAN_REUSE
  ipvs: log additional sync daemon parameters

 net/netfilter/ipvs/ip_vs_sync.c |  107 ---
 1 files changed, 54 insertions(+), 53 deletions(-)

-- 
1.7.7.6



[PATCH 5/5] ipvs: log additional sync daemon parameters

2016-06-13 Thread Quentin Armitage
Add new multicast parameters to log messages when sync daemons start.

Commits  ("ipvs: add sync_maxlen parameter for the sync
daemon") and  ("ipvs: add more mcast parameters for the
sync daemon") added additional multicast parameters, but didn't add
them to the log messages when the sync daemons started.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   26 ++
 1 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index dfac9ef..e5f6739 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1670,8 +1670,17 @@ static int sync_thread_master(void *data)
struct ip_vs_sync_buff *sb;
 
pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid, tinfo->id);
+   "syncid = %d, id = %d, maxlen = %d\n",
+   ipvs->mcfg.mcast_ifn, ipvs->mcfg.syncid,
+   tinfo->id, ipvs->mcfg.sync_maxlen);
+   if (ipvs->mcfg.mcast_af == AF_INET)
+   pr_info("   : group = %pI4, port = %d, ttl = 
%d\n",
+   >mcfg.mcast_group.in, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
+   else
+   pr_info("   : group = %pI6c, port = %d, ttl = 
%d\n",
+   >mcfg.mcast_group.in6, ipvs->mcfg.mcast_port,
+   ipvs->mcfg.mcast_ttl);
 
for (;;) {
sb = next_sync_buff(ipvs, ms);
@@ -1724,8 +1733,17 @@ static int sync_thread_backup(void *data)
int len;
 
pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
-   "syncid = %d, id = %d\n",
-   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id);
+   "syncid = %d, id = %d, maxlen = %d\n",
+   ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid,
+   tinfo->id, ipvs->bcfg.sync_maxlen);
+   if (ipvs->bcfg.mcast_af == AF_INET)
+   pr_info("   : group = %pI4, port = %d, ttl = 
%d\n",
+   >bcfg.mcast_group.in, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
+   else
+   pr_info("   : group = %pI6c, port = %d, ttl = 
%d\n",
+   >bcfg.mcast_group.in6, ipvs->bcfg.mcast_port,
+   ipvs->bcfg.mcast_ttl);
 
while (!kthread_should_stop()) {
wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
-- 
1.7.7.6



[PATCH 3/5] ipvs: Don't check result < 0 after setting result = 0

2016-06-13 Thread Quentin Armitage
Move the block testing result < 0 to avoid the test immediately
after setting result = 0

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 3181fd0..29d73d8 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1497,13 +1497,13 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id, struct net
  ipvs->mcast_ifn, );
 
result = bind_mcastif_addr(sock, dev);
+   if (result < 0) {
+   pr_err("Error binding address of the mcast 
interface\n");
+   goto error;
+   }
}
else
result = 0;
-   if (result < 0) {
-   pr_err("Error binding address of the mcast interface\n");
-   goto error;
-   }
 
get_mcast_sockaddr(_addr, , >mcfg, id);
result = sock->ops->connect(sock, (struct sockaddr *) _addr,
-- 
1.7.7.6



[PATCH 4/5] ipvs: Lock socket before setting SK_CAN_REUSE

2016-06-13 Thread Quentin Armitage
When other settings are changed in the socket it is locked, so
lock the socket before setting SK_CAN_REUSE.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 29d73d8..dfac9ef 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1540,7 +1540,9 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id, int ifi
}
 
/* it is equivalent to the REUSEADDR option in user-space */
+   lock_sock(sock->sk);
sock->sk->sk_reuse = SK_CAN_REUSE;
+   release_sock(sock->sk);
result = sysctl_sync_sock_size(ipvs);
if (result > 0)
set_sock_size(sock->sk, 0, result);
-- 
1.7.7.6



[PATCH 2/5] ipvs: Stop calling __dev_get_by_name() repeatedly when starting sync daemon

2016-06-13 Thread Quentin Armitage
Optimise starting sync daemons by using the result of the first call to
__dev_get_by_name() and pass the result or ifindex to subsequent functions
to avoid them having to call __dev_get_by_name() again.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |   66 +-
 1 files changed, 23 insertions(+), 43 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 85b48f1..3181fd0 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1356,28 +1356,22 @@ static void set_mcast_pmtudisc(struct sock *sk, int val)
 /*
  *  Specifiy default interface for outgoing multicasts
  */
-static int set_mcast_if(struct sock *sk, char *ifname)
+static int set_mcast_if(struct sock *sk, int ifindex)
 {
-   struct net_device *dev;
struct inet_sock *inet = inet_sk(sk);
-   struct net *net = sock_net(sk);
-
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
 
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   inet->mc_index = dev->ifindex;
+   inet->mc_index = ifindex;
/*  inet->mc_addr  = 0; */
 #ifdef CONFIG_IP_VS_IPV6
if (sk->sk_family == AF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
 
/* IPV6_MULTICAST_IF */
-   np->mcast_oif = dev->ifindex;
+   np->mcast_oif = ifindex;
}
 #endif
release_sock(sk);
@@ -1392,23 +1386,18 @@ static int set_mcast_if(struct sock *sk, char *ifname)
  *  in the in_addr structure passed in as a parameter.
  */
 static int
-join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
+join_mcast_group(struct sock *sk, struct in_addr *addr, int ifindex)
 {
-   struct net *net = sock_net(sk);
struct ip_mreqn mreq;
-   struct net_device *dev;
int ret;
 
memset(, 0, sizeof(mreq));
memcpy(_multiaddr, addr, sizeof(struct in_addr));
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
-   mreq.imr_ifindex = dev->ifindex;
+   mreq.imr_ifindex = ifindex;
 
lock_sock(sk);
ret = ip_mc_join_group(sk, );
@@ -1419,45 +1408,31 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, 
char *ifname)
 
 #ifdef CONFIG_IP_VS_IPV6
 static int join_mcast_group6(struct sock *sk, struct in6_addr *addr,
-char *ifname)
+int ifindex)
 {
-   struct net *net = sock_net(sk);
-   struct net_device *dev;
int ret;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-   if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
+   if (sk->sk_bound_dev_if && ifindex != sk->sk_bound_dev_if)
return -EINVAL;
 
lock_sock(sk);
-   ret = ipv6_sock_mc_join(sk, dev->ifindex, addr);
+   ret = ipv6_sock_mc_join(sk, ifindex, addr);
release_sock(sk);
 
return ret;
 }
 #endif
 
-static int bind_mcastif_addr(struct socket *sock, char *ifname)
+static int bind_mcastif_addr(struct socket *sock, struct net_device *dev)
 {
-   struct net *net = sock_net(sock->sk);
-   struct net_device *dev;
__be32 addr;
struct sockaddr_in sin;
 
-   dev = __dev_get_by_name(net, ifname);
-   if (!dev)
-   return -ENODEV;
-
addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
if (!addr)
pr_err("You probably need to specify IP address on "
   "multicast interface.\n");
 
-   IP_VS_DBG(7, "binding socket with (%s) %pI4\n",
- ifname, );
-
/* Now bind the socket with the address of multicast interface */
sin.sin_family   = AF_INET;
sin.sin_addr.s_addr  = addr;
@@ -1489,7 +1464,7 @@ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, 
int *salen,
 /*
  *  Set up sending multicast socket over UDP
  */
-static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_send_sock(struct netns_ipvs *ipvs, int id, struct 
net_device *dev)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1503,7 +1478,7 @@ static struct socket *make_send_sock(struct netns_ipvs 
*ipvs, int id)
pr_err("Error during creation of socket; terminating\n");
re

[PATCH 1/5] ipvs: Enable setting IPv6 multicast address for ipvs sync daemon backup

2016-06-13 Thread Quentin Armitage
When using HEAD from 
https://git.kernel.org/cgit/utils/kernel/ipvsadm/ipvsadm.git/,
the command:
ipvsadm --start-daemon backup --mcast-interface eth0.60 --mcast-group ff01::1:81
fails with the error message:
Argument list too long

whereas both:
ipvsadm --start-daemon master --mcast-interface eth0.60 --mcast-group ff01::1:81
and:
ipvsadm --start-daemon backup --mcast-interface eth0.60 --mcast-group 224.0.0.81
are successful.

The error message "Argument list too long" isn't helpful. The error occurs
because an IPv6 address is given in backup mode.

The error is in make_receive_sock() in net/netfilter/ipvs/ip_vs_sync.c, since
it fails to set the interface on the address or the socket before calling
inet6_bind() (via sock->ops->bind), where the test 'if (!sk->sk_bound_dev_if)'
failed.

Setting sin6_scope_id on the sockaddr before calling inet6_bind() resolves
the issue.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/netfilter/ipvs/ip_vs_sync.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 803001a..85b48f1 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1545,7 +1545,7 @@ error:
 /*
  *  Set up receiving multicast socket over UDP
  */
-static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id)
+static struct socket *make_receive_sock(struct netns_ipvs *ipvs, int id, int 
ifindex)
 {
/* multicast addr */
union ipvs_sockaddr mcast_addr;
@@ -1566,6 +1566,7 @@ static struct socket *make_receive_sock(struct netns_ipvs 
*ipvs, int id)
set_sock_size(sock->sk, 0, result);
 
get_mcast_sockaddr(_addr, , >bcfg, id);
+   ((struct sockaddr_in6 *)_addr)->sin6_scope_id = ifindex;
result = sock->ops->bind(sock, (struct sockaddr *)_addr, salen);
if (result < 0) {
pr_err("Error binding to the multicast addr\n");
@@ -1868,7 +1869,7 @@ int start_sync_thread(struct netns_ipvs *ipvs, struct 
ipvs_sync_daemon_cfg *c,
if (state == IP_VS_STATE_MASTER)
sock = make_send_sock(ipvs, id);
else
-   sock = make_receive_sock(ipvs, id);
+   sock = make_receive_sock(ipvs, id, dev->ifindex);
if (IS_ERR(sock)) {
result = PTR_ERR(sock);
goto outtinfo;
-- 
1.7.7.6



[PATCH v2] net: remove unimplemented RTNH_F_PERVASIVE

2016-04-02 Thread Quentin Armitage
Linux 2.1.68 introduced RTNH_F_PERVASIVE, but it had no implementation
and couldn't be enabled since the required config parameter wasn't in
any Kconfig file (see commit d088dde7b196 ("ipv4: obsolete config in
kernel source (IP_ROUTE_PERVASIVE)")).

This commit removes all remaining references to RTNH_F_PERVASIVE.
Although this will cause userspace applications that were using the
flag to fail to build, they will be alerted to the fact that using
RTNH_F_PERVASIVE was not achieving anything.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 include/uapi/linux/rtnetlink.h |2 +-
 net/decnet/dn_fib.c|2 +-
 net/ipv4/fib_semantics.c   |2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index ca764b5..58e6ba0 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -339,7 +339,7 @@ struct rtnexthop {
 /* rtnh_flags */
 
 #define RTNH_F_DEAD1   /* Nexthop is dead (used by multipath)  
*/
-#define RTNH_F_PERVASIVE   2   /* Do recursive gateway lookup  */
+   /* 2 was RTNH_F_PERVASIVE (never 
implemented) */
 #define RTNH_F_ONLINK  4   /* Gateway is forced on link*/
 #define RTNH_F_OFFLOAD 8   /* offloaded route */
 #define RTNH_F_LINKDOWN16  /* carrier-down on nexthop */
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index df48034..c53aa74 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -243,7 +243,7 @@ out:
} else {
struct net_device *dev;
 
-   if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+   if (nh->nh_flags & RTNH_F_ONLINK)
return -EINVAL;
 
dev = __dev_get_by_index(_net, nh->nh_oif);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index d97268e..3883860 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -803,7 +803,7 @@ static int fib_check_nh(struct fib_config *cfg, struct 
fib_info *fi,
} else {
struct in_device *in_dev;
 
-   if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK))
+   if (nh->nh_flags & RTNH_F_ONLINK)
return -EINVAL;
 
rcu_read_lock();
-- 
1.7.7.6



[PATCH] net: remove unimplemented RTNH_F_PERVASIVE

2016-04-02 Thread Quentin Armitage
Linux 2.1.68 introduced RTNH_F_PERVASIVE, but it had no implementation
and couldn't be enabled since the required config parameter wasn't in
any Kconfig file (see commit d088dde7b).

This commit removes all remaining references to RTNH_F_PERVASIVE.
Although this will cause userspace applications that were using the
flag to fail to build, they will be alerted to the fact that using
RTNH_F_PERVASIVE was not achieving anything.

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 include/uapi/linux/rtnetlink.h |2 +-
 net/decnet/dn_fib.c|2 +-
 net/ipv4/fib_semantics.c   |2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index ca764b5..58e6ba0 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -339,7 +339,7 @@ struct rtnexthop {
 /* rtnh_flags */
 
 #define RTNH_F_DEAD1   /* Nexthop is dead (used by multipath)  
*/
-#define RTNH_F_PERVASIVE   2   /* Do recursive gateway lookup  */
+   /* 2 was RTNH_F_PERVASIVE (never 
implemented) */
 #define RTNH_F_ONLINK  4   /* Gateway is forced on link*/
 #define RTNH_F_OFFLOAD 8   /* offloaded route */
 #define RTNH_F_LINKDOWN16  /* carrier-down on nexthop */
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index df48034..f5660c6 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -243,7 +243,7 @@ out:
} else {
struct net_device *dev;
 
-   if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+   if (nh->nh_flags_F_ONLINK)
return -EINVAL;
 
dev = __dev_get_by_index(_net, nh->nh_oif);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index d97268e..3883860 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -803,7 +803,7 @@ static int fib_check_nh(struct fib_config *cfg, struct 
fib_info *fi,
} else {
struct in_device *in_dev;
 
-   if (nh->nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK))
+   if (nh->nh_flags & RTNH_F_ONLINK)
return -EINVAL;
 
rcu_read_lock();
-- 
1.7.7.6



[PATCH] Fix returned tc and hoplimit values for route with IPv6 encapsulation

2016-03-27 Thread Quentin Armitage
For a route with IPv6 encapsulation, the traffic class and hop limit
values are interchanged when returned to userspace by the kernel.
For example, see below.

># ip route add 192.168.0.1 dev eth0.2 encap ip6 dst 0x50 tc 0x50 hoplimit 100 
>table 1000
># ip route show table 1000
192.168.0.1  encap ip6 id 0 src :: dst fe83::1 hoplimit 80 tc 100 dev eth0.2  
scope link

Signed-off-by: Quentin Armitage <quen...@armitage.org.uk>
---
 net/ipv4/ip_tunnel_core.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 02dd990..6165f30 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -372,8 +372,8 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb,
if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) ||
nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, _info->key.u.ipv6.dst) 
||
nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, _info->key.u.ipv6.src) 
||
-   nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.tos) ||
-   nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.ttl) ||
+   nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.tos) ||
+   nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.ttl) ||
nla_put_be16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags))
return -ENOMEM;
 
-- 
1.7.7.6