* [RFC PATCH net-next 4/5] netns: advertise netns activity with netlink
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355332630-4256-1-git-send-email-nicolas.dichtel@6wind.com>
Goal of this patch is to send netlink messages when netns are crated/deleted.
This is useful for daemon that wants to manage all netns with only one running
instance.
Note that until that netns_nl_event_mcgrp group is not registered, we cannot
send event.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/netns.h | 4 ++++
net/core/net_namespace.c | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/netns.h b/include/uapi/linux/netns.h
index e1c1da3..e14d90b 100644
--- a/include/uapi/linux/netns.h
+++ b/include/uapi/linux/netns.h
@@ -6,10 +6,14 @@
#define NETNS_GENL_NAME "netns"
#define NETNS_GENL_VERSION 0x1
+#define NETNS_GENL_MCAST_EVENT_NAME "events"
+
/* Commands */
enum {
NETNS_CMD_NOOP,
NETNS_CMD_GET,
+ NETNS_CMD_NEW,
+ NETNS_CMD_DEL,
__NETNS_CMD_MAX,
};
#define NETNS_CMD_MAX (__NETNS_CMD_MAX - 1)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 18fc62f..da92ecb 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -40,6 +40,8 @@ EXPORT_SYMBOL(init_net);
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+static int netns_nl_event(struct net *net, int cmd);
+
static struct net_generic *net_alloc_generic(void)
{
struct net_generic *ng;
@@ -179,6 +181,7 @@ again:
if (error < 0)
goto out_undo;
}
+ netns_nl_event(net, NETNS_CMD_NEW);
out:
return error;
@@ -311,6 +314,7 @@ static void cleanup_net(struct work_struct *work)
synchronize_rcu();
list_for_each_entry(net, &net_exit_list, exit_list) {
+ netns_nl_event(net, NETNS_CMD_DEL);
/* Free the index */
ida_remove(&net_namespace_ids, net->nsindex);
}
@@ -413,6 +417,10 @@ struct net *get_net_ns_by_nsindex(int nsindex)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_nsindex);
+static struct genl_multicast_group netns_nl_event_mcgrp = {
+ .name = NETNS_GENL_MCAST_EVENT_NAME,
+};
+
static struct genl_family netns_nl_family = {
.id = GENL_ID_GENERATE,
.name = NETNS_GENL_NAME,
@@ -562,10 +570,38 @@ static struct genl_ops netns_nl_ops[] = {
},
};
+static int netns_nl_event(struct net *net, int cmd)
+{
+ struct sk_buff *msg;
+ int err = -ENOBUFS;
+
+ /* Check that gennl infra is ready */
+ if (!netns_nl_event_mcgrp.id)
+ return -ENOENT;
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_ATOMIC);
+ if (!msg)
+ return -ENOMEM;
+
+ err = netns_nl_fill(msg, 0, 0, 0, cmd, net);
+ if (err < 0) {
+ nlmsg_free(msg);
+ return err;
+ }
+
+ return genlmsg_multicast(msg, 0, netns_nl_event_mcgrp.id, GFP_ATOMIC);
+}
+
int netns_genl_register(void)
{
- return genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
+ int err;
+
+ err = genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
ARRAY_SIZE(netns_nl_ops));
+ if (err < 0)
+ return err;
+
+ return genl_register_mc_group(&netns_nl_family, &netns_nl_event_mcgrp);
}
static int __init net_ns_init(void)
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 5/5] net/sock: add support of SO_NETNS
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355332630-4256-1-git-send-email-nicolas.dichtel@6wind.com>
This new setsockopt() option allows user to change netns of a socket. It
should be done enough early, before any bind(), etc.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
arch/alpha/include/asm/socket.h | 2 ++
arch/avr32/include/uapi/asm/socket.h | 2 ++
arch/frv/include/uapi/asm/socket.h | 2 ++
arch/h8300/include/asm/socket.h | 2 ++
arch/ia64/include/uapi/asm/socket.h | 2 ++
arch/m32r/include/asm/socket.h | 2 ++
arch/m68k/include/uapi/asm/socket.h | 2 ++
arch/mips/include/uapi/asm/socket.h | 2 ++
arch/mn10300/include/uapi/asm/socket.h | 2 ++
arch/parisc/include/uapi/asm/socket.h | 2 ++
arch/powerpc/include/uapi/asm/socket.h | 2 ++
arch/s390/include/uapi/asm/socket.h | 2 ++
arch/sparc/include/uapi/asm/socket.h | 2 ++
arch/xtensa/include/uapi/asm/socket.h | 2 ++
include/uapi/asm-generic/socket.h | 2 ++
net/core/sock.c | 28 ++++++++++++++++++++++++++++
16 files changed, 58 insertions(+)
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 0087d05..13aa509 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -77,6 +77,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#ifdef __KERNEL__
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 486df68..39cc927 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 871f89b..ac7eef6 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -70,5 +70,7 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index 90a2e57..4d2a4e8 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 23d6759..ed4534b 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -79,4 +79,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index 5e7088a..37d0eb0 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
index 285da3b..e79aad8 100644
--- a/arch/m68k/include/uapi/asm/socket.h
+++ b/arch/m68k/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 17307ab..356f943 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -90,5 +90,7 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index af5366b..b899cf8 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index d9ff473..8503329 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -69,6 +69,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 0x4024
+#define SO_NETNS 0x4025
+
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index eb0b186..1a520ff 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -77,4 +77,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 436d07c..cbdda59 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -76,4 +76,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index c83a937..c1c2853 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -66,6 +66,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 0x0027
+#define SO_NETNS 0x0028
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 38079be..a8f956d 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -81,4 +81,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 2d32d07..08c108c 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -73,4 +73,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/sock.c b/net/core/sock.c
index a692ef4..7ec288f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -895,6 +895,30 @@ set_rcvbuf:
sock_valbool_flag(sk, SOCK_NOFCS, valbool);
break;
+ case SO_NETNS:
+#ifdef CONFIG_NET_NS
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ ret = -EPERM;
+ else if (sk->sk_state != TCP_CLOSE)
+ ret = -EBUSY; /* Too late to change netns */
+ else {
+ struct net *net = get_net_ns_by_nsindex(val);
+
+ if (net) {
+ /* We can not use sk_change_net() because sk
+ * will not be released with
+ * sk_release_kernel(). Let do it manually.
+ */
+ put_net(sock_net(sk));
+ sock_net_set(sk, net);
+ } else
+ ret = -EINVAL;
+ }
+#else
+ ret = -EOPNOTSUPP;
+#endif
+ break;
+
default:
ret = -ENOPROTOOPT;
break;
@@ -1140,6 +1164,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
goto lenout;
+ case SO_NETNS:
+ v.val = sock_net(sk)->nsindex;
+ break;
+
default:
return -ENOPROTOOPT;
}
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 2/5] netns: allow to dump netns with netlink
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355332630-4256-1-git-send-email-nicolas.dichtel@6wind.com>
This patch adds the basic support of netlink for netns. The user can dump all
existing netns and get associated nsindex.
He also can get nsindex associated to a pid or fd.
To initialize genetlink family for netns, there is a problem of chicken and
eggs. genetlink init is done after init_net is created, hence when init_net is
created, we cannot call genl_register_family_with_ops(). It's why I put the
init part in genetlink module.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
include/uapi/linux/netns.h | 27 ++++++++
net/core/net_namespace.c | 157 ++++++++++++++++++++++++++++++++++++++++++++
net/netlink/genetlink.c | 4 ++
4 files changed, 189 insertions(+)
create mode 100644 include/uapi/linux/netns.h
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 5db7a1b..c373f2e 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -306,6 +306,7 @@ extern int register_pernet_subsys(struct pernet_operations *);
extern void unregister_pernet_subsys(struct pernet_operations *);
extern int register_pernet_device(struct pernet_operations *);
extern void unregister_pernet_device(struct pernet_operations *);
+extern int netns_genl_register(void);
struct ctl_table;
struct ctl_table_header;
diff --git a/include/uapi/linux/netns.h b/include/uapi/linux/netns.h
new file mode 100644
index 0000000..e1c1da3
--- /dev/null
+++ b/include/uapi/linux/netns.h
@@ -0,0 +1,27 @@
+#ifndef _UAPI_LINUX_NETNS_H_
+#define _UAPI_LINUX_NETNS_H_
+
+/* Generic netlink messages */
+
+#define NETNS_GENL_NAME "netns"
+#define NETNS_GENL_VERSION 0x1
+
+/* Commands */
+enum {
+ NETNS_CMD_NOOP,
+ NETNS_CMD_GET,
+ __NETNS_CMD_MAX,
+};
+#define NETNS_CMD_MAX (__NETNS_CMD_MAX - 1)
+
+/* Attributes */
+enum {
+ NETNSA_NONE,
+ NETNSA_NSINDEX,
+ NETNSA_PID,
+ NETNSA_FD,
+ __NETNSA_MAX,
+};
+#define NETNSA_MAX (__NETNSA_MAX - 1)
+
+#endif /* _UAPI_LINUX_NETNS_H_ */
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f5267e4..2ae22b0 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -14,6 +14,8 @@
#include <linux/file.h>
#include <linux/export.h>
#include <linux/user_namespace.h>
+#include <linux/netns.h>
+#include <net/genetlink.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -397,6 +399,161 @@ struct net *get_net_ns_by_pid(pid_t pid)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+static struct genl_family netns_nl_family = {
+ .id = GENL_ID_GENERATE,
+ .name = NETNS_GENL_NAME,
+ .version = NETNS_GENL_VERSION,
+ .hdrsize = 0,
+ .maxattr = NETNSA_MAX,
+ .netnsok = true,
+};
+
+static struct nla_policy netns_nl_policy[NETNSA_MAX + 1] = {
+ [NETNSA_NONE] = { .type = NLA_UNSPEC, },
+ [NETNSA_NSINDEX] = { .type = NLA_U32, },
+ [NETNSA_PID] = { .type = NLA_U32 },
+ [NETNSA_FD] = { .type = NLA_U32 },
+};
+
+static int netns_nl_get_size(void)
+{
+ return nla_total_size(sizeof(u32)) /* NETNSA_NSINDEX */
+ ;
+}
+
+static int netns_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sk_buff *msg;
+ void *hdr;
+ int ret = -ENOBUFS;
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_KERNEL);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &netns_nl_family, 0, NETNS_CMD_NOOP);
+ if (!hdr) {
+ ret = -EMSGSIZE;
+ goto err_out;
+ }
+
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+
+err_out:
+ nlmsg_free(msg);
+
+out:
+ return ret;
+}
+
+static int netns_nl_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
+ int cmd, struct net *net)
+{
+ void *hdr;
+
+ hdr = genlmsg_put(skb, portid, seq, &netns_nl_family, flags, cmd);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(skb, NETNSA_NSINDEX, net->nsindex))
+ goto nla_put_failure;
+
+ return genlmsg_end(skb, hdr);
+
+nla_put_failure:
+ genlmsg_cancel(skb, hdr);
+ return -EMSGSIZE;
+}
+
+static int netns_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct sk_buff *msg;
+ int err = -ENOBUFS;
+
+ if (info->attrs[NETNSA_PID])
+ net = get_net_ns_by_pid(nla_get_u32(info->attrs[NETNSA_PID]));
+ else if (info->attrs[NETNSA_FD])
+ net = get_net_ns_by_fd(nla_get_u32(info->attrs[NETNSA_FD]));
+ else
+ get_net(net);
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_KERNEL);
+ if (!msg) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = netns_nl_fill(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, NETNS_CMD_GET, net);
+ if (err < 0)
+ goto err_out;
+
+ err = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+ goto out;
+
+err_out:
+ nlmsg_free(msg);
+
+out:
+ put_net(net);
+ return err;
+}
+
+static int netns_nl_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int i = 0, s_i = cb->args[0];
+ struct net *net;
+
+ rtnl_lock();
+ for_each_net(net) {
+ if (i < s_i) {
+ i++;
+ continue;
+ }
+
+ if (netns_nl_fill(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ NETNS_CMD_GET, net) <= 0)
+ goto out;
+
+ i++;
+ }
+
+out:
+ cb->args[0] = i;
+ rtnl_unlock();
+
+ return skb->len;
+}
+
+static struct genl_ops netns_nl_ops[] = {
+ {
+ .cmd = NETNS_CMD_NOOP,
+ .policy = netns_nl_policy,
+ .doit = netns_nl_cmd_noop,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NETNS_CMD_GET,
+ .policy = netns_nl_policy,
+ .doit = netns_nl_cmd_get,
+ .dumpit = netns_nl_cmd_dump,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+int netns_genl_register(void)
+{
+ return genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
+ ARRAY_SIZE(netns_nl_ops));
+}
+
static int __init net_ns_init(void)
{
struct net_generic *ng;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f2aabb6..6d25ddb 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -963,6 +963,10 @@ static int __init genl_init(void)
if (err < 0)
goto problem;
+ err = netns_genl_register();
+ if (err < 0)
+ goto problem;
+
return 0;
problem:
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 3/5] dev/netns: allow to get netns from nsindex in rtnl msg
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355332630-4256-1-git-send-email-nicolas.dichtel@6wind.com>
This patch allows to move a netdevice to another netns by giving the nsindex.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/core/net_namespace.c | 14 ++++++++++++++
net/core/rtnetlink.c | 7 ++++++-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index c373f2e..68e7a36 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -151,6 +151,7 @@ extern struct list_head net_namespace_list;
extern struct net *get_net_ns_by_pid(pid_t pid);
extern struct net *get_net_ns_by_fd(int pid);
+extern struct net *get_net_ns_by_nsindex(int nsindex);
#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 60f3b6b..6720a47 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -142,6 +142,7 @@ enum {
#define IFLA_PROMISCUITY IFLA_PROMISCUITY
IFLA_NUM_TX_QUEUES,
IFLA_NUM_RX_QUEUES,
+ IFLA_NET_NS_INDEX,
__IFLA_MAX
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2ae22b0..18fc62f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -399,6 +399,20 @@ struct net *get_net_ns_by_pid(pid_t pid)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+struct net *get_net_ns_by_nsindex(int nsindex)
+{
+ struct net *net;
+
+ ASSERT_RTNL();
+ for_each_net(net)
+ if (net->nsindex == nsindex) {
+ get_net(net);
+ break;
+ }
+ return net;
+}
+EXPORT_SYMBOL_GPL(get_net_ns_by_nsindex);
+
static struct genl_family netns_nl_family = {
.id = GENL_ID_GENERATE,
.name = NETNS_GENL_NAME,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1868625..e22954a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1115,6 +1115,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_LINKINFO] = { .type = NLA_NESTED },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
[IFLA_NET_NS_FD] = { .type = NLA_U32 },
+ [IFLA_NET_NS_INDEX] = { .type = NLA_U32 },
[IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
[IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
[IFLA_VF_PORTS] = { .type = NLA_NESTED },
@@ -1171,6 +1172,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
else if (tb[IFLA_NET_NS_FD])
net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
+ else if (tb[IFLA_NET_NS_INDEX])
+ net = get_net_ns_by_nsindex(nla_get_u32(tb[IFLA_NET_NS_INDEX]));
else
net = get_net(src_net);
return net;
@@ -1310,7 +1313,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
int send_addr_notify = 0;
int err;
- if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
+ if (tb[IFLA_NET_NS_PID] ||
+ tb[IFLA_NET_NS_FD] ||
+ tb[IFLA_NET_NS_INDEX]) {
struct net *net = rtnl_link_get_net(dev_net(dev), tb);
if (IS_ERR(net)) {
err = PTR_ERR(net);
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 0/5] Ease netns management for userland
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka
The goal of this serie is to ease netns management by daemons. Some systems use
netns only to virtualize network stack and don't want to multiply userland
daemons. These system may have a lot of netns, up to 2000. We don't want to
launch an instance of each daemons (quagga, strongswan, conntrackd, ...) for
each netns because it will consume a lot of ressources. Having one daemon that
manage all netns is more efficient (mainly if there are few objects to manage:
one or two routes per netns for example).
Hence, one goal of this serie is to allow, for a daemon, to monitor netns
activities, thus it can open or close netlink sockets, allocating structures
needed to manage these netns when they are created or deleted.
To help to identify a netns, an index has been added to each netns.
A new setsockopt() option is also added, to help daemons to open socket in the
right netns. For now, a daemon that want to open a socket in a specified netns,
need to call setns(CLONE_NEWNET) with a fd (not so easy to found), open the
socket and then call again setns() to go back in the initial netns. Having this
kind of setsockopt() will simplify operations. Obviously, this setsockopt()
should be done enough early (is test on sk_state enough?). The first target is
netlink socket but it can be useful for other kind of socket, it's why a add a
generic socket option.
As usual, the patch against iproute2 will be sent once the patches are included
and net-next merged. I can send it on demand.
arch/alpha/include/asm/socket.h | 2 +
arch/avr32/include/uapi/asm/socket.h | 2 +
arch/frv/include/uapi/asm/socket.h | 2 +
arch/h8300/include/asm/socket.h | 2 +
arch/ia64/include/uapi/asm/socket.h | 2 +
arch/m32r/include/asm/socket.h | 2 +
arch/m68k/include/uapi/asm/socket.h | 2 +
arch/mips/include/uapi/asm/socket.h | 2 +
arch/mn10300/include/uapi/asm/socket.h | 2 +
arch/parisc/include/uapi/asm/socket.h | 2 +
arch/powerpc/include/uapi/asm/socket.h | 2 +
arch/s390/include/uapi/asm/socket.h | 2 +
arch/sparc/include/uapi/asm/socket.h | 2 +
arch/xtensa/include/uapi/asm/socket.h | 2 +
include/net/net_namespace.h | 3 +
include/uapi/asm-generic/socket.h | 2 +
include/uapi/linux/if_link.h | 1 +
include/uapi/linux/netns.h | 31 +++++
net/core/net_namespace.c | 223 +++++++++++++++++++++++++++++++++
net/core/rtnetlink.c | 7 +-
net/core/sock.c | 28 +++++
net/netlink/genetlink.c | 4 +
22 files changed, 326 insertions(+), 1 deletion(-)
I do not pretend to be a netns expert, it's why I add RFC in the title ;-)
Comments are welcome.
Regards,
Nicolas
^ permalink raw reply
* [RFC PATCH net-next 1/5] netns: allocate an unique id to identify a netns
From: Nicolas Dichtel @ 2012-12-12 17:17 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355332630-4256-1-git-send-email-nicolas.dichtel@6wind.com>
This patch simply adds a field nsindex, which will contain a unique index.
The goal is to prepare the monitoring of netns activities with rtnelink and to
ease netns management by userland apps.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
net/core/net_namespace.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index c5a43f5..5db7a1b 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -55,6 +55,7 @@ struct net {
struct list_head exit_list; /* Use only net_mutex */
struct user_namespace *user_ns; /* Owning user namespace */
+ int nsindex; /* index to identify this ns */
struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 6456439..f5267e4 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -27,6 +27,7 @@ static DEFINE_MUTEX(net_mutex);
LIST_HEAD(net_namespace_list);
EXPORT_SYMBOL_GPL(net_namespace_list);
+static DEFINE_IDA(net_namespace_ids);
struct net init_net = {
.dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
@@ -157,6 +158,15 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
atomic_set(&net->passive, 1);
net->dev_base_seq = 1;
net->user_ns = user_ns;
+again:
+ error = ida_get_new_above(&net_namespace_ids, 1, &net->nsindex);
+ if (error < 0) {
+ if (error == -EAGAIN) {
+ ida_pre_get(&net_namespace_ids, GFP_KERNEL);
+ goto again;
+ }
+ return error;
+ }
#ifdef NETNS_REFCNT_DEBUG
atomic_set(&net->use_count, 0);
@@ -171,6 +181,7 @@ out:
return error;
out_undo:
+ ida_remove(&net_namespace_ids, net->nsindex);
/* Walk through the list backwards calling the exit functions
* for the pernet modules whose init functions did not fail.
*/
@@ -297,6 +308,11 @@ static void cleanup_net(struct work_struct *work)
*/
synchronize_rcu();
+ list_for_each_entry(net, &net_exit_list, exit_list) {
+ /* Free the index */
+ ida_remove(&net_namespace_ids, net->nsindex);
+ }
+
/* Run all of the network namespace exit methods */
list_for_each_entry_reverse(ops, &pernet_list, list)
ops_exit_list(ops, &net_exit_list);
--
1.8.0.1
^ permalink raw reply related
* Re: [PATCH] ndisc: Unexport ndisc_{build,send}_skb().
From: David Miller @ 2012-12-12 17:42 UTC (permalink / raw)
To: yoshfuji; +Cc: netdev
In-Reply-To: <201212121740.qBCHeQON011433@94.43.138.210.xn.2iij.net>
From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Thu, 13 Dec 2012 02:40:26 +0900
> These symbols were exported for bonding device by commit 305d552a
> ("bonding: send IPv6 neighbor advertisement on failover").
>
> It bacame obsolete by commit 7c899432 ("bonding, ipv4, ipv6, vlan: Handle
> NETDEV_BONDING_FAILOVER like NETDEV_NOTIFY_PEERS") and removed by
> commit 4f5762ec ("bonding: Remove obsolete source file 'bond_ipv6.c'").
>
> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next] uapi: add missing netconf.h to export list
From: David Miller @ 2012-12-12 17:40 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: shemminger, netdev
In-Reply-To: <50C8B91A.8050400@6wind.com>
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Wed, 12 Dec 2012 18:04:26 +0100
> Le 12/12/2012 17:58, Stephen Hemminger a écrit :
>> Add netconf.h for use by iproute2.
>>
>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Applied.
^ permalink raw reply
* [PATCH] ndisc: Unexport ndisc_{build,send}_skb().
From: YOSHIFUJI Hideaki @ 2012-12-12 17:40 UTC (permalink / raw)
To: davem, netdev; +Cc: yoshfuji
These symbols were exported for bonding device by commit 305d552a
("bonding: send IPv6 neighbor advertisement on failover").
It bacame obsolete by commit 7c899432 ("bonding, ipv4, ipv6, vlan: Handle
NETDEV_BONDING_FAILOVER like NETDEV_NOTIFY_PEERS") and removed by
commit 4f5762ec ("bonding: Remove obsolete source file 'bond_ipv6.c'").
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/net/ndisc.h | 15 ---------------
net/ipv6/ndisc.c | 27 +++++++++++----------------
2 files changed, 11 insertions(+), 31 deletions(-)
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 980d263..7af1ea8 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -190,21 +190,6 @@ extern void ndisc_send_redirect(struct sk_buff *skb,
extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
struct net_device *dev, int dir);
-extern struct sk_buff *ndisc_build_skb(struct net_device *dev,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h,
- const struct in6_addr *target,
- int llinfo);
-
-extern void ndisc_send_skb(struct sk_buff *skb,
- struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h);
-
-
/*
* IGMP
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index cf43b65..4c02e6a 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -370,12 +370,12 @@ static void pndisc_destructor(struct pneigh_entry *n)
ipv6_dev_mc_dec(dev, &maddr);
}
-struct sk_buff *ndisc_build_skb(struct net_device *dev,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h,
- const struct in6_addr *target,
- int llinfo)
+static struct sk_buff *ndisc_build_skb(struct net_device *dev,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h,
+ const struct in6_addr *target,
+ int llinfo)
{
struct net *net = dev_net(dev);
struct sock *sk = net->ipv6.ndisc_sk;
@@ -431,14 +431,11 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev,
return skb;
}
-EXPORT_SYMBOL(ndisc_build_skb);
-
-void ndisc_send_skb(struct sk_buff *skb,
- struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h)
+static void ndisc_send_skb(struct sk_buff *skb, struct net_device *dev,
+ struct neighbour *neigh,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr,
+ struct icmp6hdr *icmp6h)
{
struct flowi6 fl6;
struct dst_entry *dst;
@@ -473,8 +470,6 @@ void ndisc_send_skb(struct sk_buff *skb,
rcu_read_unlock();
}
-EXPORT_SYMBOL(ndisc_send_skb);
-
/*
* Send a Neighbour Discover packet
*/
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH net-next 0/7] Allow to monitor multicast cache event via rtnetlink
From: Nicolas Dichtel @ 2012-12-12 17:30 UTC (permalink / raw)
To: Thomas Graf; +Cc: David Miller, David.Laight, netdev
In-Reply-To: <20121211184013.GD27746@casper.infradead.org>
Le 11/12/2012 19:40, Thomas Graf a écrit :
> On 12/11/12 at 04:03pm, Nicolas Dichtel wrote:
>> In fact, it seems not so easy because most users of nlmsg_new() calculate
>> the exact needed length, thus if we add an unpredicted attribute,
>> the message will be too small.
>
> True, we would either need to fix the calculations by accounting
> for an additional 4 bytes for each 64bit arg or just reserve an
> additional fixed amount for padding per message in nlmsg_new().
>
I would say that reserving additional space is better, because we also
need to align attributes that contain u64 fields:
struct attribute_foo {
__u32 bar;
__u32 bar2;
__u64 foo;
};
I wonder if it is better to align all attribute on 64-bits or only u64 and
add a new function nla_put_align64() for attribute with u64 fields.
^ permalink raw reply
* Re: [patch net-next 0/4] net: allow to change carrier from userspace
From: Stephen Hemminger @ 2012-12-12 17:27 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, edumazet, bhutchings, mirqus, greearb, fbl
In-Reply-To: <20121212170520.GA3060@minipsycho.orion>
On Wed, 12 Dec 2012 18:05:20 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> Wed, Dec 12, 2012 at 05:15:00PM CET, shemminger@vyatta.com wrote:
> >On Wed, 12 Dec 2012 11:58:03 +0100
> >Jiri Pirko <jiri@resnulli.us> wrote:
> >
> >> This is basically a repost of my previous patchset:
> >> "[patch net-next-2.6 0/2] net: allow to change carrier via sysfs" from Aug 30
> >>
> >> The way net-sysfs stores values changed and this patchset reflects it.
> >> Also, I exposed carrier via rtnetlink iface.
> >>
> >> So far, only dummy driver uses carrier change ndo. In very near future
> >> team driver will use that as well.
> >>
> >> Jiri Pirko (4):
> >> net: add change_carrier netdev op
> >> net: allow to change carrier via sysfs
> >> rtnl: expose carrier value with possibility to set it
> >> dummy: implement carrier change
> >>
> >> drivers/net/dummy.c | 10 ++++++++++
> >> include/linux/netdevice.h | 7 +++++++
> >> include/uapi/linux/if_link.h | 1 +
> >> net/core/dev.c | 19 +++++++++++++++++++
> >> net/core/net-sysfs.c | 15 ++++++++++++++-
> >> net/core/rtnetlink.c | 10 ++++++++++
> >> 6 files changed, 61 insertions(+), 1 deletion(-)
> >>
> >
> >I needed to do the same thing for a project we are working on and discovered
> >that there already is a working documented interface for doing that via
> >operstate mode. Therefore I can't recommend that the additional complexity
> >of a new API for this is required.
>
> I might be missing something, but I'm unable to find how operstate set
> can affect value returned by netif_carrier_ok()
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Here is an example using dummy device using libmnl. It is also possible
with ip commands.
# modprobe dummy
# ip li show dev dummy0
12: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT
link/ether ce:90:46:83:6e:f8 brd ff:ff:ff:ff:ff:ff
# ./dummy dummy0 init
# ip li show dev dummy0
12: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DORMANT
link/ether ce:90:46:83:6e:f8 brd ff:ff:ff:ff:ff:ff
# ip li set dummy0 up
# ip li show dev dummy0
12: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DORMANT
link/ether ce:90:46:83:6e:f8 brd ff:ff:ff:ff:ff:ff
# ./dummy dummy0 down
# ip li show dev dummy0
12: dummy0: <NO-CARRIER,BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state DORMANT mode DORMANT
link/ether ce:90:46:83:6e:f8 brd ff:ff:ff:ff:ff:ff
# ./dummy dummy0 up
# ip li show dev dummy0
12: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT
link/ether ce:90:46:83:6e:f8 brd ff:ff:ff:ff:ff:ff
/* Sample program to control link mode and link state */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <libmnl/libmnl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/rtnetlink.h>
static void panic(const char *str)
{
perror(str);
exit(1);
}
static void usage(const char *cmd)
{
fprintf(stderr, "Usage: %s dummyX [up|down|init]\n", cmd);
exit(1);
}
/* Send request and parse response */
static void mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh)
{
unsigned portid = mnl_socket_get_portid(nl);
uint32_t seq = time(NULL);
char buf[MNL_SOCKET_BUFFER_SIZE];
nlh->nlmsg_flags |= NLM_F_ACK;
nlh->nlmsg_seq = seq;
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
panic("mnl_socket_sendto failed");
int ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
if (ret < 0)
panic("mnl_socket_recvfrom");
if ( mnl_cb_run(buf, ret, seq, portid, NULL, NULL) < 0)
panic("mnl_cb_run");
}
static void linkstate(struct mnl_socket *nl,
const char *ifname, unsigned int state)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = RTM_NEWLINK;
nlh->nlmsg_flags = NLM_F_REQUEST;
struct ifinfomsg *ifi;
ifi = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg));
ifi->ifi_family = AF_UNSPEC;
mnl_attr_put_strz(nlh, IFLA_IFNAME, ifname);
mnl_attr_put_u8(nlh, IFLA_OPERSTATE, state);
mnl_talk(nl, nlh);
}
/* Set device link mode */
static void init(struct mnl_socket *nl, const char *ifname)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = RTM_NEWLINK;
nlh->nlmsg_flags = NLM_F_REQUEST;
struct ifinfomsg *ifi;
ifi = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg));
ifi->ifi_family = AF_UNSPEC;
mnl_attr_put_strz(nlh, IFLA_IFNAME, ifname);
mnl_attr_put_u8(nlh, IFLA_LINKMODE, IF_LINK_MODE_DORMANT);
mnl_talk(nl, nlh);
}
int main(int argc, char **argv)
{
if (argc != 3)
usage(argv[0]);
struct mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);
if (!nl)
panic("mnl_socket_open");
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
panic("mnl_socket_bind");
if (strcmp(argv[2], "init") == 0)
init(nl, argv[1]);
else if (strcmp(argv[2], "up") == 0)
linkstate(nl, argv[1], IF_OPER_UP);
else if (strcmp(argv[2], "down") == 0)
linkstate(nl, argv[1], IF_OPER_DORMANT);
else
usage(argv[0]);
return 0;
}
^ permalink raw reply
* [RFC PATCH net-next 0/5] Ease netns management by userland
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka
The goal of this serie is to ease netns management by daemons. Some systems use
netns only to virtualize network stack and don't want to multiply userland
daemons. These system may have a lot of netns, up to 2000. We don't want to
launch an instance of each daemons (quagga, strongswan, conntrackd, ...) for
each netns because it will consume a lot of ressources. Having one daemon that
manage all netns is more efficient (mainly if there are few objects to manage:
one or two routes per netns for example).
Hence, one goal of this serie is to allow, for a daemon, to monitor netns
activities, thus it can open or close netlink sockets, allocating structures
needed to manage these netns when they are created or deleted.
To help to identify a netns, an index has been added to each netns.
A new setsockopt() option is also added, to help daemons to open socket in the
right netns. For now, a daemon that want to open a socket in a specified netns,
need to call setns(CLONE_NEWNET) with a fd (not so easy to found), open the
socket and then call again setns() to go back in the initial netns. Having this
kind of setsockopt() will simplify operations. Obviously, this setsockopt()
should be done enough early (is test on sk_state enough?). The first target is
netlink socket but it can be useful for other kind of socket, it's why a add a
generic socket option.
As usual, the patch against iproute2 will be sent once the patches are included
and net-next merged. I can send it on demand.
arch/alpha/include/asm/socket.h | 2 +
arch/avr32/include/uapi/asm/socket.h | 2 +
arch/frv/include/uapi/asm/socket.h | 2 +
arch/h8300/include/asm/socket.h | 2 +
arch/ia64/include/uapi/asm/socket.h | 2 +
arch/m32r/include/asm/socket.h | 2 +
arch/m68k/include/uapi/asm/socket.h | 2 +
arch/mips/include/uapi/asm/socket.h | 2 +
arch/mn10300/include/uapi/asm/socket.h | 2 +
arch/parisc/include/uapi/asm/socket.h | 2 +
arch/powerpc/include/uapi/asm/socket.h | 2 +
arch/s390/include/uapi/asm/socket.h | 2 +
arch/sparc/include/uapi/asm/socket.h | 2 +
arch/xtensa/include/uapi/asm/socket.h | 2 +
include/net/net_namespace.h | 3 +
include/uapi/asm-generic/socket.h | 2 +
include/uapi/linux/if_link.h | 1 +
include/uapi/linux/netns.h | 31 +++++
net/core/net_namespace.c | 223 +++++++++++++++++++++++++++++++++
net/core/rtnetlink.c | 7 +-
net/core/sock.c | 28 +++++
net/netlink/genetlink.c | 4 +
22 files changed, 326 insertions(+), 1 deletion(-)
I do not pretend to be a netns expert, it's why I add RFC in the title ;-)
Comments are welcome.
Regards,
Nicolas
^ permalink raw reply
* [RFC PATCH net-next 5/5] net/sock: add support of SO_NETNS
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355333081-4018-1-git-send-email-nicolas.dichtel@6wind.com>
This new setsockopt() option allows user to change netns of a socket. It
should be done enough early, before any bind(), etc.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
arch/alpha/include/asm/socket.h | 2 ++
arch/avr32/include/uapi/asm/socket.h | 2 ++
arch/frv/include/uapi/asm/socket.h | 2 ++
arch/h8300/include/asm/socket.h | 2 ++
arch/ia64/include/uapi/asm/socket.h | 2 ++
arch/m32r/include/asm/socket.h | 2 ++
arch/m68k/include/uapi/asm/socket.h | 2 ++
arch/mips/include/uapi/asm/socket.h | 2 ++
arch/mn10300/include/uapi/asm/socket.h | 2 ++
arch/parisc/include/uapi/asm/socket.h | 2 ++
arch/powerpc/include/uapi/asm/socket.h | 2 ++
arch/s390/include/uapi/asm/socket.h | 2 ++
arch/sparc/include/uapi/asm/socket.h | 2 ++
arch/xtensa/include/uapi/asm/socket.h | 2 ++
include/uapi/asm-generic/socket.h | 2 ++
net/core/sock.c | 28 ++++++++++++++++++++++++++++
16 files changed, 58 insertions(+)
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 0087d05..13aa509 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -77,6 +77,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#ifdef __KERNEL__
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 486df68..39cc927 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 871f89b..ac7eef6 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -70,5 +70,7 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index 90a2e57..4d2a4e8 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 23d6759..ed4534b 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -79,4 +79,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index 5e7088a..37d0eb0 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
index 285da3b..e79aad8 100644
--- a/arch/m68k/include/uapi/asm/socket.h
+++ b/arch/m68k/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 17307ab..356f943 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -90,5 +90,7 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index af5366b..b899cf8 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -70,4 +70,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index d9ff473..8503329 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -69,6 +69,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 0x4024
+#define SO_NETNS 0x4025
+
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index eb0b186..1a520ff 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -77,4 +77,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 436d07c..cbdda59 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -76,4 +76,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index c83a937..c1c2853 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -66,6 +66,8 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 0x0027
+#define SO_NETNS 0x0028
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index 38079be..a8f956d 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -81,4 +81,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 2d32d07..08c108c 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -73,4 +73,6 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
+#define SO_NETNS 44
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/sock.c b/net/core/sock.c
index a692ef4..7ec288f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -895,6 +895,30 @@ set_rcvbuf:
sock_valbool_flag(sk, SOCK_NOFCS, valbool);
break;
+ case SO_NETNS:
+#ifdef CONFIG_NET_NS
+ if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+ ret = -EPERM;
+ else if (sk->sk_state != TCP_CLOSE)
+ ret = -EBUSY; /* Too late to change netns */
+ else {
+ struct net *net = get_net_ns_by_nsindex(val);
+
+ if (net) {
+ /* We can not use sk_change_net() because sk
+ * will not be released with
+ * sk_release_kernel(). Let do it manually.
+ */
+ put_net(sock_net(sk));
+ sock_net_set(sk, net);
+ } else
+ ret = -EINVAL;
+ }
+#else
+ ret = -EOPNOTSUPP;
+#endif
+ break;
+
default:
ret = -ENOPROTOOPT;
break;
@@ -1140,6 +1164,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
goto lenout;
+ case SO_NETNS:
+ v.val = sock_net(sk)->nsindex;
+ break;
+
default:
return -ENOPROTOOPT;
}
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 4/5] netns: advertise netns activity with netlink
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355333081-4018-1-git-send-email-nicolas.dichtel@6wind.com>
Goal of this patch is to send netlink messages when netns are crated/deleted.
This is useful for daemon that wants to manage all netns with only one running
instance.
Note that until that netns_nl_event_mcgrp group is not registered, we cannot
send event.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/netns.h | 4 ++++
net/core/net_namespace.c | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/netns.h b/include/uapi/linux/netns.h
index e1c1da3..e14d90b 100644
--- a/include/uapi/linux/netns.h
+++ b/include/uapi/linux/netns.h
@@ -6,10 +6,14 @@
#define NETNS_GENL_NAME "netns"
#define NETNS_GENL_VERSION 0x1
+#define NETNS_GENL_MCAST_EVENT_NAME "events"
+
/* Commands */
enum {
NETNS_CMD_NOOP,
NETNS_CMD_GET,
+ NETNS_CMD_NEW,
+ NETNS_CMD_DEL,
__NETNS_CMD_MAX,
};
#define NETNS_CMD_MAX (__NETNS_CMD_MAX - 1)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 18fc62f..da92ecb 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -40,6 +40,8 @@ EXPORT_SYMBOL(init_net);
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+static int netns_nl_event(struct net *net, int cmd);
+
static struct net_generic *net_alloc_generic(void)
{
struct net_generic *ng;
@@ -179,6 +181,7 @@ again:
if (error < 0)
goto out_undo;
}
+ netns_nl_event(net, NETNS_CMD_NEW);
out:
return error;
@@ -311,6 +314,7 @@ static void cleanup_net(struct work_struct *work)
synchronize_rcu();
list_for_each_entry(net, &net_exit_list, exit_list) {
+ netns_nl_event(net, NETNS_CMD_DEL);
/* Free the index */
ida_remove(&net_namespace_ids, net->nsindex);
}
@@ -413,6 +417,10 @@ struct net *get_net_ns_by_nsindex(int nsindex)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_nsindex);
+static struct genl_multicast_group netns_nl_event_mcgrp = {
+ .name = NETNS_GENL_MCAST_EVENT_NAME,
+};
+
static struct genl_family netns_nl_family = {
.id = GENL_ID_GENERATE,
.name = NETNS_GENL_NAME,
@@ -562,10 +570,38 @@ static struct genl_ops netns_nl_ops[] = {
},
};
+static int netns_nl_event(struct net *net, int cmd)
+{
+ struct sk_buff *msg;
+ int err = -ENOBUFS;
+
+ /* Check that gennl infra is ready */
+ if (!netns_nl_event_mcgrp.id)
+ return -ENOENT;
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_ATOMIC);
+ if (!msg)
+ return -ENOMEM;
+
+ err = netns_nl_fill(msg, 0, 0, 0, cmd, net);
+ if (err < 0) {
+ nlmsg_free(msg);
+ return err;
+ }
+
+ return genlmsg_multicast(msg, 0, netns_nl_event_mcgrp.id, GFP_ATOMIC);
+}
+
int netns_genl_register(void)
{
- return genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
+ int err;
+
+ err = genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
ARRAY_SIZE(netns_nl_ops));
+ if (err < 0)
+ return err;
+
+ return genl_register_mc_group(&netns_nl_family, &netns_nl_event_mcgrp);
}
static int __init net_ns_init(void)
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 2/5] netns: allow to dump netns with netlink
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355333081-4018-1-git-send-email-nicolas.dichtel@6wind.com>
This patch adds the basic support of netlink for netns. The user can dump all
existing netns and get associated nsindex.
He also can get nsindex associated to a pid or fd.
To initialize genetlink family for netns, there is a problem of chicken and
eggs. genetlink init is done after init_net is created, hence when init_net is
created, we cannot call genl_register_family_with_ops(). It's why I put the
init part in genetlink module.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
include/uapi/linux/netns.h | 27 ++++++++
net/core/net_namespace.c | 157 ++++++++++++++++++++++++++++++++++++++++++++
net/netlink/genetlink.c | 4 ++
4 files changed, 189 insertions(+)
create mode 100644 include/uapi/linux/netns.h
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 5db7a1b..c373f2e 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -306,6 +306,7 @@ extern int register_pernet_subsys(struct pernet_operations *);
extern void unregister_pernet_subsys(struct pernet_operations *);
extern int register_pernet_device(struct pernet_operations *);
extern void unregister_pernet_device(struct pernet_operations *);
+extern int netns_genl_register(void);
struct ctl_table;
struct ctl_table_header;
diff --git a/include/uapi/linux/netns.h b/include/uapi/linux/netns.h
new file mode 100644
index 0000000..e1c1da3
--- /dev/null
+++ b/include/uapi/linux/netns.h
@@ -0,0 +1,27 @@
+#ifndef _UAPI_LINUX_NETNS_H_
+#define _UAPI_LINUX_NETNS_H_
+
+/* Generic netlink messages */
+
+#define NETNS_GENL_NAME "netns"
+#define NETNS_GENL_VERSION 0x1
+
+/* Commands */
+enum {
+ NETNS_CMD_NOOP,
+ NETNS_CMD_GET,
+ __NETNS_CMD_MAX,
+};
+#define NETNS_CMD_MAX (__NETNS_CMD_MAX - 1)
+
+/* Attributes */
+enum {
+ NETNSA_NONE,
+ NETNSA_NSINDEX,
+ NETNSA_PID,
+ NETNSA_FD,
+ __NETNSA_MAX,
+};
+#define NETNSA_MAX (__NETNSA_MAX - 1)
+
+#endif /* _UAPI_LINUX_NETNS_H_ */
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f5267e4..2ae22b0 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -14,6 +14,8 @@
#include <linux/file.h>
#include <linux/export.h>
#include <linux/user_namespace.h>
+#include <linux/netns.h>
+#include <net/genetlink.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -397,6 +399,161 @@ struct net *get_net_ns_by_pid(pid_t pid)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+static struct genl_family netns_nl_family = {
+ .id = GENL_ID_GENERATE,
+ .name = NETNS_GENL_NAME,
+ .version = NETNS_GENL_VERSION,
+ .hdrsize = 0,
+ .maxattr = NETNSA_MAX,
+ .netnsok = true,
+};
+
+static struct nla_policy netns_nl_policy[NETNSA_MAX + 1] = {
+ [NETNSA_NONE] = { .type = NLA_UNSPEC, },
+ [NETNSA_NSINDEX] = { .type = NLA_U32, },
+ [NETNSA_PID] = { .type = NLA_U32 },
+ [NETNSA_FD] = { .type = NLA_U32 },
+};
+
+static int netns_nl_get_size(void)
+{
+ return nla_total_size(sizeof(u32)) /* NETNSA_NSINDEX */
+ ;
+}
+
+static int netns_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sk_buff *msg;
+ void *hdr;
+ int ret = -ENOBUFS;
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_KERNEL);
+ if (!msg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &netns_nl_family, 0, NETNS_CMD_NOOP);
+ if (!hdr) {
+ ret = -EMSGSIZE;
+ goto err_out;
+ }
+
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+
+err_out:
+ nlmsg_free(msg);
+
+out:
+ return ret;
+}
+
+static int netns_nl_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
+ int cmd, struct net *net)
+{
+ void *hdr;
+
+ hdr = genlmsg_put(skb, portid, seq, &netns_nl_family, flags, cmd);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(skb, NETNSA_NSINDEX, net->nsindex))
+ goto nla_put_failure;
+
+ return genlmsg_end(skb, hdr);
+
+nla_put_failure:
+ genlmsg_cancel(skb, hdr);
+ return -EMSGSIZE;
+}
+
+static int netns_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct sk_buff *msg;
+ int err = -ENOBUFS;
+
+ if (info->attrs[NETNSA_PID])
+ net = get_net_ns_by_pid(nla_get_u32(info->attrs[NETNSA_PID]));
+ else if (info->attrs[NETNSA_FD])
+ net = get_net_ns_by_fd(nla_get_u32(info->attrs[NETNSA_FD]));
+ else
+ get_net(net);
+
+ msg = genlmsg_new(netns_nl_get_size(), GFP_KERNEL);
+ if (!msg) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = netns_nl_fill(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, NETNS_CMD_GET, net);
+ if (err < 0)
+ goto err_out;
+
+ err = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+ goto out;
+
+err_out:
+ nlmsg_free(msg);
+
+out:
+ put_net(net);
+ return err;
+}
+
+static int netns_nl_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int i = 0, s_i = cb->args[0];
+ struct net *net;
+
+ rtnl_lock();
+ for_each_net(net) {
+ if (i < s_i) {
+ i++;
+ continue;
+ }
+
+ if (netns_nl_fill(skb, NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
+ NETNS_CMD_GET, net) <= 0)
+ goto out;
+
+ i++;
+ }
+
+out:
+ cb->args[0] = i;
+ rtnl_unlock();
+
+ return skb->len;
+}
+
+static struct genl_ops netns_nl_ops[] = {
+ {
+ .cmd = NETNS_CMD_NOOP,
+ .policy = netns_nl_policy,
+ .doit = netns_nl_cmd_noop,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NETNS_CMD_GET,
+ .policy = netns_nl_policy,
+ .doit = netns_nl_cmd_get,
+ .dumpit = netns_nl_cmd_dump,
+ .flags = GENL_ADMIN_PERM,
+ },
+};
+
+int netns_genl_register(void)
+{
+ return genl_register_family_with_ops(&netns_nl_family, netns_nl_ops,
+ ARRAY_SIZE(netns_nl_ops));
+}
+
static int __init net_ns_init(void)
{
struct net_generic *ng;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f2aabb6..6d25ddb 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -963,6 +963,10 @@ static int __init genl_init(void)
if (err < 0)
goto problem;
+ err = netns_genl_register();
+ if (err < 0)
+ goto problem;
+
return 0;
problem:
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 3/5] dev/netns: allow to get netns from nsindex in rtnl msg
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355333081-4018-1-git-send-email-nicolas.dichtel@6wind.com>
This patch allows to move a netdevice to another netns by giving the nsindex.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/core/net_namespace.c | 14 ++++++++++++++
net/core/rtnetlink.c | 7 ++++++-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index c373f2e..68e7a36 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -151,6 +151,7 @@ extern struct list_head net_namespace_list;
extern struct net *get_net_ns_by_pid(pid_t pid);
extern struct net *get_net_ns_by_fd(int pid);
+extern struct net *get_net_ns_by_nsindex(int nsindex);
#ifdef CONFIG_NET_NS
extern void __put_net(struct net *net);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 60f3b6b..6720a47 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -142,6 +142,7 @@ enum {
#define IFLA_PROMISCUITY IFLA_PROMISCUITY
IFLA_NUM_TX_QUEUES,
IFLA_NUM_RX_QUEUES,
+ IFLA_NET_NS_INDEX,
__IFLA_MAX
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2ae22b0..18fc62f 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -399,6 +399,20 @@ struct net *get_net_ns_by_pid(pid_t pid)
}
EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+struct net *get_net_ns_by_nsindex(int nsindex)
+{
+ struct net *net;
+
+ ASSERT_RTNL();
+ for_each_net(net)
+ if (net->nsindex == nsindex) {
+ get_net(net);
+ break;
+ }
+ return net;
+}
+EXPORT_SYMBOL_GPL(get_net_ns_by_nsindex);
+
static struct genl_family netns_nl_family = {
.id = GENL_ID_GENERATE,
.name = NETNS_GENL_NAME,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1868625..e22954a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1115,6 +1115,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_LINKINFO] = { .type = NLA_NESTED },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
[IFLA_NET_NS_FD] = { .type = NLA_U32 },
+ [IFLA_NET_NS_INDEX] = { .type = NLA_U32 },
[IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
[IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
[IFLA_VF_PORTS] = { .type = NLA_NESTED },
@@ -1171,6 +1172,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
else if (tb[IFLA_NET_NS_FD])
net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
+ else if (tb[IFLA_NET_NS_INDEX])
+ net = get_net_ns_by_nsindex(nla_get_u32(tb[IFLA_NET_NS_INDEX]));
else
net = get_net(src_net);
return net;
@@ -1310,7 +1313,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
int send_addr_notify = 0;
int err;
- if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
+ if (tb[IFLA_NET_NS_PID] ||
+ tb[IFLA_NET_NS_FD] ||
+ tb[IFLA_NET_NS_INDEX]) {
struct net *net = rtnl_link_get_net(dev_net(dev), tb);
if (IS_ERR(net)) {
err = PTR_ERR(net);
--
1.8.0.1
^ permalink raw reply related
* [RFC PATCH net-next 1/5] netns: allocate an unique id to identify a netns
From: Nicolas Dichtel @ 2012-12-12 17:24 UTC (permalink / raw)
To: netdev; +Cc: davem, ebiederm, aatteka, Nicolas Dichtel
In-Reply-To: <1355333081-4018-1-git-send-email-nicolas.dichtel@6wind.com>
This patch simply adds a field nsindex, which will contain a unique index.
The goal is to prepare the monitoring of netns activities with rtnelink and to
ease netns management by userland apps.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/net_namespace.h | 1 +
net/core/net_namespace.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index c5a43f5..5db7a1b 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -55,6 +55,7 @@ struct net {
struct list_head exit_list; /* Use only net_mutex */
struct user_namespace *user_ns; /* Owning user namespace */
+ int nsindex; /* index to identify this ns */
struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 6456439..f5267e4 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -27,6 +27,7 @@ static DEFINE_MUTEX(net_mutex);
LIST_HEAD(net_namespace_list);
EXPORT_SYMBOL_GPL(net_namespace_list);
+static DEFINE_IDA(net_namespace_ids);
struct net init_net = {
.dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
@@ -157,6 +158,15 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
atomic_set(&net->passive, 1);
net->dev_base_seq = 1;
net->user_ns = user_ns;
+again:
+ error = ida_get_new_above(&net_namespace_ids, 1, &net->nsindex);
+ if (error < 0) {
+ if (error == -EAGAIN) {
+ ida_pre_get(&net_namespace_ids, GFP_KERNEL);
+ goto again;
+ }
+ return error;
+ }
#ifdef NETNS_REFCNT_DEBUG
atomic_set(&net->use_count, 0);
@@ -171,6 +181,7 @@ out:
return error;
out_undo:
+ ida_remove(&net_namespace_ids, net->nsindex);
/* Walk through the list backwards calling the exit functions
* for the pernet modules whose init functions did not fail.
*/
@@ -297,6 +308,11 @@ static void cleanup_net(struct work_struct *work)
*/
synchronize_rcu();
+ list_for_each_entry(net, &net_exit_list, exit_list) {
+ /* Free the index */
+ ida_remove(&net_namespace_ids, net->nsindex);
+ }
+
/* Run all of the network namespace exit methods */
list_for_each_entry_reverse(ops, &pernet_list, list)
ops_exit_list(ops, &net_exit_list);
--
1.8.0.1
^ permalink raw reply related
* Re: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
From: Nicolas Dichtel @ 2012-12-12 17:20 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20121212091118.390b8a2b@nehalam.linuxnetplumber.net>
Le 12/12/2012 18:11, Stephen Hemminger a écrit :
> On Wed, 12 Dec 2012 10:51:47 +0100
> Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:
>
>> This patch allows to manage ip tunnels via the interface ip link.
>> The syntax for parameters is the same that 'ip tunnel'.
>>
>> It also allows to display tunnels parameters with 'ip -details link' or
>> 'ip -details monitor link'.
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> ---
>> ip/Makefile | 3 +-
>> ip/iplink.c | 2 +-
>> ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 343 insertions(+), 2 deletions(-)
>> create mode 100644 ip/link_iptnl.c
>>
>> diff --git a/ip/Makefile b/ip/Makefile
>> index abf54bf..2b606d4 100644
>> --- a/ip/Makefile
>> +++ b/ip/Makefile
>> @@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
>> ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
>> iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
>> iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
>> - iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
>> + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
>> + link_iptnl.o
>>
>> RTMONOBJ=rtmon.o
>>
>> diff --git a/ip/iplink.c b/ip/iplink.c
>> index 8aac9fc..d73c705 100644
>> --- a/ip/iplink.c
>> +++ b/ip/iplink.c
>> @@ -84,7 +84,7 @@ void iplink_usage(void)
>> if (iplink_have_newlink()) {
>> fprintf(stderr, "\n");
>> fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
>> - fprintf(stderr, " bridge | ipoib | ip6tnl }\n");
>> + fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit }\n");
>> }
>> exit(-1);
>> }
>> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
>> new file mode 100644
>> index 0000000..238722d
>> --- /dev/null
>> +++ b/ip/link_iptnl.c
>> @@ -0,0 +1,340 @@
>> +/*
>> + * link_iptnl.c ipip and sit driver module
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version
>> + * 2 of the License, or (at your option) any later version.
>> + *
>> + * Authors: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> + *
>> + */
>> +
>> +#include <string.h>
>> +#include <net/if.h>
>> +#include <sys/types.h>
>> +#include <sys/socket.h>
>> +#include <arpa/inet.h>
>> +
>> +#include <linux/ip.h>
>> +#include <linux/if_tunnel.h>
>> +#include "rt_names.h"
>> +#include "utils.h"
>> +#include "ip_common.h"
>> +#include "tunnel.h"
>> +
>> +static void usage(int sit) __attribute__((noreturn));
>> +static void usage(int sit)
>> +{
>> + fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
>> + fprintf(stderr, " type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
>> + fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
>> + fprintf(stderr, " [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
>> + if (sit)
>> + fprintf(stderr, " [ isatap ]\n");
>> + fprintf(stderr, "\n");
>> + fprintf(stderr, "Where: NAME := STRING\n");
>> + fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
>> + fprintf(stderr, " TOS := { NUMBER | inherit }\n");
>> + fprintf(stderr, " TTL := { 1..255 | inherit }\n");
>> + exit(-1);
>> +}
>> +
>> +static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
>> + struct nlmsghdr *n)
>> +{
>> + struct {
>> + struct nlmsghdr n;
>> + struct ifinfomsg i;
>> + char buf[2048];
>> + } req;
>> + struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
>> + struct rtattr *tb[IFLA_MAX + 1];
>> + struct rtattr *linkinfo[IFLA_INFO_MAX+1];
>> + struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
>> + int len;
>> + __u32 link = 0;
>> + __u32 laddr = 0;
>> + __u32 raddr = 0;
>> + __u8 ttl = 0;
>> + __u8 tos = 0;
>> + __u8 pmtudisc = 1;
>> + __u16 iflags = 0;
>> + struct in6_addr ip6rdprefix;
>> + __u16 ip6rdprefixlen = 0;
>> + __u32 ip6rdrelayprefix = 0;
>> + __u16 ip6rdrelayprefixlen = 0;
>> +
>> + memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
>> +
>> + if (!(n->nlmsg_flags & NLM_F_CREATE)) {
>> + memset(&req, 0, sizeof(req));
>> +
>> + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
>> + req.n.nlmsg_flags = NLM_F_REQUEST;
>> + req.n.nlmsg_type = RTM_GETLINK;
>> + req.i.ifi_family = preferred_family;
>> + req.i.ifi_index = ifi->ifi_index;
>> +
>> + if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
>> +get_failed:
>> + fprintf(stderr,
>> + "Failed to get existing tunnel info.\n");
>> + return -1;
>> + }
>> +
>> + len = req.n.nlmsg_len;
>> + len -= NLMSG_LENGTH(sizeof(*ifi));
>> + if (len < 0)
>> + goto get_failed;
>> +
>> + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
>> +
>> + if (!tb[IFLA_LINKINFO])
>> + goto get_failed;
>> +
>> + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
>> +
>> + if (!linkinfo[IFLA_INFO_DATA])
>> + goto get_failed;
>> +
>> + parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
>> + linkinfo[IFLA_INFO_DATA]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_LOCAL])
>> + laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_REMOTE])
>> + raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_TTL])
>> + ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_TOS])
>> + tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_PMTUDISC])
>> + pmtudisc =
>> + rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_FLAGS])
>> + iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_LINK])
>> + link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
>> + memcpy(&ip6rdprefix,
>> + RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
>> + sizeof(laddr));
>> +
>> + if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
>> + ip6rdprefixlen =
>> + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
>> + ip6rdrelayprefix =
>> + rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
>> +
>> + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
>> + ip6rdrelayprefixlen =
>> + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
>> + }
>> +
>> + while (argc > 0) {
>> + if (strcmp(*argv, "remote") == 0) {
>> + NEXT_ARG();
>> + if (strcmp(*argv, "any"))
>> + raddr = get_addr32(*argv);
>> + else
>> + raddr = 0;
>> + } else if (strcmp(*argv, "local") == 0) {
>> + NEXT_ARG();
>> + if (strcmp(*argv, "any"))
>> + laddr = get_addr32(*argv);
>> + else
>> + laddr = 0;
>> + } else if (matches(*argv, "dev") == 0) {
>> + NEXT_ARG();
>> + link = if_nametoindex(*argv);
>> + if (link == 0)
>> + invarg("\"dev\" is invalid", *argv);
>> + } else if (strcmp(*argv, "ttl") == 0 ||
>> + strcmp(*argv, "hoplimit") == 0) {
>> + NEXT_ARG();
>> + if (strcmp(*argv, "inherit") != 0) {
>> + if (get_u8(&ttl, *argv, 0))
>> + invarg("invalid TTL\n", *argv);
>> + } else
>> + ttl = 0;
>> + } else if (strcmp(*argv, "tos") == 0 ||
>> + strcmp(*argv, "tclass") == 0 ||
>> + matches(*argv, "dsfield") == 0) {
>> + __u32 uval;
>> + NEXT_ARG();
>> + if (strcmp(*argv, "inherit") != 0) {
>> + if (rtnl_dsfield_a2n(&uval, *argv))
>> + invarg("bad TOS value", *argv);
>> + tos = uval;
>> + } else
>> + tos = 1;
>> + } else if (strcmp(*argv, "nopmtudisc") == 0) {
>> + pmtudisc = 0;
>> + } else if (strcmp(*argv, "pmtudisc") == 0) {
>> + pmtudisc = 1;
>> + } else if (strcmp(lu->id, "sit") == 0 &&
>> + strcmp(*argv, "isatap") == 0) {
>> + iflags |= SIT_ISATAP;
>> + } else if (strcmp(*argv, "6rd-prefix") == 0) {
>> + inet_prefix prefix;
>> + NEXT_ARG();
>> + if (get_prefix(&prefix, *argv, AF_INET6))
>> + invarg("invalid 6rd_prefix\n", *argv);
>> + memcpy(&ip6rdprefix, prefix.data, 16);
>> + ip6rdprefixlen = prefix.bitlen;
>> + } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
>> + inet_prefix prefix;
>> + NEXT_ARG();
>> + if (get_prefix(&prefix, *argv, AF_INET))
>> + invarg("invalid 6rd-relay_prefix\n", *argv);
>> + memcpy(&ip6rdrelayprefix, prefix.data, 4);
>> + ip6rdrelayprefixlen = prefix.bitlen;
>> + } else if (strcmp(*argv, "6rd-reset") == 0) {
>> + inet_prefix prefix;
>> + get_prefix(&prefix, "2002::", AF_INET6);
>> + memcpy(&ip6rdprefix, prefix.data, 16);
>> + ip6rdprefixlen = 16;
>> + ip6rdrelayprefix = 0;
>> + ip6rdrelayprefixlen = 0;
>> + } else
>> + usage(strcmp(lu->id, "sit") == 0);
>> + argc--, argv++;
>> + }
>> +
>> + if (ttl && pmtudisc == 0) {
>> + fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
>> + exit(-1);
>> + }
>> +
>> + addattr32(n, 1024, IFLA_IPTUN_LINK, link);
>> + addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
>> + addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
>> + addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
>> + addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
>> + addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
>> + if (strcmp(lu->id, "sit") == 0) {
>> + addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
>> + if (ip6rdprefixlen) {
>> + addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
>> + &ip6rdprefix, sizeof(ip6rdprefix));
>> + addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
>> + ip6rdprefixlen);
>> + addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
>> + ip6rdrelayprefix);
>> + addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
>> + ip6rdrelayprefixlen);
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
>> +{
>> + char s1[1024];
>> + char s2[64];
>> + const char *local = "any";
>> + const char *remote = "any";
>> +
>> + if (!tb)
>> + return;
>> +
>> + if (tb[IFLA_IPTUN_REMOTE]) {
>> + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
>> +
>> + if (addr)
>> + remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
>> + }
>> +
>> + fprintf(f, "remote %s ", remote);
>> +
>> + if (tb[IFLA_IPTUN_LOCAL]) {
>> + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
>> +
>> + if (addr)
>> + local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
>> + }
>> +
>> + fprintf(f, "local %s ", local);
>> +
>> + if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
>> + unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
>> + const char *n = if_indextoname(link, s2);
>> +
>> + if (n)
>> + fprintf(f, "dev %s ", n);
>> + else
>> + fprintf(f, "dev %u ", link);
>> + }
>> +
>> + if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
>> + fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
>> + else
>> + fprintf(f, "ttl inherit ");
>> +
>> + if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
>> + int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
>> +
>> + fputs("tos ", f);
>> + if (tos == 1)
>> + fputs("inherit ", f);
>> + else
>> + fprintf(f, "0x%x ", tos);
>> + }
>> +
>> + if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
>> + fprintf(f, "pmtudisc ");
>> + else
>> + fprintf(f, "nopmtudisc ");
>> +
>> + if (tb[IFLA_IPTUN_FLAGS]) {
>> + __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
>> +
>> + if (iflags & SIT_ISATAP)
>> + fprintf(f, "isatap ");
>> + }
>> +
>> + if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
>> + *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
>> + __u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
>> + __u16 relayprefixlen =
>> + rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
>> + __u32 relayprefix =
>> + rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
>> +
>> + printf("6rd-prefix %s/%u ",
>> + inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
>> + s1, sizeof(s1)),
>> + prefixlen);
>> + if (relayprefix) {
>> + printf("6rd-relay_prefix %s/%u ",
>> + format_host(AF_INET, 4, &relayprefix, s1,
>> + sizeof(s1)),
>> + relayprefixlen);
>> + }
>> + }
>> +}
>> +
>> +struct link_util ipip_link_util = {
>> + .id = "ipip",
>> + .maxattr = IFLA_IPTUN_MAX,
>> + .parse_opt = iptunnel_parse_opt,
>> + .print_opt = iptunnel_print_opt,
>> +};
>> +
>> +struct link_util sit_link_util = {
>> + .id = "sit",
>> + .maxattr = IFLA_IPTUN_MAX,
>> + .parse_opt = iptunnel_parse_opt,
>> + .print_opt = iptunnel_print_opt,
>> +};
>
> All applied with minor corrections to header files.
>
> Could you please add man pages for this new functionality?
>
Ok.
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: ethtool: Add destination MAC address to flow steering API
From: Ben Hutchings @ 2012-12-12 17:17 UTC (permalink / raw)
To: Amir Vadai; +Cc: David S. Miller, netdev, Or Gerlitz, Yan Burman
In-Reply-To: <1355227436-18383-2-git-send-email-amirv@mellanox.com>
On Tue, 2012-12-11 at 14:03 +0200, Amir Vadai wrote:
> From: Yan Burman <yanb@mellanox.com>
>
> Add ability to specify destination MAC address for L3/L4 flow spec
> in order to be able to specify action for different VM's under vSwitch
> configuration. This change is transparent to older userspace.
>
> Signed-off-by: Yan Burman <yanb@mellanox.com>
> Signed-off-by: Amir Vadai <amirv@mellanox.com>
> ---
> include/uapi/linux/ethtool.h | 11 +++++++----
> 1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
> index d3eaaaf..be8c41e 100644
> --- a/include/uapi/linux/ethtool.h
> +++ b/include/uapi/linux/ethtool.h
> @@ -500,13 +500,15 @@ union ethtool_flow_union {
> struct ethtool_ah_espip4_spec esp_ip4_spec;
> struct ethtool_usrip4_spec usr_ip4_spec;
> struct ethhdr ether_spec;
> - __u8 hdata[60];
> + __u8 hdata[52];
> };
>
> struct ethtool_flow_ext {
> - __be16 vlan_etype;
> - __be16 vlan_tci;
> - __be32 data[2];
> + __u8 padding[2];
> + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
> + __be16 vlan_etype;
> + __be16 vlan_tci;
> + __be32 data[2];
> };
>
> /**
> @@ -1027,6 +1029,7 @@ enum ethtool_sfeatures_retval_bits {
> #define ETHER_FLOW 0x12 /* spec only (ether_spec) */
> /* Flag to enable additional fields in struct ethtool_rx_flow_spec */
> #define FLOW_EXT 0x80000000
> +#define FLOW_MAC_EXT 0x40000000
You'll need to document exactly which flags and fields are related.
Adding kernel-doc to struct ethtool_flow_ext is probably the best way to
do that.
Ben.
> /* L3-L4 network traffic flow hash options */
> #define RXH_L2DA (1 << 1)
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCHv2 iproute2] add DOVE extensions for iproute2
From: Stephen Hemminger @ 2012-12-12 17:14 UTC (permalink / raw)
To: David L Stevens; +Cc: David Miller, netdev
In-Reply-To: <201212121612.qBCGAimS017147@lab1.dls>
On Wed, 12 Dec 2012 11:10:44 -0500
David L Stevens <dlstevens@us.ibm.com> wrote:
>
> This patch adds a new flag to iproute2 for vxlan devices to enable
> DOVE features. It also adds support for L2 and L3 switch lookup miss
> netlink messages to "ip monitor".
>
> Changes since v1:
> - split "dove" flag into separate feature flags:
> - "proxy" for ARP reduction
> - "rsc" for route short circuiting
> - "l2miss" for L2 switch miss notifications
> - "l3miss" for L3 switch miss notifications
>
> Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
>
> diff --git a/include/linux/if_link.h b/include/linux/if_link.h
> index 012d95a..a163702 100644
> - --- a/include/linux/if_link.h
> +++ b/include/linux/if_link.h
> @@ -283,6 +283,10 @@ enum {
> IFLA_VXLAN_AGEING,
> IFLA_VXLAN_LIMIT,
> IFLA_VXLAN_PORT_RANGE,
> + IFLA_VXLAN_PROXY,
> + IFLA_VXLAN_RSC,
> + IFLA_VXLAN_L2MISS,
> + IFLA_VXLAN_L3MISS,
> __IFLA_VXLAN_MAX
> };
> #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
> diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
> index ba5c4ab..f2e6bef 100644
> - --- a/ip/iplink_vxlan.c
> +++ b/ip/iplink_vxlan.c
> @@ -26,6 +26,8 @@ static void explain(void)
> fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n");
> fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n");
> fprintf(stderr, " [ port MIN MAX ] [ [no]learning ]\n");
> + fprintf(stderr, " [ [no]proxy ] [ [no]rsc ]\n");
> + fprintf(stderr, " [ [no]l2miss ] [ [no]l3miss ]\n");
> fprintf(stderr, "\n");
> fprintf(stderr, "Where: VNI := 0-16777215\n");
> fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
> @@ -44,6 +46,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
> __u8 tos = 0;
> __u8 ttl = 0;
> __u8 learning = 1;
> + __u8 proxy = 0;
> + __u8 rsc = 0;
> + __u8 l2miss = 0;
> + __u8 l3miss = 0;
> __u8 noage = 0;
> __u32 age = 0;
> __u32 maxaddr = 0;
> @@ -123,6 +129,22 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
> learning = 0;
> } else if (!matches(*argv, "learning")) {
> learning = 1;
> + } else if (!matches(*argv, "noproxy")) {
> + proxy = 0;
> + } else if (!matches(*argv, "proxy")) {
> + proxy = 1;
> + } else if (!matches(*argv, "norsc")) {
> + rsc = 0;
> + } else if (!matches(*argv, "rsc")) {
> + rsc = 1;
> + } else if (!matches(*argv, "nol2miss")) {
> + l2miss = 0;
> + } else if (!matches(*argv, "l2miss")) {
> + l2miss = 1;
> + } else if (!matches(*argv, "nol3miss")) {
> + l3miss = 0;
> + } else if (!matches(*argv, "l3miss")) {
> + l3miss = 1;
> } else if (matches(*argv, "help") == 0) {
> explain();
> return -1;
> @@ -148,6 +170,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
> addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
> addattr8(n, 1024, IFLA_VXLAN_TOS, tos);
> addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning);
> + addattr8(n, 1024, IFLA_VXLAN_PROXY, proxy);
> + addattr8(n, 1024, IFLA_VXLAN_RSC, rsc);
> + addattr8(n, 1024, IFLA_VXLAN_L2MISS, l2miss);
> + addattr8(n, 1024, IFLA_VXLAN_L3MISS, l3miss);
> if (noage)
> addattr32(n, 1024, IFLA_VXLAN_AGEING, 0);
> else if (age)
> @@ -213,6 +239,18 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
> if (tb[IFLA_VXLAN_LEARNING] &&
> !rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]))
> fputs("nolearning ", f);
> +
> + if (tb[IFLA_VXLAN_PROXY] && rta_getattr_u8(tb[IFLA_VXLAN_PROXY]))
> + fputs("proxy ", f);
> +
> + if (tb[IFLA_VXLAN_RSC] && rta_getattr_u8(tb[IFLA_VXLAN_RSC]))
> + fputs("rsc ", f);
> +
> + if (tb[IFLA_VXLAN_L2MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L2MISS]))
> + fputs("l2miss ", f);
> +
> + if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS]))
> + fputs("l3miss ", f);
>
> if (tb[IFLA_VXLAN_TOS] &&
> (tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) {
> diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
> index 4b1d469..7a7cc88 100644
> - --- a/ip/ipmonitor.c
> +++ b/ip/ipmonitor.c
> @@ -67,7 +67,8 @@ int accept_msg(const struct sockaddr_nl *who,
> print_addrlabel(who, n, arg);
> return 0;
> }
> - - if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) {
> + if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
> + n->nlmsg_type == RTM_GETNEIGH) {
> if (prefix_banner)
> fprintf(fp, "[NEIGH]");
> print_neigh(who, n, arg);
> diff --git a/ip/ipneigh.c b/ip/ipneigh.c
> index 56e56b2..1b7600b 100644
> - --- a/ip/ipneigh.c
> +++ b/ip/ipneigh.c
> @@ -189,7 +189,8 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
> struct rtattr * tb[NDA_MAX+1];
> char abuf[256];
>
> - - if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) {
> + if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
> + n->nlmsg_type != RTM_GETNEIGH) {
> fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n",
> n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
>
> @@ -251,6 +252,8 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
>
> if (n->nlmsg_type == RTM_DELNEIGH)
> fprintf(fp, "delete ");
> + else if (n->nlmsg_type == RTM_GETNEIGH)
> + fprintf(fp, "miss ");
> if (tb[NDA_DST]) {
> fprintf(fp, "%s ",
> format_host(r->ndm_family,
>
This patch doesn't apply cleanly against the current version in iproute2 git.
Not your fault, conflicts arose from earlier patches applied. Could you fix
the conflicts and resubmit please.
^ permalink raw reply
* Re: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'
From: Stephen Hemminger @ 2012-12-12 17:11 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev
In-Reply-To: <1355305907-7102-3-git-send-email-nicolas.dichtel@6wind.com>
On Wed, 12 Dec 2012 10:51:47 +0100
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:
> This patch allows to manage ip tunnels via the interface ip link.
> The syntax for parameters is the same that 'ip tunnel'.
>
> It also allows to display tunnels parameters with 'ip -details link' or
> 'ip -details monitor link'.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> ip/Makefile | 3 +-
> ip/iplink.c | 2 +-
> ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 343 insertions(+), 2 deletions(-)
> create mode 100644 ip/link_iptnl.c
>
> diff --git a/ip/Makefile b/ip/Makefile
> index abf54bf..2b606d4 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
> ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
> iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
> iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
> - iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
> + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
> + link_iptnl.o
>
> RTMONOBJ=rtmon.o
>
> diff --git a/ip/iplink.c b/ip/iplink.c
> index 8aac9fc..d73c705 100644
> --- a/ip/iplink.c
> +++ b/ip/iplink.c
> @@ -84,7 +84,7 @@ void iplink_usage(void)
> if (iplink_have_newlink()) {
> fprintf(stderr, "\n");
> fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
> - fprintf(stderr, " bridge | ipoib | ip6tnl }\n");
> + fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit }\n");
> }
> exit(-1);
> }
> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
> new file mode 100644
> index 0000000..238722d
> --- /dev/null
> +++ b/ip/link_iptnl.c
> @@ -0,0 +1,340 @@
> +/*
> + * link_iptnl.c ipip and sit driver module
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + * Authors: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> + *
> + */
> +
> +#include <string.h>
> +#include <net/if.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <arpa/inet.h>
> +
> +#include <linux/ip.h>
> +#include <linux/if_tunnel.h>
> +#include "rt_names.h"
> +#include "utils.h"
> +#include "ip_common.h"
> +#include "tunnel.h"
> +
> +static void usage(int sit) __attribute__((noreturn));
> +static void usage(int sit)
> +{
> + fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
> + fprintf(stderr, " type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
> + fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
> + fprintf(stderr, " [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
> + if (sit)
> + fprintf(stderr, " [ isatap ]\n");
> + fprintf(stderr, "\n");
> + fprintf(stderr, "Where: NAME := STRING\n");
> + fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
> + fprintf(stderr, " TOS := { NUMBER | inherit }\n");
> + fprintf(stderr, " TTL := { 1..255 | inherit }\n");
> + exit(-1);
> +}
> +
> +static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
> + struct nlmsghdr *n)
> +{
> + struct {
> + struct nlmsghdr n;
> + struct ifinfomsg i;
> + char buf[2048];
> + } req;
> + struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
> + struct rtattr *tb[IFLA_MAX + 1];
> + struct rtattr *linkinfo[IFLA_INFO_MAX+1];
> + struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
> + int len;
> + __u32 link = 0;
> + __u32 laddr = 0;
> + __u32 raddr = 0;
> + __u8 ttl = 0;
> + __u8 tos = 0;
> + __u8 pmtudisc = 1;
> + __u16 iflags = 0;
> + struct in6_addr ip6rdprefix;
> + __u16 ip6rdprefixlen = 0;
> + __u32 ip6rdrelayprefix = 0;
> + __u16 ip6rdrelayprefixlen = 0;
> +
> + memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
> +
> + if (!(n->nlmsg_flags & NLM_F_CREATE)) {
> + memset(&req, 0, sizeof(req));
> +
> + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
> + req.n.nlmsg_flags = NLM_F_REQUEST;
> + req.n.nlmsg_type = RTM_GETLINK;
> + req.i.ifi_family = preferred_family;
> + req.i.ifi_index = ifi->ifi_index;
> +
> + if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
> +get_failed:
> + fprintf(stderr,
> + "Failed to get existing tunnel info.\n");
> + return -1;
> + }
> +
> + len = req.n.nlmsg_len;
> + len -= NLMSG_LENGTH(sizeof(*ifi));
> + if (len < 0)
> + goto get_failed;
> +
> + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
> +
> + if (!tb[IFLA_LINKINFO])
> + goto get_failed;
> +
> + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
> +
> + if (!linkinfo[IFLA_INFO_DATA])
> + goto get_failed;
> +
> + parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
> + linkinfo[IFLA_INFO_DATA]);
> +
> + if (iptuninfo[IFLA_IPTUN_LOCAL])
> + laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
> +
> + if (iptuninfo[IFLA_IPTUN_REMOTE])
> + raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
> +
> + if (iptuninfo[IFLA_IPTUN_TTL])
> + ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
> +
> + if (iptuninfo[IFLA_IPTUN_TOS])
> + tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
> +
> + if (iptuninfo[IFLA_IPTUN_PMTUDISC])
> + pmtudisc =
> + rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
> +
> + if (iptuninfo[IFLA_IPTUN_FLAGS])
> + iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
> +
> + if (iptuninfo[IFLA_IPTUN_LINK])
> + link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
> +
> + if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
> + memcpy(&ip6rdprefix,
> + RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
> + sizeof(laddr));
> +
> + if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
> + ip6rdprefixlen =
> + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
> +
> + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
> + ip6rdrelayprefix =
> + rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
> +
> + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
> + ip6rdrelayprefixlen =
> + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
> + }
> +
> + while (argc > 0) {
> + if (strcmp(*argv, "remote") == 0) {
> + NEXT_ARG();
> + if (strcmp(*argv, "any"))
> + raddr = get_addr32(*argv);
> + else
> + raddr = 0;
> + } else if (strcmp(*argv, "local") == 0) {
> + NEXT_ARG();
> + if (strcmp(*argv, "any"))
> + laddr = get_addr32(*argv);
> + else
> + laddr = 0;
> + } else if (matches(*argv, "dev") == 0) {
> + NEXT_ARG();
> + link = if_nametoindex(*argv);
> + if (link == 0)
> + invarg("\"dev\" is invalid", *argv);
> + } else if (strcmp(*argv, "ttl") == 0 ||
> + strcmp(*argv, "hoplimit") == 0) {
> + NEXT_ARG();
> + if (strcmp(*argv, "inherit") != 0) {
> + if (get_u8(&ttl, *argv, 0))
> + invarg("invalid TTL\n", *argv);
> + } else
> + ttl = 0;
> + } else if (strcmp(*argv, "tos") == 0 ||
> + strcmp(*argv, "tclass") == 0 ||
> + matches(*argv, "dsfield") == 0) {
> + __u32 uval;
> + NEXT_ARG();
> + if (strcmp(*argv, "inherit") != 0) {
> + if (rtnl_dsfield_a2n(&uval, *argv))
> + invarg("bad TOS value", *argv);
> + tos = uval;
> + } else
> + tos = 1;
> + } else if (strcmp(*argv, "nopmtudisc") == 0) {
> + pmtudisc = 0;
> + } else if (strcmp(*argv, "pmtudisc") == 0) {
> + pmtudisc = 1;
> + } else if (strcmp(lu->id, "sit") == 0 &&
> + strcmp(*argv, "isatap") == 0) {
> + iflags |= SIT_ISATAP;
> + } else if (strcmp(*argv, "6rd-prefix") == 0) {
> + inet_prefix prefix;
> + NEXT_ARG();
> + if (get_prefix(&prefix, *argv, AF_INET6))
> + invarg("invalid 6rd_prefix\n", *argv);
> + memcpy(&ip6rdprefix, prefix.data, 16);
> + ip6rdprefixlen = prefix.bitlen;
> + } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
> + inet_prefix prefix;
> + NEXT_ARG();
> + if (get_prefix(&prefix, *argv, AF_INET))
> + invarg("invalid 6rd-relay_prefix\n", *argv);
> + memcpy(&ip6rdrelayprefix, prefix.data, 4);
> + ip6rdrelayprefixlen = prefix.bitlen;
> + } else if (strcmp(*argv, "6rd-reset") == 0) {
> + inet_prefix prefix;
> + get_prefix(&prefix, "2002::", AF_INET6);
> + memcpy(&ip6rdprefix, prefix.data, 16);
> + ip6rdprefixlen = 16;
> + ip6rdrelayprefix = 0;
> + ip6rdrelayprefixlen = 0;
> + } else
> + usage(strcmp(lu->id, "sit") == 0);
> + argc--, argv++;
> + }
> +
> + if (ttl && pmtudisc == 0) {
> + fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
> + exit(-1);
> + }
> +
> + addattr32(n, 1024, IFLA_IPTUN_LINK, link);
> + addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
> + addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
> + addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
> + addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
> + addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
> + if (strcmp(lu->id, "sit") == 0) {
> + addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
> + if (ip6rdprefixlen) {
> + addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
> + &ip6rdprefix, sizeof(ip6rdprefix));
> + addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
> + ip6rdprefixlen);
> + addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
> + ip6rdrelayprefix);
> + addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
> + ip6rdrelayprefixlen);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
> +{
> + char s1[1024];
> + char s2[64];
> + const char *local = "any";
> + const char *remote = "any";
> +
> + if (!tb)
> + return;
> +
> + if (tb[IFLA_IPTUN_REMOTE]) {
> + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
> +
> + if (addr)
> + remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
> + }
> +
> + fprintf(f, "remote %s ", remote);
> +
> + if (tb[IFLA_IPTUN_LOCAL]) {
> + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
> +
> + if (addr)
> + local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
> + }
> +
> + fprintf(f, "local %s ", local);
> +
> + if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
> + unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
> + const char *n = if_indextoname(link, s2);
> +
> + if (n)
> + fprintf(f, "dev %s ", n);
> + else
> + fprintf(f, "dev %u ", link);
> + }
> +
> + if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
> + fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
> + else
> + fprintf(f, "ttl inherit ");
> +
> + if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
> + int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
> +
> + fputs("tos ", f);
> + if (tos == 1)
> + fputs("inherit ", f);
> + else
> + fprintf(f, "0x%x ", tos);
> + }
> +
> + if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
> + fprintf(f, "pmtudisc ");
> + else
> + fprintf(f, "nopmtudisc ");
> +
> + if (tb[IFLA_IPTUN_FLAGS]) {
> + __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
> +
> + if (iflags & SIT_ISATAP)
> + fprintf(f, "isatap ");
> + }
> +
> + if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
> + *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
> + __u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
> + __u16 relayprefixlen =
> + rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
> + __u32 relayprefix =
> + rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
> +
> + printf("6rd-prefix %s/%u ",
> + inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
> + s1, sizeof(s1)),
> + prefixlen);
> + if (relayprefix) {
> + printf("6rd-relay_prefix %s/%u ",
> + format_host(AF_INET, 4, &relayprefix, s1,
> + sizeof(s1)),
> + relayprefixlen);
> + }
> + }
> +}
> +
> +struct link_util ipip_link_util = {
> + .id = "ipip",
> + .maxattr = IFLA_IPTUN_MAX,
> + .parse_opt = iptunnel_parse_opt,
> + .print_opt = iptunnel_print_opt,
> +};
> +
> +struct link_util sit_link_util = {
> + .id = "sit",
> + .maxattr = IFLA_IPTUN_MAX,
> + .parse_opt = iptunnel_parse_opt,
> + .print_opt = iptunnel_print_opt,
> +};
All applied with minor corrections to header files.
Could you please add man pages for this new functionality?
^ permalink raw reply
* Re: [patch net-next 0/4] net: allow to change carrier from userspace
From: Jiri Pirko @ 2012-12-12 17:05 UTC (permalink / raw)
To: Stephen Hemminger
Cc: netdev, davem, edumazet, bhutchings, mirqus, greearb, fbl
In-Reply-To: <20121212081500.24085752@nehalam.linuxnetplumber.net>
Wed, Dec 12, 2012 at 05:15:00PM CET, shemminger@vyatta.com wrote:
>On Wed, 12 Dec 2012 11:58:03 +0100
>Jiri Pirko <jiri@resnulli.us> wrote:
>
>> This is basically a repost of my previous patchset:
>> "[patch net-next-2.6 0/2] net: allow to change carrier via sysfs" from Aug 30
>>
>> The way net-sysfs stores values changed and this patchset reflects it.
>> Also, I exposed carrier via rtnetlink iface.
>>
>> So far, only dummy driver uses carrier change ndo. In very near future
>> team driver will use that as well.
>>
>> Jiri Pirko (4):
>> net: add change_carrier netdev op
>> net: allow to change carrier via sysfs
>> rtnl: expose carrier value with possibility to set it
>> dummy: implement carrier change
>>
>> drivers/net/dummy.c | 10 ++++++++++
>> include/linux/netdevice.h | 7 +++++++
>> include/uapi/linux/if_link.h | 1 +
>> net/core/dev.c | 19 +++++++++++++++++++
>> net/core/net-sysfs.c | 15 ++++++++++++++-
>> net/core/rtnetlink.c | 10 ++++++++++
>> 6 files changed, 61 insertions(+), 1 deletion(-)
>>
>
>I needed to do the same thing for a project we are working on and discovered
>that there already is a working documented interface for doing that via
>operstate mode. Therefore I can't recommend that the additional complexity
>of a new API for this is required.
I might be missing something, but I'm unable to find how operstate set
can affect value returned by netif_carrier_ok()
^ permalink raw reply
* Re: [PATCH net-next] uapi: add missing netconf.h to export list
From: Nicolas Dichtel @ 2012-12-12 17:04 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20121212085852.5b840314@nehalam.linuxnetplumber.net>
Le 12/12/2012 17:58, Stephen Hemminger a écrit :
> Add netconf.h for use by iproute2.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>
> --- a/include/uapi/linux/Kbuild 2012-10-25 09:11:15.499273810 -0700
> +++ b/include/uapi/linux/Kbuild 2012-12-12 08:56:36.130263710 -0800
> @@ -258,6 +258,7 @@ header-y += neighbour.h
> header-y += net.h
> header-y += net_dropmon.h
> header-y += net_tstamp.h
> +header-y += netconf.h
> header-y += netdevice.h
> header-y += netfilter.h
> header-y += netfilter_arp.h
>
^ permalink raw reply
* Re: [PATCH iproute2 1/3] ip: add support of netconf messages
From: Nicolas Dichtel @ 2012-12-12 17:03 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20121212085959.31d8cd79@nehalam.linuxnetplumber.net>
Le 12/12/2012 17:59, Stephen Hemminger a écrit :
> Ok, but the headers for all of iproute2 are supposed to come from
> sanitized kernel headers from "make headers_install"
>
> You missed that piece in the original patch.
>
Right! I will update the patch.
^ permalink raw reply
* Re: [PATCH iproute2 1/3] ip: add support of netconf messages
From: Stephen Hemminger @ 2012-12-12 16:59 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: netdev
In-Reply-To: <1355305907-7102-1-git-send-email-nicolas.dichtel@6wind.com>
Ok, but the headers for all of iproute2 are supposed to come from
sanitized kernel headers from "make headers_install"
You missed that piece in the original patch.
^ 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