Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 5/9] sctp: Make the ctl_sock per network namespace
From: Eric W. Biederman @ 2012-08-06 18:43 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87zk67q31q.fsf_-_@xmission.com>


- Kill sctp_get_ctl_sock, it is useless now.
- Pass struct net where needed so net->sctp.ctl_sock is accessible.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 include/net/netns/sctp.h |    8 +++++++
 include/net/sctp/sctp.h  |    1 -
 net/sctp/input.c         |    4 +-
 net/sctp/protocol.c      |   47 ++++++++++++++++++---------------------------
 net/sctp/sm_statefuns.c  |   45 ++++++++++++++++++++++++++++++-------------
 5 files changed, 60 insertions(+), 45 deletions(-)

diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index cbd684e..29e36b4 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -1,7 +1,15 @@
 #ifndef __NETNS_SCTP_H__
 #define __NETNS_SCTP_H__
 
+struct sock;
+
 struct netns_sctp {
+	/* This is the global socket data structure used for responding to
+	 * the Out-of-the-blue (OOTB) packets.  A control sock will be created
+	 * for this socket at the initialization time.
+	 */
+	struct sock *ctl_sock;
+
 	/* This is the global local address list.
 	 * We actively maintain this complete list of addresses on
 	 * the system by catching address add/delete events.
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 00c9205..550a81b 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -114,7 +114,6 @@
 /*
  * sctp/protocol.c
  */
-extern struct sock *sctp_get_ctl_sock(void);
 extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
 				     sctp_scope_t, gfp_t gfp,
 				     int flags);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index a7e9a85..c9a0449 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -204,7 +204,7 @@ int sctp_rcv(struct sk_buff *skb)
 			sctp_endpoint_put(ep);
 			ep = NULL;
 		}
-		sk = sctp_get_ctl_sock();
+		sk = net->sctp.ctl_sock;
 		ep = sctp_sk(sk)->ep;
 		sctp_endpoint_hold(ep);
 		rcvr = &ep->base;
@@ -795,7 +795,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
 			goto hit;
 	}
 
-	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+	ep = sctp_sk(net->sctp.ctl_sock)->ep;
 
 hit:
 	sctp_endpoint_hold(ep);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 291e682..6193d20 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -78,12 +78,6 @@ struct proc_dir_entry	*proc_net_sctp;
 struct idr sctp_assocs_id;
 DEFINE_SPINLOCK(sctp_assocs_id_lock);
 
-/* This is the global socket data structure used for responding to
- * the Out-of-the-blue (OOTB) packets.  A control sock will be created
- * for this socket at the initialization time.
- */
-static struct sock *sctp_ctl_sock;
-
 static struct sctp_pf *sctp_pf_inet6_specific;
 static struct sctp_pf *sctp_pf_inet_specific;
 static struct sctp_af *sctp_af_v4_specific;
@@ -96,12 +90,6 @@ long sysctl_sctp_mem[3];
 int sysctl_sctp_rmem[3];
 int sysctl_sctp_wmem[3];
 
-/* Return the address of the control sock. */
-struct sock *sctp_get_ctl_sock(void)
-{
-	return sctp_ctl_sock;
-}
-
 /* Set up the proc fs entry for the SCTP protocol. */
 static __init int sctp_proc_init(void)
 {
@@ -822,7 +810,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
  * Initialize the control inode/socket with a control endpoint data
  * structure.  This endpoint is reserved exclusively for the OOTB processing.
  */
-static int sctp_ctl_sock_init(void)
+static int sctp_ctl_sock_init(struct net *net)
 {
 	int err;
 	sa_family_t family = PF_INET;
@@ -830,14 +818,14 @@ static int sctp_ctl_sock_init(void)
 	if (sctp_get_pf_specific(PF_INET6))
 		family = PF_INET6;
 
-	err = inet_ctl_sock_create(&sctp_ctl_sock, family,
-				   SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
+	err = inet_ctl_sock_create(&net->sctp.ctl_sock, family,
+				   SOCK_SEQPACKET, IPPROTO_SCTP, net);
 
 	/* If IPv6 socket could not be created, try the IPv4 socket */
 	if (err < 0 && family == PF_INET6)
-		err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET,
+		err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET,
 					   SOCK_SEQPACKET, IPPROTO_SCTP,
-					   &init_net);
+					   net);
 
 	if (err < 0) {
 		pr_err("Failed to create the SCTP control socket\n");
@@ -1196,6 +1184,14 @@ static void sctp_v4_del_protocol(void)
 
 static int sctp_net_init(struct net *net)
 {
+	int status;
+
+	/* Initialize the control inode/socket for handling OOTB packets.  */
+	if ((status = sctp_ctl_sock_init(net))) {
+		pr_err("Failed to initialize the SCTP control sock\n");
+		goto err_ctl_sock_init;
+	}
+
 	/* Initialize the local address list. */
 	INIT_LIST_HEAD(&net->sctp.local_addr_list);
 	spin_lock_init(&net->sctp.local_addr_lock);
@@ -1210,6 +1206,9 @@ static int sctp_net_init(struct net *net)
 		    (unsigned long)net);
 
 	return 0;
+
+err_ctl_sock_init:
+	return status;
 }
 
 static void sctp_net_exit(struct net *net)
@@ -1217,6 +1216,9 @@ static void sctp_net_exit(struct net *net)
 	/* Free the local address list */
 	sctp_free_addr_wq(net);
 	sctp_free_local_addr_list(net);
+
+	/* Free the control endpoint.  */
+	inet_ctl_sock_destroy(net->sctp.ctl_sock);
 }
 
 static struct pernet_operations sctp_net_ops = {
@@ -1438,12 +1440,6 @@ SCTP_STATIC __init int sctp_init(void)
 	if (status)
 		goto err_v6_protosw_init;
 
-	/* Initialize the control inode/socket for handling OOTB packets.  */
-	if ((status = sctp_ctl_sock_init())) {
-		pr_err("Failed to initialize the SCTP control sock\n");
-		goto err_ctl_sock_init;
-	}
-
 	status = register_pernet_subsys(&sctp_net_ops);
 	if (status)
 		goto err_register_pernet_subsys;
@@ -1465,8 +1461,6 @@ err_v6_add_protocol:
 err_add_protocol:
 	unregister_pernet_subsys(&sctp_net_ops);
 err_register_pernet_subsys:
-	inet_ctl_sock_destroy(sctp_ctl_sock);
-err_ctl_sock_init:
 	sctp_v6_protosw_exit();
 err_v6_protosw_init:
 	sctp_v4_protosw_exit();
@@ -1506,9 +1500,6 @@ SCTP_STATIC __exit void sctp_exit(void)
 	sctp_v6_del_protocol();
 	sctp_v4_del_protocol();
 
-	/* Free the control endpoint.  */
-	inet_ctl_sock_destroy(sctp_ctl_sock);
-
 	unregister_pernet_subsys(&sctp_net_ops);
 
 	/* Free protosw registrations */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 9fca103..f2daf61 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -74,7 +74,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
 static int sctp_eat_data(const struct sctp_association *asoc,
 			 struct sctp_chunk *chunk,
 			 sctp_cmd_seq_t *commands);
-static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
+					     const struct sctp_association *asoc,
 					     const struct sctp_chunk *chunk);
 static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
 				       const struct sctp_association *asoc,
@@ -301,6 +302,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
 	struct sctp_chunk *err_chunk;
 	struct sctp_packet *packet;
 	sctp_unrecognized_param_t *unk_param;
+	struct net *net;
 	int len;
 
 	/* 6.10 Bundling
@@ -318,7 +320,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
 	/* If the packet is an OOTB packet which is temporarily on the
 	 * control endpoint, respond with an ABORT.
 	 */
-	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
+	net = sock_net(ep->base.sk);
+	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
 		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 	}
@@ -646,11 +649,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
 	int error = 0;
 	struct sctp_chunk *err_chk_p;
 	struct sock *sk;
+	struct net *net;
 
 	/* If the packet is an OOTB packet which is temporarily on the
 	 * control endpoint, respond with an ABORT.
 	 */
-	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) {
+	net = sock_net(ep->base.sk);
+	if (ep == sctp_sk(net->sctp.ctl_sock)->ep) {
 		SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES);
 		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
 	}
@@ -1171,7 +1176,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
 /* Helper function to send out an abort for the restart
  * condition.
  */
-static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
+static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
 				      struct sctp_chunk *init,
 				      sctp_cmd_seq_t *commands)
 {
@@ -1197,7 +1202,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
 	errhdr->length = htons(len);
 
 	/* Assign to the control socket. */
-	ep = sctp_sk((sctp_get_ctl_sock()))->ep;
+	ep = sctp_sk(net->sctp.ctl_sock)->ep;
 
 	/* Association is NULL since this may be a restart attack and we
 	 * want to send back the attacker's vtag.
@@ -1240,6 +1245,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
 				       struct sctp_chunk *init,
 				       sctp_cmd_seq_t *commands)
 {
+	struct net *net = sock_net(new_asoc->base.sk);
 	struct sctp_transport *new_addr;
 	int ret = 1;
 
@@ -1258,7 +1264,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
 			    transports) {
 		if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
 					&new_addr->ipaddr)) {
-			sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
+			sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init,
 						   commands);
 			ret = 0;
 			break;
@@ -1650,10 +1656,11 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,
 					    const sctp_subtype_t type,
 					    void *arg, sctp_cmd_seq_t *commands)
 {
+	struct net *net = sock_net(ep->base.sk);
 	/* Per the above section, we'll discard the chunk if we have an
 	 * endpoint.  If this is an OOTB INIT-ACK, treat it as such.
 	 */
-	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
+	if (ep == sctp_sk(net->sctp.ctl_sock)->ep)
 		return sctp_sf_ootb(ep, asoc, type, arg, commands);
 	else
 		return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);
@@ -3163,8 +3170,10 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
 	struct sctp_packet *packet = NULL;
 	struct sctp_chunk *chunk = arg;
 	struct sctp_chunk *abort;
+	struct net *net;
 
-	packet = sctp_ootb_pkt_new(asoc, chunk);
+	net = sock_net(ep->base.sk);
+	packet = sctp_ootb_pkt_new(net, asoc, chunk);
 
 	if (packet) {
 		/* Make an ABORT. The T bit will be set if the asoc
@@ -3425,8 +3434,10 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
 	struct sctp_packet *packet = NULL;
 	struct sctp_chunk *chunk = arg;
 	struct sctp_chunk *shut;
+	struct net *net;
 
-	packet = sctp_ootb_pkt_new(asoc, chunk);
+	net = sock_net(ep->base.sk);
+	packet = sctp_ootb_pkt_new(net, asoc, chunk);
 
 	if (packet) {
 		/* Make an SHUTDOWN_COMPLETE.
@@ -4262,6 +4273,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
 	struct sctp_packet *packet = NULL;
 	struct sctp_chunk *chunk =  arg;
 	struct sctp_chunk *abort = NULL;
+	struct net *net;
 
 	/* SCTP-AUTH, Section 6.3:
 	 *    It should be noted that if the receiver wants to tear
@@ -4282,6 +4294,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
 	if (!abort)
 		goto nomem;
 
+	net = sock_net(ep->base.sk);
 	if (asoc) {
 		/* Treat INIT-ACK as a special case during COOKIE-WAIT. */
 		if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK &&
@@ -4319,7 +4332,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
 			SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
 		}
 	} else {
-		packet = sctp_ootb_pkt_new(asoc, chunk);
+		packet = sctp_ootb_pkt_new(net, asoc, chunk);
 
 		if (!packet)
 			goto nomem_pkt;
@@ -5825,8 +5838,10 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
 {
 	struct sctp_packet *packet;
 	struct sctp_chunk *abort;
+	struct net *net;
 
-	packet = sctp_ootb_pkt_new(asoc, chunk);
+	net = sock_net(ep->base.sk);
+	packet = sctp_ootb_pkt_new(net, asoc, chunk);
 
 	if (packet) {
 		/* Make an ABORT.
@@ -5858,7 +5873,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
 }
 
 /* Allocate a packet for responding in the OOTB conditions.  */
-static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
+static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
+					     const struct sctp_association *asoc,
 					     const struct sctp_chunk *chunk)
 {
 	struct sctp_packet *packet;
@@ -5919,7 +5935,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
 	 * the source address.
 	 */
 	sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
-			     sctp_sk(sctp_get_ctl_sock()));
+			     sctp_sk(net->sctp.ctl_sock));
 
 	packet = sctp_packet_init(&transport->packet, transport, sport, dport);
 	packet = sctp_packet_config(packet, vtag, 0);
@@ -5946,7 +5962,8 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
 	struct sctp_packet *packet;
 
 	if (err_chunk) {
-		packet = sctp_ootb_pkt_new(asoc, chunk);
+		struct net *net = sock_net(ep->base.sk);
+		packet = sctp_ootb_pkt_new(net, asoc, chunk);
 		if (packet) {
 			struct sctp_signed_cookie *cookie;
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH net-next 4/9] sctp: Make the address lists per network namespace
From: Eric W. Biederman @ 2012-08-06 18:42 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87zk67q31q.fsf_-_@xmission.com>


- Move the address lists into struct net
- Add per network namespace initialization and cleanup
- Pass around struct net so it is everywhere I need it.
- Rename all of the global variable references into references
  to the variables moved into struct net

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 include/net/net_namespace.h |    4 +
 include/net/netns/sctp.h    |   21 +++++++
 include/net/sctp/sctp.h     |    4 +-
 include/net/sctp/structs.h  |   22 +-------
 net/sctp/associola.c        |    3 +-
 net/sctp/bind_addr.c        |   14 ++--
 net/sctp/ipv6.c             |   17 +++---
 net/sctp/protocol.c         |  141 +++++++++++++++++++++++++------------------
 net/sctp/socket.c           |    7 +-
 9 files changed, 131 insertions(+), 102 deletions(-)
 create mode 100644 include/net/netns/sctp.h

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ae1cd6c..8ab5250 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -15,6 +15,7 @@
 #include <net/netns/packet.h>
 #include <net/netns/ipv4.h>
 #include <net/netns/ipv6.h>
+#include <net/netns/sctp.h>
 #include <net/netns/dccp.h>
 #include <net/netns/x_tables.h>
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -80,6 +81,9 @@ struct net {
 #if IS_ENABLED(CONFIG_IPV6)
 	struct netns_ipv6	ipv6;
 #endif
+#if defined(CONFIG_IP_SCTP) || defined(CONFIG_IP_SCTP_MODULE)
+	struct netns_sctp	sctp;
+#endif
 #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
 	struct netns_dccp	dccp;
 #endif
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
new file mode 100644
index 0000000..cbd684e
--- /dev/null
+++ b/include/net/netns/sctp.h
@@ -0,0 +1,21 @@
+#ifndef __NETNS_SCTP_H__
+#define __NETNS_SCTP_H__
+
+struct netns_sctp {
+	/* This is the global local address list.
+	 * We actively maintain this complete list of addresses on
+	 * the system by catching address add/delete events.
+	 *
+	 * It is a list of sctp_sockaddr_entry.
+	 */
+	struct list_head local_addr_list;
+	struct list_head addr_waitq;
+	struct timer_list addr_wq_timer;
+	struct list_head auto_asconf_splist;
+	spinlock_t addr_wq_lock;
+
+	/* Lock that protects the local_addr_list writers */
+	spinlock_t local_addr_lock;
+};
+
+#endif /* __NETNS_SCTP_H__ */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 640915a..00c9205 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -115,12 +115,12 @@
  * sctp/protocol.c
  */
 extern struct sock *sctp_get_ctl_sock(void);
-extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
+extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
 				     sctp_scope_t, gfp_t gfp,
 				     int flags);
 extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
 extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
-extern void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *, int);
+extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
 
 /*
  * sctp/socket.c
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index c0563d1..6bdfcab 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -205,21 +205,7 @@ extern struct sctp_globals {
 	int port_hashsize;
 	struct sctp_bind_hashbucket *port_hashtable;
 
-	/* This is the global local address list.
-	 * We actively maintain this complete list of addresses on
-	 * the system by catching address add/delete events.
-	 *
-	 * It is a list of sctp_sockaddr_entry.
-	 */
-	struct list_head local_addr_list;
 	int default_auto_asconf;
-	struct list_head addr_waitq;
-	struct timer_list addr_wq_timer;
-	struct list_head auto_asconf_splist;
-	spinlock_t addr_wq_lock;
-
-	/* Lock that protects the local_addr_list writers */
-	spinlock_t addr_list_lock;
 	
 	/* Flag to indicate if addip is enabled. */
 	int addip_enable;
@@ -278,12 +264,6 @@ extern struct sctp_globals {
 #define sctp_assoc_hashtable		(sctp_globals.assoc_hashtable)
 #define sctp_port_hashsize		(sctp_globals.port_hashsize)
 #define sctp_port_hashtable		(sctp_globals.port_hashtable)
-#define sctp_local_addr_list		(sctp_globals.local_addr_list)
-#define sctp_local_addr_lock		(sctp_globals.addr_list_lock)
-#define sctp_auto_asconf_splist		(sctp_globals.auto_asconf_splist)
-#define sctp_addr_waitq			(sctp_globals.addr_waitq)
-#define sctp_addr_wq_timer		(sctp_globals.addr_wq_timer)
-#define sctp_addr_wq_lock		(sctp_globals.addr_wq_lock)
 #define sctp_default_auto_asconf	(sctp_globals.default_auto_asconf)
 #define sctp_scope_policy		(sctp_globals.ipv4_scope_policy)
 #define sctp_addip_enable		(sctp_globals.addip_enable)
@@ -1241,7 +1221,7 @@ struct sctp_bind_addr {
 
 void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
 void sctp_bind_addr_free(struct sctp_bind_addr *);
-int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
 			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, gfp_t gfp,
 			int flags);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index a3601f3..ed4930b 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1544,7 +1544,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
 	if (asoc->peer.ipv6_address)
 		flags |= SCTP_ADDR6_PEERSUPP;
 
-	return sctp_bind_addr_copy(&asoc->base.bind_addr,
+	return sctp_bind_addr_copy(sock_net(asoc->base.sk),
+				   &asoc->base.bind_addr,
 				   &asoc->ep->base.bind_addr,
 				   scope, gfp, flags);
 }
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 4ece451..a85ce4b 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -52,8 +52,8 @@
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers. */
-static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
-			      sctp_scope_t scope, gfp_t gfp,
+static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
+			      union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
 			      int flags);
 static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 
@@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
  * in 'src' which have a broader scope than 'scope'.
  */
-int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
+int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
 			const struct sctp_bind_addr *src,
 			sctp_scope_t scope, gfp_t gfp,
 			int flags)
@@ -75,7 +75,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
 
 	/* Extract the addresses which are relevant for this scope.  */
 	list_for_each_entry(addr, &src->address_list, list) {
-		error = sctp_copy_one_addr(dest, &addr->a, scope,
+		error = sctp_copy_one_addr(net, dest, &addr->a, scope,
 					   gfp, flags);
 		if (error < 0)
 			goto out;
@@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
 	 */
 	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
 		list_for_each_entry(addr, &src->address_list, list) {
-			error = sctp_copy_one_addr(dest, &addr->a,
+			error = sctp_copy_one_addr(net, dest, &addr->a,
 						   SCTP_SCOPE_LINK, gfp,
 						   flags);
 			if (error < 0)
@@ -448,7 +448,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
 }
 
 /* Copy out addresses from the global local address list. */
-static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
+static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
 			      union sctp_addr *addr,
 			      sctp_scope_t scope, gfp_t gfp,
 			      int flags)
@@ -456,7 +456,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
 	int error = 0;
 
 	if (sctp_is_any(NULL, addr)) {
-		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
+		error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
 	} else if (sctp_in_scope(addr, scope)) {
 		/* Now that the address is in scope, check to see if
 		 * the address type is supported by local sock as
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 2165a7e..bbf1534 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
 	struct sctp_sockaddr_entry *addr = NULL;
 	struct sctp_sockaddr_entry *temp;
+	struct net *net = dev_net(ifa->idev->dev);
 	int found = 0;
 
 	switch (ev) {
@@ -110,27 +111,27 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 			addr->a.v6.sin6_addr = ifa->addr;
 			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
 			addr->valid = 1;
-			spin_lock_bh(&sctp_local_addr_lock);
-			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
-			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
-			spin_unlock_bh(&sctp_local_addr_lock);
+			spin_lock_bh(&net->sctp.local_addr_lock);
+			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
+			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+			spin_unlock_bh(&net->sctp.local_addr_lock);
 		}
 		break;
 	case NETDEV_DOWN:
-		spin_lock_bh(&sctp_local_addr_lock);
+		spin_lock_bh(&net->sctp.local_addr_lock);
 		list_for_each_entry_safe(addr, temp,
-					&sctp_local_addr_list, list) {
+					&net->sctp.local_addr_list, list) {
 			if (addr->a.sa.sa_family == AF_INET6 &&
 					ipv6_addr_equal(&addr->a.v6.sin6_addr,
 						&ifa->addr)) {
-				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
+				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 				found = 1;
 				addr->valid = 0;
 				list_del_rcu(&addr->list);
 				break;
 			}
 		}
-		spin_unlock_bh(&sctp_local_addr_lock);
+		spin_unlock_bh(&net->sctp.local_addr_lock);
 		if (found)
 			kfree_rcu(addr, rcu);
 		break;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 1f89c4e..291e682 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -201,29 +201,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
 /* Extract our IP addresses from the system and stash them in the
  * protocol structure.
  */
-static void sctp_get_local_addr_list(void)
+static void sctp_get_local_addr_list(struct net *net)
 {
 	struct net_device *dev;
 	struct list_head *pos;
 	struct sctp_af *af;
 
 	rcu_read_lock();
-	for_each_netdev_rcu(&init_net, dev) {
+	for_each_netdev_rcu(net, dev) {
 		__list_for_each(pos, &sctp_address_families) {
 			af = list_entry(pos, struct sctp_af, list);
-			af->copy_addrlist(&sctp_local_addr_list, dev);
+			af->copy_addrlist(&net->sctp.local_addr_list, dev);
 		}
 	}
 	rcu_read_unlock();
 }
 
 /* Free the existing local addresses.  */
-static void sctp_free_local_addr_list(void)
+static void sctp_free_local_addr_list(struct net *net)
 {
 	struct sctp_sockaddr_entry *addr;
 	struct list_head *pos, *temp;
 
-	list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+	list_for_each_safe(pos, temp, &net->sctp.local_addr_list) {
 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		list_del(pos);
 		kfree(addr);
@@ -231,14 +231,14 @@ static void sctp_free_local_addr_list(void)
 }
 
 /* Copy the local addresses which are valid for 'scope' into 'bp'.  */
-int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
-			      gfp_t gfp, int copy_flags)
+int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
+			      sctp_scope_t scope, gfp_t gfp, int copy_flags)
 {
 	struct sctp_sockaddr_entry *addr;
 	int error = 0;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
 		if (!addr->valid)
 			continue;
 		if (sctp_in_scope(&addr->a, scope)) {
@@ -627,14 +627,15 @@ static void sctp_v4_ecn_capable(struct sock *sk)
 
 void sctp_addr_wq_timeout_handler(unsigned long arg)
 {
+	struct net *net = (struct net *)arg;
 	struct sctp_sockaddr_entry *addrw, *temp;
 	struct sctp_sock *sp;
 
-	spin_lock_bh(&sctp_addr_wq_lock);
+	spin_lock_bh(&net->sctp.addr_wq_lock);
 
-	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
 		SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ",
-		    " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state,
+		    " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state,
 		    addrw);
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -648,7 +649,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
 				goto free_next;
 
 			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
-			if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 &&
+			if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
 			    addrw->state == SCTP_ADDR_NEW) {
 				unsigned long timeo_val;
 
@@ -656,12 +657,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
 				    SCTP_ADDRESS_TICK_DELAY);
 				timeo_val = jiffies;
 				timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
-				mod_timer(&sctp_addr_wq_timer, timeo_val);
+				mod_timer(&net->sctp.addr_wq_timer, timeo_val);
 				break;
 			}
 		}
 #endif
-		list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) {
+		list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) {
 			struct sock *sk;
 
 			sk = sctp_opt2sk(sp);
@@ -679,31 +680,32 @@ free_next:
 		list_del(&addrw->list);
 		kfree(addrw);
 	}
-	spin_unlock_bh(&sctp_addr_wq_lock);
+	spin_unlock_bh(&net->sctp.addr_wq_lock);
 }
 
-static void sctp_free_addr_wq(void)
+static void sctp_free_addr_wq(struct net *net)
 {
 	struct sctp_sockaddr_entry *addrw;
 	struct sctp_sockaddr_entry *temp;
 
-	spin_lock_bh(&sctp_addr_wq_lock);
-	del_timer(&sctp_addr_wq_timer);
-	list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) {
+	spin_lock_bh(&net->sctp.addr_wq_lock);
+	del_timer(&net->sctp.addr_wq_timer);
+	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
 		list_del(&addrw->list);
 		kfree(addrw);
 	}
-	spin_unlock_bh(&sctp_addr_wq_lock);
+	spin_unlock_bh(&net->sctp.addr_wq_lock);
 }
 
 /* lookup the entry for the same address in the addr_waitq
  * sctp_addr_wq MUST be locked
  */
-static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr)
+static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net,
+					struct sctp_sockaddr_entry *addr)
 {
 	struct sctp_sockaddr_entry *addrw;
 
-	list_for_each_entry(addrw, &sctp_addr_waitq, list) {
+	list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
 		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
 			continue;
 		if (addrw->a.sa.sa_family == AF_INET) {
@@ -719,7 +721,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr
 	return NULL;
 }
 
-void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
+void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd)
 {
 	struct sctp_sockaddr_entry *addrw;
 	unsigned long timeo_val;
@@ -730,9 +732,9 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
 	 * new address after a couple of addition and deletion of that address
 	 */
 
-	spin_lock_bh(&sctp_addr_wq_lock);
+	spin_lock_bh(&net->sctp.addr_wq_lock);
 	/* Offsets existing events in addr_wq */
-	addrw = sctp_addr_wq_lookup(addr);
+	addrw = sctp_addr_wq_lookup(net, addr);
 	if (addrw) {
 		if (addrw->state != cmd) {
 			SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ",
@@ -741,27 +743,27 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd)
 			list_del(&addrw->list);
 			kfree(addrw);
 		}
-		spin_unlock_bh(&sctp_addr_wq_lock);
+		spin_unlock_bh(&net->sctp.addr_wq_lock);
 		return;
 	}
 
 	/* OK, we have to add the new address to the wait queue */
 	addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 	if (addrw == NULL) {
-		spin_unlock_bh(&sctp_addr_wq_lock);
+		spin_unlock_bh(&net->sctp.addr_wq_lock);
 		return;
 	}
 	addrw->state = cmd;
-	list_add_tail(&addrw->list, &sctp_addr_waitq);
+	list_add_tail(&addrw->list, &net->sctp.addr_waitq);
 	SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ",
-	    " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq);
+	    " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq);
 
-	if (!timer_pending(&sctp_addr_wq_timer)) {
+	if (!timer_pending(&net->sctp.addr_wq_timer)) {
 		timeo_val = jiffies;
 		timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY);
-		mod_timer(&sctp_addr_wq_timer, timeo_val);
+		mod_timer(&net->sctp.addr_wq_timer, timeo_val);
 	}
-	spin_unlock_bh(&sctp_addr_wq_lock);
+	spin_unlock_bh(&net->sctp.addr_wq_lock);
 }
 
 /* Event handler for inet address addition/deletion events.
@@ -776,11 +778,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
 	struct sctp_sockaddr_entry *addr = NULL;
 	struct sctp_sockaddr_entry *temp;
+	struct net *net = dev_net(ifa->ifa_dev->dev);
 	int found = 0;
 
-	if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net))
-		return NOTIFY_DONE;
-
 	switch (ev) {
 	case NETDEV_UP:
 		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
@@ -789,27 +789,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 			addr->a.v4.sin_port = 0;
 			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
 			addr->valid = 1;
-			spin_lock_bh(&sctp_local_addr_lock);
-			list_add_tail_rcu(&addr->list, &sctp_local_addr_list);
-			sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW);
-			spin_unlock_bh(&sctp_local_addr_lock);
+			spin_lock_bh(&net->sctp.local_addr_lock);
+			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
+			sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
+			spin_unlock_bh(&net->sctp.local_addr_lock);
 		}
 		break;
 	case NETDEV_DOWN:
-		spin_lock_bh(&sctp_local_addr_lock);
+		spin_lock_bh(&net->sctp.local_addr_lock);
 		list_for_each_entry_safe(addr, temp,
-					&sctp_local_addr_list, list) {
+					&net->sctp.local_addr_list, list) {
 			if (addr->a.sa.sa_family == AF_INET &&
 					addr->a.v4.sin_addr.s_addr ==
 					ifa->ifa_local) {
-				sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL);
+				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 				found = 1;
 				addr->valid = 0;
 				list_del_rcu(&addr->list);
 				break;
 			}
 		}
-		spin_unlock_bh(&sctp_local_addr_lock);
+		spin_unlock_bh(&net->sctp.local_addr_lock);
 		if (found)
 			kfree_rcu(addr, rcu);
 		break;
@@ -1194,6 +1194,36 @@ static void sctp_v4_del_protocol(void)
 	unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
 }
 
+static int sctp_net_init(struct net *net)
+{
+	/* Initialize the local address list. */
+	INIT_LIST_HEAD(&net->sctp.local_addr_list);
+	spin_lock_init(&net->sctp.local_addr_lock);
+	sctp_get_local_addr_list(net);
+
+	/* Initialize the address event list */
+	INIT_LIST_HEAD(&net->sctp.addr_waitq);
+	INIT_LIST_HEAD(&net->sctp.auto_asconf_splist);
+	spin_lock_init(&net->sctp.addr_wq_lock);
+	net->sctp.addr_wq_timer.expires = 0;
+	setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler,
+		    (unsigned long)net);
+
+	return 0;
+}
+
+static void sctp_net_exit(struct net *net)
+{
+	/* Free the local address list */
+	sctp_free_addr_wq(net);
+	sctp_free_local_addr_list(net);
+}
+
+static struct pernet_operations sctp_net_ops = {
+	.init = sctp_net_init,
+	.exit = sctp_net_exit,
+};
+
 /* Initialize the universe into something sensible.  */
 SCTP_STATIC __init int sctp_init(void)
 {
@@ -1399,18 +1429,6 @@ SCTP_STATIC __init int sctp_init(void)
 	sctp_v4_pf_init();
 	sctp_v6_pf_init();
 
-	/* Initialize the local address list. */
-	INIT_LIST_HEAD(&sctp_local_addr_list);
-	spin_lock_init(&sctp_local_addr_lock);
-	sctp_get_local_addr_list();
-
-	/* Initialize the address event list */
-	INIT_LIST_HEAD(&sctp_addr_waitq);
-	INIT_LIST_HEAD(&sctp_auto_asconf_splist);
-	spin_lock_init(&sctp_addr_wq_lock);
-	sctp_addr_wq_timer.expires = 0;
-	setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0);
-
 	status = sctp_v4_protosw_init();
 
 	if (status)
@@ -1426,6 +1444,10 @@ SCTP_STATIC __init int sctp_init(void)
 		goto err_ctl_sock_init;
 	}
 
+	status = register_pernet_subsys(&sctp_net_ops);
+	if (status)
+		goto err_register_pernet_subsys;
+
 	status = sctp_v4_add_protocol();
 	if (status)
 		goto err_add_protocol;
@@ -1441,13 +1463,14 @@ out:
 err_v6_add_protocol:
 	sctp_v4_del_protocol();
 err_add_protocol:
+	unregister_pernet_subsys(&sctp_net_ops);
+err_register_pernet_subsys:
 	inet_ctl_sock_destroy(sctp_ctl_sock);
 err_ctl_sock_init:
 	sctp_v6_protosw_exit();
 err_v6_protosw_init:
 	sctp_v4_protosw_exit();
 err_protosw_init:
-	sctp_free_local_addr_list();
 	sctp_v4_pf_exit();
 	sctp_v6_pf_exit();
 	sctp_sysctl_unregister();
@@ -1482,18 +1505,16 @@ SCTP_STATIC __exit void sctp_exit(void)
 	/* Unregister with inet6/inet layers. */
 	sctp_v6_del_protocol();
 	sctp_v4_del_protocol();
-	sctp_free_addr_wq();
 
 	/* Free the control endpoint.  */
 	inet_ctl_sock_destroy(sctp_ctl_sock);
 
+	unregister_pernet_subsys(&sctp_net_ops);
+
 	/* Free protosw registrations */
 	sctp_v6_protosw_exit();
 	sctp_v4_protosw_exit();
 
-	/* Free the local address list.  */
-	sctp_free_local_addr_list();
-
 	/* Unregister with socket layer. */
 	sctp_v6_pf_exit();
 	sctp_v4_pf_exit();
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4316b0f..5b6dd0e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3471,7 +3471,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
 		sp->do_auto_asconf = 0;
 	} else if (val && !sp->do_auto_asconf) {
 		list_add_tail(&sp->auto_asconf_list,
-		    &sctp_auto_asconf_splist);
+		    &sock_net(sk)->sctp.auto_asconf_splist);
 		sp->do_auto_asconf = 1;
 	}
 	return 0;
@@ -3964,7 +3964,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
 	if (sctp_default_auto_asconf) {
 		list_add_tail(&sp->auto_asconf_list,
-		    &sctp_auto_asconf_splist);
+		    &sock_net(sk)->sctp.auto_asconf_splist);
 		sp->do_auto_asconf = 1;
 	} else
 		sp->do_auto_asconf = 0;
@@ -4653,9 +4653,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
 	union sctp_addr temp;
 	int cnt = 0;
 	int addrlen;
+	struct net *net = sock_net(sk);
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
+	list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) {
 		if (!addr->valid)
 			continue;
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH net-next 3/9] sctp: Make the association hashtable handle multiple network namespaces
From: Eric W. Biederman @ 2012-08-06 18:41 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87zk67q31q.fsf_-_@xmission.com>


- Use struct net in the hash calculation
- Use sock_net(association.base.sk) in the association lookups.
- On receive calculate the network namespace from skb->dev.
- Pass struct net from receive down to the functions that actually
  do the association lookup.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 include/net/sctp/sctp.h    |    6 ++--
 include/net/sctp/structs.h |    3 +-
 net/sctp/associola.c       |    4 ++-
 net/sctp/endpointola.c     |    6 +++-
 net/sctp/input.c           |   64 +++++++++++++++++++++++++++----------------
 net/sctp/ipv6.c            |    3 +-
 6 files changed, 54 insertions(+), 32 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 87b119f..640915a 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -156,7 +156,7 @@ void sctp_hash_established(struct sctp_association *);
 void sctp_unhash_established(struct sctp_association *);
 void sctp_hash_endpoint(struct sctp_endpoint *);
 void sctp_unhash_endpoint(struct sctp_endpoint *);
-struct sock *sctp_err_lookup(int family, struct sk_buff *,
+struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,
 			     struct sctphdr *, struct sctp_association **,
 			     struct sctp_transport **);
 void sctp_err_finish(struct sock *, struct sctp_association *);
@@ -644,9 +644,9 @@ static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
 }
 
 /* This is the hash function for the association hash table. */
-static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport)
+static inline int sctp_assoc_hashfn(struct net *net, __u16 lport, __u16 rport)
 {
-	int h = (lport << 16) + rport;
+	int h = (lport << 16) + rport + net_hash_mix(net);
 	h ^= h>>8;
 	return h & (sctp_assoc_hashsize - 1);
 }
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 9f9de55..c0563d1 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1427,7 +1427,7 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
 				const union sctp_addr *);
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
 					struct net *, const union sctp_addr *);
-int sctp_has_association(const union sctp_addr *laddr,
+int sctp_has_association(struct net *net, const union sctp_addr *laddr,
 			 const union sctp_addr *paddr);
 
 int sctp_verify_init(const struct sctp_association *asoc, sctp_cid_t,
@@ -2014,6 +2014,7 @@ void sctp_assoc_control_transport(struct sctp_association *,
 				  sctp_transport_cmd_t, sctp_sn_error_t);
 struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
 struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
+					   struct net *,
 					   const union sctp_addr *,
 					   const union sctp_addr *);
 void sctp_assoc_migrate(struct sctp_association *, struct sock *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index ebaef3e..a3601f3 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1089,13 +1089,15 @@ out:
 
 /* Is this the association we are looking for? */
 struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
+					   struct net *net,
 					   const union sctp_addr *laddr,
 					   const union sctp_addr *paddr)
 {
 	struct sctp_transport *transport;
 
 	if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
-	    (htons(asoc->peer.port) == paddr->v4.sin_port)) {
+	    (htons(asoc->peer.port) == paddr->v4.sin_port) &&
+	    net_eq(sock_net(asoc->base.sk), net)) {
 		transport = sctp_assoc_lookup_paddr(asoc, paddr);
 		if (!transport)
 			goto out;
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 50c87b4..6b76393 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -345,7 +345,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
 
 	rport = ntohs(paddr->v4.sin_port);
 
-	hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
+	hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
+				 rport);
 	head = &sctp_assoc_hashtable[hash];
 	read_lock(&head->lock);
 	sctp_for_each_hentry(epb, node, &head->chain) {
@@ -388,13 +389,14 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
 {
 	struct sctp_sockaddr_entry *addr;
 	struct sctp_bind_addr *bp;
+	struct net *net = sock_net(ep->base.sk);
 
 	bp = &ep->base.bind_addr;
 	/* This function is called with the socket lock held,
 	 * so the address_list can not change.
 	 */
 	list_for_each_entry(addr, &bp->address_list, list) {
-		if (sctp_has_association(&addr->a, paddr))
+		if (sctp_has_association(net, &addr->a, paddr))
 			return 1;
 	}
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index c0ca893..a7e9a85 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -66,13 +66,15 @@
 
 /* Forward declarations for internal helpers. */
 static int sctp_rcv_ootb(struct sk_buff *);
-static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct net *net,
+				      struct sk_buff *skb,
 				      const union sctp_addr *laddr,
 				      const union sctp_addr *paddr,
 				      struct sctp_transport **transportp);
 static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
 						const union sctp_addr *laddr);
 static struct sctp_association *__sctp_lookup_association(
+					struct net *net,
 					const union sctp_addr *local,
 					const union sctp_addr *peer,
 					struct sctp_transport **pt);
@@ -180,7 +182,7 @@ int sctp_rcv(struct sk_buff *skb)
 	    !af->addr_valid(&dest, NULL, skb))
 		goto discard_it;
 
-	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
+	asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport);
 
 	if (!asoc)
 		ep = __sctp_rcv_lookup_endpoint(net, &dest);
@@ -476,7 +478,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
 }
 
 /* Common lookup code for icmp/icmpv6 error handler. */
-struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
+struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
 			     struct sctphdr *sctphdr,
 			     struct sctp_association **app,
 			     struct sctp_transport **tpp)
@@ -505,7 +507,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
 	/* Look for an association that matches the incoming ICMP error
 	 * packet.
 	 */
-	asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
+	asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport);
 	if (!asoc)
 		return NULL;
 
@@ -588,6 +590,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	struct inet_sock *inet;
 	sk_buff_data_t saveip, savesctp;
 	int err;
+	struct net *net = dev_net(skb->dev);
 
 	if (skb->len < ihlen + 8) {
 		ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS);
@@ -599,7 +602,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
 	savesctp = skb->transport_header;
 	skb_reset_network_header(skb);
 	skb_set_transport_header(skb, ihlen);
-	sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
+	sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
 	/* Put back, the original values. */
 	skb->network_header = saveip;
 	skb->transport_header = savesctp;
@@ -803,13 +806,15 @@ hit:
 /* Insert association into the hash table.  */
 static void __sctp_hash_established(struct sctp_association *asoc)
 {
+	struct net *net = sock_net(asoc->base.sk);
 	struct sctp_ep_common *epb;
 	struct sctp_hashbucket *head;
 
 	epb = &asoc->base;
 
 	/* Calculate which chain this entry will belong to. */
-	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port);
+	epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
+					 asoc->peer.port);
 
 	head = &sctp_assoc_hashtable[epb->hashent];
 
@@ -832,12 +837,13 @@ void sctp_hash_established(struct sctp_association *asoc)
 /* Remove association from the hash table.  */
 static void __sctp_unhash_established(struct sctp_association *asoc)
 {
+	struct net *net = sock_net(asoc->base.sk);
 	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 
 	epb = &asoc->base;
 
-	epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port,
+	epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port,
 					 asoc->peer.port);
 
 	head = &sctp_assoc_hashtable[epb->hashent];
@@ -860,6 +866,7 @@ void sctp_unhash_established(struct sctp_association *asoc)
 
 /* Look up an association. */
 static struct sctp_association *__sctp_lookup_association(
+					struct net *net,
 					const union sctp_addr *local,
 					const union sctp_addr *peer,
 					struct sctp_transport **pt)
@@ -874,12 +881,13 @@ static struct sctp_association *__sctp_lookup_association(
 	/* Optimize here for direct hit, only listening connections can
 	 * have wildcards anyways.
 	 */
-	hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
+	hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
+				 ntohs(peer->v4.sin_port));
 	head = &sctp_assoc_hashtable[hash];
 	read_lock(&head->lock);
 	sctp_for_each_hentry(epb, node, &head->chain) {
 		asoc = sctp_assoc(epb);
-		transport = sctp_assoc_is_match(asoc, local, peer);
+		transport = sctp_assoc_is_match(asoc, net, local, peer);
 		if (transport)
 			goto hit;
 	}
@@ -897,27 +905,29 @@ hit:
 
 /* Look up an association. BH-safe. */
 SCTP_STATIC
-struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
+struct sctp_association *sctp_lookup_association(struct net *net,
+						 const union sctp_addr *laddr,
 						 const union sctp_addr *paddr,
 					    struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
 
 	sctp_local_bh_disable();
-	asoc = __sctp_lookup_association(laddr, paddr, transportp);
+	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
 	sctp_local_bh_enable();
 
 	return asoc;
 }
 
 /* Is there an association matching the given local and peer addresses? */
-int sctp_has_association(const union sctp_addr *laddr,
+int sctp_has_association(struct net *net,
+			 const union sctp_addr *laddr,
 			 const union sctp_addr *paddr)
 {
 	struct sctp_association *asoc;
 	struct sctp_transport *transport;
 
-	if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
+	if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) {
 		sctp_association_put(asoc);
 		return 1;
 	}
@@ -943,7 +953,8 @@ int sctp_has_association(const union sctp_addr *laddr,
  * in certain circumstances.
  *
  */
-static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
+	struct sk_buff *skb,
 	const union sctp_addr *laddr, struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
@@ -983,7 +994,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
 
 		af->from_addr_param(paddr, params.addr, sh->source, 0);
 
-		asoc = __sctp_lookup_association(laddr, paddr, &transport);
+		asoc = __sctp_lookup_association(net, laddr, paddr, &transport);
 		if (asoc)
 			return asoc;
 	}
@@ -1006,6 +1017,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
  * subsequent ASCONF Chunks. If found, proceed to rule D4.
  */
 static struct sctp_association *__sctp_rcv_asconf_lookup(
+					struct net *net,
 					sctp_chunkhdr_t *ch,
 					const union sctp_addr *laddr,
 					__be16 peer_port,
@@ -1025,7 +1037,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
 
 	af->from_addr_param(&paddr, param, peer_port, 0);
 
-	return __sctp_lookup_association(laddr, &paddr, transportp);
+	return __sctp_lookup_association(net, laddr, &paddr, transportp);
 }
 
 
@@ -1038,7 +1050,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
 * This means that any chunks that can help us identify the association need
 * to be looked at to find this association.
 */
-static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
+				      struct sk_buff *skb,
 				      const union sctp_addr *laddr,
 				      struct sctp_transport **transportp)
 {
@@ -1080,7 +1093,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
 
 		    case SCTP_CID_ASCONF:
 			    if (have_auth || sctp_addip_noauth)
-				    asoc = __sctp_rcv_asconf_lookup(ch, laddr,
+				    asoc = __sctp_rcv_asconf_lookup(
+							net, ch, laddr,
 							sctp_hdr(skb)->source,
 							transportp);
 		    default:
@@ -1103,7 +1117,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb,
  * include looking inside of INIT/INIT-ACK chunks or after the AUTH
  * chunks.
  */
-static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
+				      struct sk_buff *skb,
 				      const union sctp_addr *laddr,
 				      struct sctp_transport **transportp)
 {
@@ -1123,11 +1138,11 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
 	switch (ch->type) {
 	case SCTP_CID_INIT:
 	case SCTP_CID_INIT_ACK:
-		return __sctp_rcv_init_lookup(skb, laddr, transportp);
+		return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
 		break;
 
 	default:
-		return __sctp_rcv_walk_lookup(skb, laddr, transportp);
+		return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
 		break;
 	}
 
@@ -1136,21 +1151,22 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
 }
 
 /* Lookup an association for an inbound skb. */
-static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct net *net,
+				      struct sk_buff *skb,
 				      const union sctp_addr *paddr,
 				      const union sctp_addr *laddr,
 				      struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
 
-	asoc = __sctp_lookup_association(laddr, paddr, transportp);
+	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
 
 	/* Further lookup for INIT/INIT-ACK packets.
 	 * SCTP Implementors Guide, 2.18 Handling of address
 	 * parameters within the INIT or INIT-ACK.
 	 */
 	if (!asoc)
-		asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp);
+		asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp);
 
 	return asoc;
 }
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ed7139e..2165a7e 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -154,6 +154,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	struct ipv6_pinfo *np;
 	sk_buff_data_t saveip, savesctp;
 	int err;
+	struct net *net = dev_net(skb->dev);
 
 	idev = in6_dev_get(skb->dev);
 
@@ -162,7 +163,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	savesctp = skb->transport_header;
 	skb_reset_network_header(skb);
 	skb_set_transport_header(skb, offset);
-	sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
+	sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
 	/* Put back, the original pointers. */
 	skb->network_header   = saveip;
 	skb->transport_header = savesctp;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH net-next 2/9] sctp: Make the endpoint hashtable handle multiple network namespaces
From: Eric W. Biederman @ 2012-08-06 18:40 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87zk67q31q.fsf_-_@xmission.com>


- Use struct net in the hash calculation
- Use sock_net(endpoint.base.sk) in the endpoint lookups.
- On receive calculate the network namespace from skb->dev.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 include/net/sctp/sctp.h    |    4 ++--
 include/net/sctp/structs.h |    2 +-
 net/sctp/endpointola.c     |    4 +++-
 net/sctp/input.c           |   19 ++++++++++++-------
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 7c05040..87b119f 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -638,9 +638,9 @@ static inline int sctp_phashfn(struct net *net, __u16 lport)
 }
 
 /* This is the hash function for the endpoint hash table. */
-static inline int sctp_ep_hashfn(__u16 lport)
+static inline int sctp_ep_hashfn(struct net *net, __u16 lport)
 {
-	return lport & (sctp_ep_hashsize - 1);
+	return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1);
 }
 
 /* This is the hash function for the association hash table. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index c089bb1..9f9de55 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1426,7 +1426,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
 int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
 				const union sctp_addr *);
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
-					const union sctp_addr *);
+					struct net *, const union sctp_addr *);
 int sctp_has_association(const union sctp_addr *laddr,
 			 const union sctp_addr *paddr);
 
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 68a385d..50c87b4 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -302,11 +302,13 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
 
 /* Is this the endpoint we are looking for?  */
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
+					       struct net *net,
 					       const union sctp_addr *laddr)
 {
 	struct sctp_endpoint *retval = NULL;
 
-	if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
+	if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) &&
+	    net_eq(sock_net(ep->base.sk), net)) {
 		if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
 					 sctp_sk(ep->base.sk)))
 			retval = ep;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index e64d521..c0ca893 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -70,7 +70,8 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
 				      const union sctp_addr *laddr,
 				      const union sctp_addr *paddr,
 				      struct sctp_transport **transportp);
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+						const union sctp_addr *laddr);
 static struct sctp_association *__sctp_lookup_association(
 					const union sctp_addr *local,
 					const union sctp_addr *peer,
@@ -129,6 +130,7 @@ int sctp_rcv(struct sk_buff *skb)
 	union sctp_addr dest;
 	int family;
 	struct sctp_af *af;
+	struct net *net = dev_net(skb->dev);
 
 	if (skb->pkt_type!=PACKET_HOST)
 		goto discard_it;
@@ -181,7 +183,7 @@ int sctp_rcv(struct sk_buff *skb)
 	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
 
 	if (!asoc)
-		ep = __sctp_rcv_lookup_endpoint(&dest);
+		ep = __sctp_rcv_lookup_endpoint(net, &dest);
 
 	/* Retrieve the common input handling substructure. */
 	rcvr = asoc ? &asoc->base : &ep->base;
@@ -723,12 +725,13 @@ discard:
 /* Insert endpoint into the hash table.  */
 static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
 {
+	struct net *net = sock_net(ep->base.sk);
 	struct sctp_ep_common *epb;
 	struct sctp_hashbucket *head;
 
 	epb = &ep->base;
 
-	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
+	epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
 	head = &sctp_ep_hashtable[epb->hashent];
 
 	sctp_write_lock(&head->lock);
@@ -747,12 +750,13 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep)
 /* Remove endpoint from the hash table.  */
 static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
 {
+	struct net *net = sock_net(ep->base.sk);
 	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 
 	epb = &ep->base;
 
-	epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
+	epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
 
 	head = &sctp_ep_hashtable[epb->hashent];
 
@@ -770,7 +774,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
 }
 
 /* Look up an endpoint. */
-static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
+						const union sctp_addr *laddr)
 {
 	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
@@ -778,12 +783,12 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
 	struct hlist_node *node;
 	int hash;
 
-	hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
+	hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port));
 	head = &sctp_ep_hashtable[hash];
 	read_lock(&head->lock);
 	sctp_for_each_hentry(epb, node, &head->chain) {
 		ep = sctp_ep(epb);
-		if (sctp_endpoint_is_match(ep, laddr))
+		if (sctp_endpoint_is_match(ep, net, laddr))
 			goto hit;
 	}
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH net-next 1/9] sctp: Make the port hash table use struct net in it's key.
From: Eric W. Biederman @ 2012-08-06 18:39 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87zk67q31q.fsf_-_@xmission.com>


- Add struct net into the port hash table hash calculation
- Add struct net inot the struct sctp_bind_bucket so there
  is a memory of which network namespace a port is allocated in.
  No need for a ref count because sctp_bind_bucket only exists
  when there are sockets in the hash table and sockets can not
  change their network namspace, and sockets already ref count
  their network namespace.
- Add struct net into the key comparison when we are testing
  to see if we have found the port hash table entry we are
  looking for.

With these changes lookups in the port hash table becomes
safe to use in multiple network namespaces.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 include/net/sctp/sctp.h    |    4 ++--
 include/net/sctp/structs.h |    1 +
 net/sctp/socket.c          |   22 +++++++++++++---------
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index ff49964..7c05040 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -632,9 +632,9 @@ static inline int sctp_sanity_check(void)
 
 /* Warning: The following hash functions assume a power of two 'size'. */
 /* This is the hash function for the SCTP port hash table. */
-static inline int sctp_phashfn(__u16 lport)
+static inline int sctp_phashfn(struct net *net, __u16 lport)
 {
-	return lport & (sctp_port_hashsize - 1);
+	return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1);
 }
 
 /* This is the hash function for the endpoint hash table. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index fc5e600..c089bb1 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -102,6 +102,7 @@ struct sctp_bind_bucket {
 	unsigned short	fastreuse;
 	struct hlist_node	node;
 	struct hlist_head	owner;
+	struct net	*net;
 };
 
 struct sctp_bind_hashbucket {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5e25981..4316b0f 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5769,7 +5769,7 @@ static void sctp_unhash(struct sock *sk)
  * a fastreuse flag (FIXME: NPI ipg).
  */
 static struct sctp_bind_bucket *sctp_bucket_create(
-	struct sctp_bind_hashbucket *head, unsigned short snum);
+	struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
 
 static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
 {
@@ -5799,11 +5799,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
 				rover = low;
 			if (inet_is_reserved_local_port(rover))
 				continue;
-			index = sctp_phashfn(rover);
+			index = sctp_phashfn(sock_net(sk), rover);
 			head = &sctp_port_hashtable[index];
 			sctp_spin_lock(&head->lock);
 			sctp_for_each_hentry(pp, node, &head->chain)
-				if (pp->port == rover)
+				if ((pp->port == rover) &&
+				    net_eq(sock_net(sk), pp->net))
 					goto next;
 			break;
 		next:
@@ -5827,10 +5828,10 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
 		 * to the port number (snum) - we detect that with the
 		 * port iterator, pp being NULL.
 		 */
-		head = &sctp_port_hashtable[sctp_phashfn(snum)];
+		head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)];
 		sctp_spin_lock(&head->lock);
 		sctp_for_each_hentry(pp, node, &head->chain) {
-			if (pp->port == snum)
+			if ((pp->port == snum) && net_eq(pp->net, sock_net(sk)))
 				goto pp_found;
 		}
 	}
@@ -5881,7 +5882,7 @@ pp_found:
 pp_not_found:
 	/* If there was a hash table miss, create a new port.  */
 	ret = 1;
-	if (!pp && !(pp = sctp_bucket_create(head, snum)))
+	if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum)))
 		goto fail_unlock;
 
 	/* In either case (hit or miss), make sure fastreuse is 1 only
@@ -6113,7 +6114,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
  ********************************************************************/
 
 static struct sctp_bind_bucket *sctp_bucket_create(
-	struct sctp_bind_hashbucket *head, unsigned short snum)
+	struct sctp_bind_hashbucket *head, struct net *net, unsigned short snum)
 {
 	struct sctp_bind_bucket *pp;
 
@@ -6123,6 +6124,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
 		pp->port = snum;
 		pp->fastreuse = 0;
 		INIT_HLIST_HEAD(&pp->owner);
+		pp->net = net;
 		hlist_add_head(&pp->node, &head->chain);
 	}
 	return pp;
@@ -6142,7 +6144,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
 static inline void __sctp_put_port(struct sock *sk)
 {
 	struct sctp_bind_hashbucket *head =
-		&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)];
+		&sctp_port_hashtable[sctp_phashfn(sock_net(sk),
+						  inet_sk(sk)->inet_num)];
 	struct sctp_bind_bucket *pp;
 
 	sctp_spin_lock(&head->lock);
@@ -6809,7 +6812,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 	newsp->hmac = NULL;
 
 	/* Hook this new socket in to the bind_hash list. */
-	head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)];
+	head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk),
+						 inet_sk(oldsk)->inet_num)];
 	sctp_local_bh_disable();
 	sctp_spin_lock(&head->lock);
 	pp = sctp_sk(oldsk)->bind_hash;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH net-next 0/9] sctp: Basic support for network namespaces
From: Eric W. Biederman @ 2012-08-06 18:38 UTC (permalink / raw)
  To: David Miller
  Cc: Vlad Yasevich, linux-sctp, netdev, linux-kernel, Jan Ariyasu,
	Jan Ariyasu, Neil Horman, Thomas Graf, Xi Wang
In-Reply-To: <87mx27rig7.fsf@xmission.com>


The other day I wanted to play around with sctp and did a basic pass to
make sctp per network namespace, so that I could play more conviniently.
Apparently this is an idea who's time has come because Jan Ariyasu also
made a similar set of changes.

I have played around some with these changes and have confirmed that
sctp_test from lksctp-tools works without problems.

Compared to Jan's changes I have per network namespace association and
endpoint hash table lookups, my patch has per network namespace mib
statistics, my changes don't contiain per network namespace tunables
and my patchset only touches about half as many lines as Jan's change.

So for both correctness and simplicity reasons it looks like the
practical way to handle this is to merge my changes and get Jan rebase
his tunable changes on top.

 include/net/net_namespace.h |    4 +
 include/net/netns/sctp.h    |   37 +++++
 include/net/sctp/sctp.h     |   44 +++----
 include/net/sctp/structs.h  |   28 +----
 net/sctp/associola.c        |    9 +-
 net/sctp/bind_addr.c        |   14 +-
 net/sctp/chunk.c            |    2 +-
 net/sctp/endpointola.c      |   12 +-
 net/sctp/input.c            |  109 +++++++++------
 net/sctp/ipv6.c             |   36 +++---
 net/sctp/output.c           |    2 +-
 net/sctp/outqueue.c         |   18 ++-
 net/sctp/proc.c             |   58 +++++---
 net/sctp/protocol.c         |  305 ++++++++++++++++++++++---------------------
 net/sctp/sm_statefuns.c     |  208 ++++++++++++++++++-----------
 net/sctp/socket.c           |   29 +++--
 net/sctp/ulpqueue.c         |   18 ++-
 17 files changed, 533 insertions(+), 400 deletions(-)


Eric W. Biederman (9):
      sctp: Make the port hash table use struct net in it's key.
      sctp: Make the endpoint hashtable handle multiple network namespaces
      sctp: Make the association hashtable handle multiple network namespaces
      sctp: Make the address lists per network namespace
      sctp: Make the ctl_sock per network namespace
      sctp: Move the percpu sockets counter out of sctp_proc_init
      sctp: Make the proc files per network namespace.
      sctp: Enable sctp in all network namespaces
      sctp: Make the mib per network namespace

^ permalink raw reply

* [PATCH] net: Use PTR_RET rather than if(IS_ERR(.. [1]
From: Thomas Meyer @ 2012-08-06 17:51 UTC (permalink / raw)
  To: "[acme

The semantic patch that makes this change is available
in scripts/coccinelle/api/ptr_ret.cocci.

More information about semantic patching is available at
http://coccinelle.lip6.fr/

Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
---

diff -u -p a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -996,9 +996,7 @@ static int __init cops_module_init(void)
 		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
 			cardname);
 	cops_dev = cops_probe(-1);
-	if (IS_ERR(cops_dev))
-		return PTR_ERR(cops_dev);
-        return 0;
+	return PTR_RET(cops_dev);
 }
 
 static void __exit cops_module_exit(void)
diff -u -p a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1243,9 +1243,7 @@ static int __init ltpc_module_init(void)
 		       "ltpc: Autoprobing is not recommended for modules\n");
 
 	dev_ltpc = ltpc_probe();
-	if (IS_ERR(dev_ltpc))
-		return PTR_ERR(dev_ltpc);
-	return 0;
+	return PTR_RET(dev_ltpc);
 }
 module_init(ltpc_module_init);
 #endif

^ permalink raw reply

* Re: [PATCH net-next] igb: use build_skb()
From: Eric Dumazet @ 2012-08-06 18:21 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: Jeff Kirsher, netdev
In-Reply-To: <50200066.6060905@intel.com>

On Mon, 2012-08-06 at 10:35 -0700, Alexander Duyck wrote:

> I was planning to move igb over to an ixgbe style receive path at some
> point anyway.  Since it seems like this is now a higher priority I
> figured I would try to get the patches for it implemented in the next
> week or so.  Would there be any issue with us rejecting this patch and
> instead switching igb over to the ixgbe style path?

It seems I missed this part.

I use igb on my dev machine, not on prod machines, so if you are moving
igb to ixgbe, I can certainly can maintain my patch in my tree, while
you make your changes.

^ permalink raw reply

* Re: [PATCH 00/13] SCTP: Enable netns
From: Eric W. Biederman @ 2012-08-06 18:20 UTC (permalink / raw)
  To: Jan Ariyasu
  Cc: Vlad Yasevich, David S. Miller, linux-sctp, netdev, linux-kernel,
	Jan Ariyasu
In-Reply-To: <1344115837-6150-1-git-send-email-jan.ariyasu@hp.com>

Jan Ariyasu <jan.ariyasu@gmail.com> writes:

> The following set of patches enable network-namespaces for the SCTP protocol.
>
> The multitude of global parameters are stored in a net_generic
> structure, and the bulk of the patches enable the protocol to access
> the parameters on a per-namespace basis.  The first five patches
> enable netns handling of the protocol, procfs and sysfs.

I am going to do something to muddy the waters here, that I had hoped to
avoid when I saw your patchset.

A few weeks ago I wanted to play with sctp and also made a network
namespace enabled version.  I am not deeply attached to my changes,
however when comparing the differences I realized that your code fails
to make the lookup of associations per network namespace.

Given that we only have source and destination port to lookup
assoications by this almost guarantees one network namespace can
accidentially use the association of another network namespace meerly
by reusing the same ports.

The downside with my version is that it does not make all of the sctp
tunables per network namespace the way yours does, but making all of
the tunables per network namespace should be straight forward from
my base.

My patchset also misses some nice to haves like making the association
id allocation per network namespace.  It is not important for
correctness of the code but it might allow an information leak between
namespaces.

So Jan I am going to send my patchset and hopefully you can rebase your
changes to make all of the tunables per network namespace on top of
mine.

Since my patchset is half the size of your I think that is the most
reasonable way to go.

Eric

^ permalink raw reply

* Re: [PATCH net-next] igb: use build_skb()
From: Eric Dumazet @ 2012-08-06 18:08 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: Jeff Kirsher, netdev
In-Reply-To: <50200066.6060905@intel.com>

On Mon, 2012-08-06 at 10:35 -0700, Alexander Duyck wrote:
> On 08/02/2012 08:51 AM, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> >
> > By using netdev_alloc_frag() & build_skb() instead of legacy
> > netdev_alloc_skb_ip_align() calls, we reduce number of cache misses in
> > RX path and size of working set.
> >
> > For a given rx workload, number of 'inuse' sk_buff can be reduced to a
> > very minimum, especially when packets are dropped by our stack.
> >
> > (Before this patch, default sk_buff allocation was 2048 sk_buffs in rx
> > ring buffer)
> >
> > They are initialized right before being delivered to stack, so can stay
> > hot in cpu caches.
> >
> > Ethernet header prefetching is more effective (old prefetch of skb->data
> > paid a stall to access skb->data pointer)
> >
> > I have 15% performance increase in a RX stress test, removing SLUB slow
> > path in the profiles.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > Cc: Alexander Duyck <alexander.h.duyck@intel.com>
> > ---
> >  drivers/net/ethernet/intel/igb/igb.h         |    8 ++
> >  drivers/net/ethernet/intel/igb/igb_ethtool.c |   14 ++--
> >  drivers/net/ethernet/intel/igb/igb_main.c    |   56 ++++++++++-------
> >  3 files changed, 49 insertions(+), 29 deletions(-)
> >
> [...]
> > diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> > index b7c2d50..8b732c9 100644
> > --- a/drivers/net/ethernet/intel/igb/igb_main.c
> > +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> [...]
> > @@ -6091,6 +6095,15 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
> >  		next_rxd = IGB_RX_DESC(rx_ring, i);
> >  		prefetch(next_rxd);
> >  
> > +		if (!skb) {
> > +			skb = build_skb(data, IGB_FRAGSZ);
> > +			if (unlikely(!skb)) {
> > +				rx_ring->rx_stats.alloc_failed++;
> > +				buffer_info->data = data;
> > +				goto next_desc;
> > +			}
> > +			skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
> > +		}
> >  		/*
> >  		 * This memory barrier is needed to keep us from reading
> >  		 * any other fields out of the rx_desc until we know the
> This logic is broken.  If an allocation failure occurs it would leave
> the data in the ring and could possibly give you a corrupted packet.
> 
> I was planning to move igb over to an ixgbe style receive path at some
> point anyway.  Since it seems like this is now a higher priority I
> figured I would try to get the patches for it implemented in the next
> week or so.  Would there be any issue with us rejecting this patch and
> instead switching igb over to the ixgbe style path?

I checked again and I believe logic is fine, exactly like driver before
this patch.

If skb cannot be allocated, the data part is reused for next frame.

( buffer_info->data = data; goto next_desc; )

^ permalink raw reply

* Re: [PATCH] net:appletalk:ddp:fixed coding style issue relating to
From: Ben Hutchings @ 2012-08-06 17:57 UTC (permalink / raw)
  To: Jeffrin Jose; +Cc: acme, davem, netdev, linux-kernel
In-Reply-To: <1344274298-4711-1-git-send-email-ahiliation@yahoo.co.in>

On Mon, 2012-08-06 at 23:01 +0530, Jeffrin Jose wrote:
> Fixed coding style issue relating to indentation
> in net/appletalk/ddp.c found by checkpatch.pl tool.
> 
> Signed-off-by: Jeffrin Jose <ahiliation@yahoo.co.in>
> ---
>  net/appletalk/ddp.c |   26 +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
> index 8685296..4023fca 100644
> --- a/net/appletalk/ddp.c
> +++ b/net/appletalk/ddp.c
> @@ -1796,7 +1796,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
>  
>  	switch (cmd) {
>  		/* Protocol layer */
> -		case TIOCOUTQ: {
> +	case TIOCOUTQ: {
>  			long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
>  
>  			if (amount < 0)
[...]

The whole of the switch body should be shifted left by one tab, not just
the case-labels.

Ben.

-- 
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: [PATCH net-next] igb: use build_skb()
From: Alexander Duyck @ 2012-08-06 17:35 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Jeff Kirsher, netdev
In-Reply-To: <1343922692.9299.231.camel@edumazet-glaptop>

On 08/02/2012 08:51 AM, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> By using netdev_alloc_frag() & build_skb() instead of legacy
> netdev_alloc_skb_ip_align() calls, we reduce number of cache misses in
> RX path and size of working set.
>
> For a given rx workload, number of 'inuse' sk_buff can be reduced to a
> very minimum, especially when packets are dropped by our stack.
>
> (Before this patch, default sk_buff allocation was 2048 sk_buffs in rx
> ring buffer)
>
> They are initialized right before being delivered to stack, so can stay
> hot in cpu caches.
>
> Ethernet header prefetching is more effective (old prefetch of skb->data
> paid a stall to access skb->data pointer)
>
> I have 15% performance increase in a RX stress test, removing SLUB slow
> path in the profiles.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
>  drivers/net/ethernet/intel/igb/igb.h         |    8 ++
>  drivers/net/ethernet/intel/igb/igb_ethtool.c |   14 ++--
>  drivers/net/ethernet/intel/igb/igb_main.c    |   56 ++++++++++-------
>  3 files changed, 49 insertions(+), 29 deletions(-)
>
[...]
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index b7c2d50..8b732c9 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
[...]
> @@ -6091,6 +6095,15 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
>  		next_rxd = IGB_RX_DESC(rx_ring, i);
>  		prefetch(next_rxd);
>  
> +		if (!skb) {
> +			skb = build_skb(data, IGB_FRAGSZ);
> +			if (unlikely(!skb)) {
> +				rx_ring->rx_stats.alloc_failed++;
> +				buffer_info->data = data;
> +				goto next_desc;
> +			}
> +			skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
> +		}
>  		/*
>  		 * This memory barrier is needed to keep us from reading
>  		 * any other fields out of the rx_desc until we know the
This logic is broken.  If an allocation failure occurs it would leave
the data in the ring and could possibly give you a corrupted packet.

I was planning to move igb over to an ixgbe style receive path at some
point anyway.  Since it seems like this is now a higher priority I
figured I would try to get the patches for it implemented in the next
week or so.  Would there be any issue with us rejecting this patch and
instead switching igb over to the ixgbe style path?

Thanks,

Alex

^ permalink raw reply

* [PATCH] net:appletalk:ddp:fixed coding style issue relating to
From: Jeffrin Jose @ 2012-08-06 17:31 UTC (permalink / raw)
  To: acme, davem; +Cc: netdev, linux-kernel, Jeffrin Jose

Fixed coding style issue relating to indentation
in net/appletalk/ddp.c found by checkpatch.pl tool.

Signed-off-by: Jeffrin Jose <ahiliation@yahoo.co.in>
---
 net/appletalk/ddp.c |   26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 8685296..4023fca 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1796,7 +1796,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 	switch (cmd) {
 		/* Protocol layer */
-		case TIOCOUTQ: {
+	case TIOCOUTQ: {
 			long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
 
 			if (amount < 0)
@@ -1804,7 +1804,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 			rc = put_user(amount, (int __user *)argp);
 			break;
 		}
-		case TIOCINQ: {
+	case TIOCINQ: {
 			/*
 			 * These two are safe on a single CPU system as only
 			 * user tasks fiddle here
@@ -1817,27 +1817,27 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 			rc = put_user(amount, (int __user *)argp);
 			break;
 		}
-		case SIOCGSTAMP:
+	case SIOCGSTAMP:
 			rc = sock_get_timestamp(sk, argp);
 			break;
-		case SIOCGSTAMPNS:
+	case SIOCGSTAMPNS:
 			rc = sock_get_timestampns(sk, argp);
 			break;
 		/* Routing */
-		case SIOCADDRT:
-		case SIOCDELRT:
+	case SIOCADDRT:
+	case SIOCDELRT:
 			rc = -EPERM;
 			if (capable(CAP_NET_ADMIN))
 				rc = atrtr_ioctl(cmd, argp);
 			break;
 		/* Interface */
-		case SIOCGIFADDR:
-		case SIOCSIFADDR:
-		case SIOCGIFBRDADDR:
-		case SIOCATALKDIFADDR:
-		case SIOCDIFADDR:
-		case SIOCSARP:		/* proxy AARP */
-		case SIOCDARP:		/* proxy AARP */
+	case SIOCGIFADDR:
+	case SIOCSIFADDR:
+	case SIOCGIFBRDADDR:
+	case SIOCATALKDIFADDR:
+	case SIOCDIFADDR:
+	case SIOCSARP:		/* proxy AARP */
+	case SIOCDARP:		/* proxy AARP */
 			rtnl_lock();
 			rc = atif_ioctl(cmd, argp);
 			rtnl_unlock();
-- 
1.7.10

^ permalink raw reply related

* Atheros Communications Inc. AR8121/AR8113/AR8114 Gigabit or Fast Ethernet (rev b0) 1.0.0.7 md5 corrupted using NFS
From: Marco Castiglione @ 2012-08-06 17:02 UTC (permalink / raw)
  To: netdev

Hi,

I have a problem with :

Ethernet controller: Atheros Communications Inc. AR8121/AR8113/AR8114
Gigabit or Fast Ethernet (rev b0)
        Subsystem: ASUSTeK Computer Inc. Device 831c
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr-
Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
<TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 46
        Region 0: Memory at fbec0000 (64-bit, non-prefetchable) [size=256K]
        Region 2: I/O ports at dc00 [size=128]
        Capabilities: <access denied>
        Kernel driver in use: ATL1E

The driver working fine except for nfs3 and nfs4

If I try to copy a file bigger of 400 mb the file get corrupted, If I try
with multiple files I have a kernel oops

I tried different system and service (Ftp,samba) and they working fine.

I also tried to set nfs to use udp, it kinda fix the problem but only in
part (I get 1 on 3 big file with md5 mismatch).

I notice in almost every kernel from 2.6 to now 3.2.15 the driver is the
same version

Filename:       /lib/modules/3.2.0-2-amd64/
kernel/drivers/net/ethernet/atheros/atl1e/atl1e.ko
version:        1.0.0.7-NAPI
license:        GPL
description:    Atheros 1000M Ethernet Network Driver
author:         Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <
jie.yang@atheros.com>
srcversion:     6E5949327D7FDF32D5F4A5B
alias:          pci:v00001969d00001066sv*sd*bc*sc*i*
alias:          pci:v00001969d00001026sv*sd*bc*sc*i*
depends:
intree:         Y
vermagic:       3.2.0-2-amd64 SMP mod_unload modversions
parm:           tx_desc_cnt:Transmit description count (array of int)
parm:           rx_mem_size:memory size of rx buffer(KB) (array of int)
parm:           media_type:MediaType Select (array of int)
parm:           int_mod_timer:Interrupt Moderator Timer (array of int)

I found on ubuntu website the last version of the driver is 1.0.1.14 with
this change log :

1.0.1.14
    1. don't define napi_struct in kcompat.h when GRO isn't supported.

1.0.1.13
    1. fix AR8151-A hang when plug in LAN cable by cleaning bit1 of
REG(0x1114).

1.0.1.12
    1. fix tpd, rfd, rrs, configure error for powerpc

1.0.1.11
    1. only save power when WOL enable.

1.0.1.10
    1. add l1d 2.0 support.
    2. fix atl1c_phy_power_saving bug.

1.0.1.9
    1. fix AR8131 reset error TX pending.
    2. add AR8152 description.

1.0.1.8
    1. add L2CB V2.0 support.

1.0.1.7
    1. fix L0s/L1 bug.
    2. update suspend procedure.

1.0.1.6
    1. fix valn error.
    2. use common task instead of reset task and link change task.
    3. reset phy when link down.

1.0.1.5
    1. change rx mod.

1.0.1.4
    1. add l1d support.

1.0.1.3
    1. fix TSO error.

1.0.1.2
    1. fix compile error for kernel >= 2.6.30.

1.0.1.1
    1. add L2cB support.

1.0.0.10
    1. fix memory leak when power suspend.

1.0.0.9
    1. do power saving when bootup with link lost.
    2. remove ATL1C_INTR_CLEAR_ON_READ for power saving

1.0.0.8
    1. remove dump_stack(), which was used for debugging.


So I found out the TSO is corrupt in the current version  and that explain
with the udp setting do the trick.

Now I tried to compile the new version from
AR81Family-linux-v1.0.1.14.tar.gz but was made for the 2.6 so I can't
compile.( <http://goog_56610235>
http://media.cdn.ubuntu-de.org/forum/attachments/2666793/AR81Family-linux-
v1.0.1.14_10.10.tar.gz
)

The Atheros support and web page is gone after Qualcomm acquisition and the
patch I found on Ubuntu forum don't work either (
http://ubuntuforums.org/attachment.php?attachmentid=182141&d=1296221015)

I found out lots of people have the same issue and they using samba at the
moment.

My temp solution is use a usb/eth adapter with ax8112 chipset but it run at
100mbps.

SO my request is this : Is possible for somebody of the kernel team look
the code inside AR81Family-linux-v1.0.1.14.tar.gz  and update the one in
the kernel 3.x?

Thank you for you time and consideration

^ permalink raw reply

* Re: ethtool 3.5 released
From: Ben Hutchings @ 2012-08-06 16:41 UTC (permalink / raw)
  To: Naoto MATSUMOTO; +Cc: netdev
In-Reply-To: <20120806102723.D637.C42C3789@sakura.ad.jp>

On Mon, 2012-08-06 at 10:27 +0900, Naoto MATSUMOTO wrote:
> Dear Ben.
> 
> FYI(For Your Information)
> This is Naoto MATSUMOTO, Senior Researcher, SAKURA Internet.
> 
> We tried ethtool 3.5 on 40GbE NIC(Mellanox), it's result here.
> -----------------------------------------------------------------------
> # ./ethtool --version
> ethtool version 3.5
> 
> # ./ethtool eth1
> Settings for eth1:
>         Supported ports: [ TP ]
>         Supported link modes:   10000baseT/Full
>         Supported pause frame use: No
>         Supports auto-negotiation: No
>         Advertised link modes:  10000baseT/Full
>         Advertised pause frame use: No
>         Advertised auto-negotiation: No
>         Speed: 40000Mb/s
>         Duplex: Full
>         Port: Twisted Pair

40G twisted-pair, eh?

>         PHYAD: 0
>         Transceiver: internal
>         Auto-negotiation: off
>         MDI-X: Unknown
>         Supports Wake-on: d
>         Wake-on: d
>         Current message level: 0x00000014 (20)
>                                link ifdown
>         Link detected: yes
> 
> 
> Our 40GbE NIC Firmware/Dirver status are here.
> -----------------------------------------------------------------------
> Mellanox ConnectX HCA Ethernet driver v1.5.8.3 (June 2012)
> Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]
> Firmware Version: 2.10.800
> -----------------------------------------------------------------------
> 
> 
> And We were testing 10GbE(Intel) NIC and your 40GbE NIC in our lab
> using ethtool with added some debug code.

I work for Solarflare, not Mellanox... and the patch adding 40G link
modes came from Parav Pandit at Emulex.

[...]
> It's firmware problem I thinks. But Just Information for you ;-)

Also, the 40G link mode flags were only just defined, so the driver
probably has yet to be updated.

Ben.

-- 
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

* WARNING: at net/ipv4/tcp.c:1598 tcp_recvmsg+0x641/0xd30()
From: Dave Jones @ 2012-08-06 15:46 UTC (permalink / raw)
  To: netdev; +Cc: Fedora Kernel Team

We just got an automated report of this WARN being hit in 3.5

 > backtrace:
 > :WARNING: at net/ipv4/tcp.c:1598 tcp_recvmsg+0x641/0xd30()
 > :Hardware name: P5Q DELUXE
 > :recvmsg bug: copied 99F66400 seq 99F6A4A8 rcvnxt 99F6CDAD fl 0
 > : [<ffffffff811848e6>] do_sync_read+0xe6/0x120
 > : [<ffffffff81275eea>] ? inode_has_perm.isra.31.constprop.61+0x2a/0x30
 > : [<ffffffff81272f32>] ? security_file_permission+0x92/0xb0
 > : [<ffffffff81184d81>] ? rw_verify_area+0x61/0xf0
 > : [<ffffffff811852cd>] vfs_read+0x15d/0x180
 > : [<ffffffff8118533a>] sys_read+0x4a/0x90
 > : [<ffffffff8160fc29>] system_call_fastpath+0x16/0x1b

1594                         /* Now that we have two receive queues this
1595                          * shouldn't happen.
1596                          */
1597                         if (WARN(before(*seq, TCP_SKB_CB(skb)->seq),
1598                                  "recvmsg bug: copied %X seq %X rcvnxt %X fl %X\n",
1599                                  *seq, TCP_SKB_CB(skb)->seq, tp->rcv_nxt,
1600                                  flags))
1601                                 break;


Hopefully this means more to you guys than it does to me.

	Dave

^ permalink raw reply

* [PATCH net] net_sched: act: Delete estimator in error path.
From: Hiroaki SHIMODA @ 2012-08-06 15:45 UTC (permalink / raw)
  To: davem; +Cc: netdev

Some action modules free struct tcf_common in their error path
while estimator is still active. This results in est_timer()
dereference freed memory.
Add gen_kill_estimator() in ipt, pedit and simple action.

Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
---
 net/sched/act_ipt.c    |    7 ++++++-
 net/sched/act_pedit.c  |    5 ++++-
 net/sched/act_simple.c |    5 ++++-
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 60e281a..58fb3c7 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -185,7 +185,12 @@ err3:
 err2:
 	kfree(tname);
 err1:
-	kfree(pc);
+	if (ret == ACT_P_CREATED) {
+		if (est)
+			gen_kill_estimator(&pc->tcfc_bstats,
+					   &pc->tcfc_rate_est);
+		kfree_rcu(pc, tcfc_rcu);
+	}
 	return err;
 }
 
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 26aa2f6..45c53ab 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -74,7 +74,10 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
 		p = to_pedit(pc);
 		keys = kmalloc(ksize, GFP_KERNEL);
 		if (keys == NULL) {
-			kfree(pc);
+			if (est)
+				gen_kill_estimator(&pc->tcfc_bstats,
+						   &pc->tcfc_rate_est);
+			kfree_rcu(pc, tcfc_rcu);
 			return -ENOMEM;
 		}
 		ret = ACT_P_CREATED;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 3922f2a..3714f60 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -131,7 +131,10 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 		d = to_defact(pc);
 		ret = alloc_defdata(d, defdata);
 		if (ret < 0) {
-			kfree(pc);
+			if (est)
+				gen_kill_estimator(&pc->tcfc_bstats,
+						   &pc->tcfc_rate_est);
+			kfree_rcu(pc, tcfc_rcu);
 			return ret;
 		}
 		d->tcf_action = parm->action;
-- 
1.7.8.6

^ permalink raw reply related

* Re: [PATCH 1/8] netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
From: Eric Dumazet @ 2012-08-06 15:20 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David S. Miller
In-Reply-To: <1344263012-4031-2-git-send-email-amwang@redhat.com>

On Mon, 2012-08-06 at 22:23 +0800, Cong Wang wrote:
> slave_enable_netpoll() and __netpoll_setup() may be called
> with read_lock() held, so should use GFP_ATOMIC to allocate
> memory. Eric suggested to pass gfp flags to __netpoll_setup().
> 
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> Signed-off-by: Cong Wang <amwang@redhat.com>
> ---

You based this on net-next, but didnt add the net-next suffix in your
[PATCH ...] description.

Signed-off-by: Eric Dumazet <edumazet@google.com>

^ permalink raw reply

* [PATCH] net: ipv6: fix TCP early demux
From: Eric Dumazet @ 2012-08-06 15:09 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

From: Eric Dumazet <edumazet@google.com>

IPv6 needs a cookie in dst_check() call.

We need to add rx_dst_cookie and provide a family independent
sk_rx_dst_set(sk, skb) method to properly support IPv6 TCP early demux.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
Note: we could group sk_rx_dst/rx_dst_ifindex/rx_dst_cookie
in same cache line (in sk)

 include/linux/ipv6.h               |    1 +
 include/net/inet_connection_sock.h |    1 +
 include/net/inet_sock.h            |    9 ---------
 net/ipv4/tcp_input.c               |    4 +++-
 net/ipv4/tcp_ipv4.c                |   13 ++++++++++---
 net/ipv4/tcp_minisocks.c           |    2 +-
 net/ipv6/tcp_ipv6.c                |   27 +++++++++++++++++++++++++--
 7 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 379e433..879db26 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -369,6 +369,7 @@ struct ipv6_pinfo {
 	__u8			rcv_tclass;
 
 	__u32			dst_cookie;
+	__u32			rx_dst_cookie;
 
 	struct ipv6_mc_socklist	__rcu *ipv6_mc_list;
 	struct ipv6_ac_socklist	*ipv6_ac_list;
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 5ee66f5..ba1d361 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -39,6 +39,7 @@ struct inet_connection_sock_af_ops {
 	int	    (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);
 	void	    (*send_check)(struct sock *sk, struct sk_buff *skb);
 	int	    (*rebuild_header)(struct sock *sk);
+	void	    (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
 	int	    (*conn_request)(struct sock *sk, struct sk_buff *skb);
 	struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
 				      struct request_sock *req,
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 83b567f..613cfa4 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -249,13 +249,4 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
 	return flags;
 }
 
-static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
-{
-	struct dst_entry *dst = skb_dst(skb);
-
-	dst_hold(dst);
-	sk->sk_rx_dst = dst;
-	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
-}
-
 #endif	/* _INET_SOCK_H */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2fd2bc9..85308b9 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5392,6 +5392,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 
+	if (unlikely(sk->sk_rx_dst == NULL))
+		inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);
 	/*
 	 *	Header prediction.
 	 *	The code loosely follows the one in the famous
@@ -5605,7 +5607,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
 	tcp_set_state(sk, TCP_ESTABLISHED);
 
 	if (skb != NULL) {
-		inet_sk_rx_dst_set(sk, skb);
+		icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
 		security_inet_conn_established(sk, skb);
 	}
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 42b2a6a..272241f 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1627,9 +1627,6 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 				sk->sk_rx_dst = NULL;
 			}
 		}
-		if (unlikely(sk->sk_rx_dst == NULL))
-			inet_sk_rx_dst_set(sk, skb);
-
 		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
 			rsk = sk;
 			goto reset;
@@ -1872,10 +1869,20 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = {
 	.twsk_destructor= tcp_twsk_destructor,
 };
 
+static void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+
+	dst_hold(dst);
+	sk->sk_rx_dst = dst;
+	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
+}
+
 const struct inet_connection_sock_af_ops ipv4_specific = {
 	.queue_xmit	   = ip_queue_xmit,
 	.send_check	   = tcp_v4_send_check,
 	.rebuild_header	   = inet_sk_rebuild_header,
+	.sk_rx_dst_set	   = inet_sk_rx_dst_set,
 	.conn_request	   = tcp_v4_conn_request,
 	.syn_recv_sock	   = tcp_v4_syn_recv_sock,
 	.net_header_len	   = sizeof(struct iphdr),
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 232a90c..d9c9dce 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -387,7 +387,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
 		struct tcp_sock *oldtp = tcp_sk(sk);
 		struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
 
-		inet_sk_rx_dst_set(newsk, skb);
+		newicsk->icsk_af_ops->sk_rx_dst_set(newsk, skb);
 
 		/* TCP Cookie Transactions require space for the cookie pair,
 		 * as it differs for each connection.  There is no need to
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c66b90f..5a439e9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1447,7 +1447,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 		opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
 
 	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
+		struct dst_entry *dst = sk->sk_rx_dst;
+
 		sock_rps_save_rxhash(sk, skb);
+		if (dst) {
+			if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
+			    dst->ops->check(dst, np->rx_dst_cookie) == NULL) {
+				dst_release(dst);
+				sk->sk_rx_dst = NULL;
+			}
+		}
+
 		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
 			goto reset;
 		if (opt_skb)
@@ -1705,9 +1715,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
 			struct dst_entry *dst = sk->sk_rx_dst;
 			struct inet_sock *icsk = inet_sk(sk);
 			if (dst)
-				dst = dst_check(dst, 0);
+				dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
 			if (dst &&
-			    icsk->rx_dst_ifindex == inet6_iif(skb))
+			    icsk->rx_dst_ifindex == skb->skb_iif)
 				skb_dst_set_noref(skb, dst);
 		}
 	}
@@ -1719,10 +1729,23 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
 	.twsk_destructor= tcp_twsk_destructor,
 };
 
+static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb_dst(skb);
+	const struct rt6_info *rt = (const struct rt6_info *)dst;
+
+	dst_hold(dst);
+	sk->sk_rx_dst = dst;
+	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
+	if (rt->rt6i_node)
+		inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum;
+}
+
 static const struct inet_connection_sock_af_ops ipv6_specific = {
 	.queue_xmit	   = inet6_csk_xmit,
 	.send_check	   = tcp_v6_send_check,
 	.rebuild_header	   = inet6_sk_rebuild_header,
+	.sk_rx_dst_set	   = inet6_sk_rx_dst_set,
 	.conn_request	   = tcp_v6_conn_request,
 	.syn_recv_sock	   = tcp_v6_syn_recv_sock,
 	.net_header_len	   = sizeof(struct ipv6hdr),

^ permalink raw reply related

* [PATCH 2/2] documentation: dt: bindings: cpsw: fixing the examples for directly using it in dts file
From: Mugunthan V N @ 2012-08-06 15:05 UTC (permalink / raw)
  To: netdev
  Cc: davem, devicetree-discuss, linux-arm-kernel, linux-omap,
	Mugunthan V N
In-Reply-To: <1344265558-5724-1-git-send-email-mugunthanvnm@ti.com>

Fixing the cpsw device tree example to make it simpler to copy pastable to dts
file and use it directly.

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 Documentation/devicetree/bindings/net/cpsw.txt |  101 ++++++++++++-----------
 1 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index acca48c..dcaabe9 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -11,6 +11,7 @@ Required properties:
 - cpdma_channels 	: Specifies number of channels in CPDMA
 - host_port_no		: Specifies host port shift
 - cpdma_reg_ofs		: Specifies CPDMA submodule register offset
+- cpdma_sram_ofs	: Specifies CPDMA SRAM offset
 - ale_reg_ofs		: Specifies ALE submodule register offset
 - ale_entries		: Specifies No of entries ALE can hold
 - host_port_reg_ofs	: Specifies host port register offset
@@ -43,62 +44,66 @@ Examples:
 		reg = <0x4A100000 0x1000>;
 		interrupts = <55 0x4>;
 		interrupt-parent = <&intc>;
-		cpdma_channels = 8;
-		host_port_no = 0;
-		cpdma_reg_ofs = 0x800;
-		ale_reg_ofs = 0xd00;
-		ale_entries = 1024;
-		host_port_reg_ofs = 0x108;
-		hw_stats_reg_ofs = 0x900;
-		bd_ram_ofs = 0x2000;
-		bd_ram_size = 0x2000;
-		no_bd_ram = 0;
-		rx_descs = 64;
-		mac_control = 0x20;
-		slaves = 2;
-		slave@0 {
-			slave_reg_ofs = 0x208;
-			sliver_reg_ofs = 0xd80;
-			phy_id = "davinci_mdio-0:00"
-			mac-address = [00 04 9F 01 1B B8];
+		cpdma_channels = <8>;
+		host_port_no = <0>;
+		cpdma_reg_ofs = <0x800>;
+		cpdma_sram_ofs = <0xa00>;
+		ale_reg_ofs = <0xd00>;
+		ale_entries = <1024>;
+		host_port_reg_ofs = <0x108>;
+		hw_stats_reg_ofs = <0x900>;
+		bd_ram_ofs = <0x2000>;
+		bd_ram_size = <0x2000>;
+		no_bd_ram = <0>;
+		rx_descs = <64>;
+		mac_control = <0x20>;
+		slaves = <2>;
+		cpsw_emac0: slave@0 {
+			slave_reg_ofs = <0x208>;
+			sliver_reg_ofs = <0xd80>;
+			phy_id = "davinci_mdio.16:00";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
 		};
-		slave@1 {
-			slave_reg_ofs = 0x208;
-			sliver_reg_ofs = 0xd80;
-			phy_id = "davinci_mdio-0:01"
-			mac-address = [00 04 9F 01 1B B9];
+		cpsw_emac1: slave@1 {
+			slave_reg_ofs = <0x308>;
+			sliver_reg_ofs = <0xdc0>;
+			phy_id = "davinci_mdio.16:01";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
 		};
 	};
 
 (or)
-
 	mac: ethernet@4A100000 {
 		compatible = "ti,cpsw";
 		ti,hwmods = "cpgmac0";
-		cpdma_channels = 8;
-		host_port_no = 0;
-		cpdma_reg_ofs = 0x800;
-		ale_reg_ofs = 0xd00;
-		ale_entries = 1024;
-		host_port_reg_ofs = 0x108;
-		hw_stats_reg_ofs = 0x900;
-		bd_ram_ofs = 0x2000;
-		bd_ram_size = 0x2000;
-		no_bd_ram = 0;
-		rx_descs = 64;
-		mac_control = 0x20;
-		slaves = 2;
-		slave@0 {
-			slave_reg_ofs = 0x208;
-			sliver_reg_ofs = 0xd80;
-			phy_id = "davinci_mdio-0:00"
-			mac-address = [00 04 9F 01 1B B8];
+		cpdma_channels = <8>;
+		host_port_no = <0>;
+		cpdma_reg_ofs = <0x800>;
+		cpdma_sram_ofs = <0xa00>;
+		ale_reg_ofs = <0xd00>;
+		ale_entries = <1024>;
+		host_port_reg_ofs = <0x108>;
+		hw_stats_reg_ofs = <0x900>;
+		bd_ram_ofs = <0x2000>;
+		bd_ram_size = <0x2000>;
+		no_bd_ram = <0>;
+		rx_descs = <64>;
+		mac_control = <0x20>;
+		slaves = <2>;
+		cpsw_emac0: slave@0 {
+			slave_reg_ofs = <0x208>;
+			sliver_reg_ofs = <0xd80>;
+			phy_id = "davinci_mdio.16:00";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
 		};
-		slave@1 {
-			slave_reg_ofs = 0x208;
-			sliver_reg_ofs = 0xd80;
-			phy_id = "davinci_mdio-0:01"
-			mac-address = [00 04 9F 01 1B B9];
+		cpsw_emac1: slave@1 {
+			slave_reg_ofs = <0x308>;
+			sliver_reg_ofs = <0xdc0>;
+			phy_id = "davinci_mdio.16:01";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
 		};
-
 	};
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/2] drivers: net: ethernet: davince_mdio: device tree implementation
From: Mugunthan V N @ 2012-08-06 15:05 UTC (permalink / raw)
  To: netdev
  Cc: davem, devicetree-discuss, linux-arm-kernel, linux-omap,
	Mugunthan V N
In-Reply-To: <1344265558-5724-1-git-send-email-mugunthanvnm@ti.com>

device tree implementation for davinci mdio driver

Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
 .../devicetree/bindings/net/davinci-mdio.txt       |   33 ++++++++++++++++
 drivers/net/ethernet/ti/davinci_mdio.c             |   41 ++++++++++++++++++--
 2 files changed, 70 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/davinci-mdio.txt

diff --git a/Documentation/devicetree/bindings/net/davinci-mdio.txt b/Documentation/devicetree/bindings/net/davinci-mdio.txt
new file mode 100644
index 0000000..72efaaf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/davinci-mdio.txt
@@ -0,0 +1,33 @@
+TI SoC Davinci MDIO Controller Device Tree Bindings
+---------------------------------------------------
+
+Required properties:
+- compatible		: Should be "ti,davinci_mdio"
+- reg			: physical base address and size of the davinci mdio
+			  registers map
+- bus_freq		: Mdio Bus frequency
+
+Optional properties:
+- ti,hwmods		: Must be "davinci_mdio"
+
+Note: "ti,hwmods" field is used to fetch the base address and irq
+resources from TI, omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Examples:
+
+	mdio: davinci_mdio@4A101000 {
+		compatible = "ti,cpsw";
+		reg = <0x4A101000 0x1000>;
+		bus_freq = <1000000>;
+	};
+
+(or)
+
+	mdio: davinci_mdio@4A101000 {
+		compatible = "ti,cpsw";
+		ti,hwmods = "davinci_mdio";
+		bus_freq = <1000000>;
+	};
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index cd7ee20..573f3be 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -36,6 +36,8 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/davinci_emac.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 /*
  * This timeout definition is a worst-case ultra defensive measure against
@@ -289,6 +291,25 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
 	return 0;
 }
 
+static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
+			 struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	u32 prop;
+
+	if (!node)
+		return -EINVAL;
+
+	if (of_property_read_u32(node, "bus_freq", &prop)) {
+		pr_err("Missing bus_freq property in the DT.\n");
+		return -EINVAL;
+	}
+	data->bus_freq = prop;
+
+	return 0;
+}
+
+
 static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 {
 	struct mdio_platform_data *pdata = pdev->dev.platform_data;
@@ -304,8 +325,6 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	data->pdata = pdata ? (*pdata) : default_pdata;
-
 	data->bus = mdiobus_alloc();
 	if (!data->bus) {
 		dev_err(dev, "failed to alloc mii bus\n");
@@ -313,14 +332,22 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)
 		goto bail_out;
 	}
 
+	if (dev->of_node) {
+		if (davinci_mdio_probe_dt(&data->pdata, pdev))
+			data->pdata = default_pdata;
+		snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s", pdev->name);
+	} else {
+		data->pdata = pdata ? (*pdata) : default_pdata;
+		snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s-%x",
+			 pdev->name, pdev->id);
+	}
+
 	data->bus->name		= dev_name(dev);
 	data->bus->read		= davinci_mdio_read,
 	data->bus->write	= davinci_mdio_write,
 	data->bus->reset	= davinci_mdio_reset,
 	data->bus->parent	= dev;
 	data->bus->priv		= data;
-	snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s-%x",
-		pdev->name, pdev->id);
 
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
@@ -454,11 +481,17 @@ static const struct dev_pm_ops davinci_mdio_pm_ops = {
 	.resume		= davinci_mdio_resume,
 };
 
+static const struct of_device_id davinci_mdio_of_mtable[] = {
+	{ .compatible = "ti,davinci_mdio", },
+	{ /* sentinel */ },
+};
+
 static struct platform_driver davinci_mdio_driver = {
 	.driver = {
 		.name	 = "davinci_mdio",
 		.owner	 = THIS_MODULE,
 		.pm	 = &davinci_mdio_pm_ops,
+		.of_match_table = of_match_ptr(davinci_mdio_of_mtable),
 	},
 	.probe = davinci_mdio_probe,
 	.remove = __devexit_p(davinci_mdio_remove),
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/2] Add device tree support for davinci_mdio driver and fix cpsw DT binding documentation
From: Mugunthan V N @ 2012-08-06 15:05 UTC (permalink / raw)
  To: netdev
  Cc: Mugunthan V N, devicetree-discuss, linux-omap, davem,
	linux-arm-kernel

This patch set adds support for device tree for Davinci MDIO driver and fixes
CPSW DT binding documentation to make it copy pastable to dts file.

This patch set is tested with the following git tree on AM335X Beagle Bone
https://github.com/hvaibhav/am335x-linux/tree/am335x-upstream-staging-cpsw

Mugunthan V N (2):
  drivers: net: ethernet: davince_mdio: device tree implementation
  documentation: dt: bindings: cpsw: fixing the examples for directly
    using it in dts file

 Documentation/devicetree/bindings/net/cpsw.txt     |  101 ++++++++++---------
 .../devicetree/bindings/net/davinci-mdio.txt       |   33 +++++++
 drivers/net/ethernet/ti/davinci_mdio.c             |   41 +++++++-
 3 files changed, 123 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/davinci-mdio.txt

^ permalink raw reply

* RE: pch_gbe: dont-copy-payload (was [PATCH 1/4] ...)
From: Eric Dumazet @ 2012-08-06 14:52 UTC (permalink / raw)
  To: Andy Cress; +Cc: netdev
In-Reply-To: <40680C535D6FE6498883F1640FACD44D0122CF12@ka-exchange-1.kontronamerica.local>

On Mon, 2012-08-06 at 07:19 -0700, Andy Cress wrote:
> I found out why the proposed dont-copy-payload patch didn't work with
> this pch_gbe NIC.
> This NIC PHY requires 64-byte-aligned DMA, and the transmit buffers
> won't be transferred if skb->data is not 64-byte-aligned.  Apparently
> the data copy has a by-product of aligning the buffers.  
> 
> I tried using skb_reserve(skb,64) in pch_gbe_alloc_tx_buffers and
> pch-gbe_alloc_rx_buffers, but that didn't seem to resolve it.
> 
> How can I make sure that the transmit data buffers are
> 64-byte-aligned?
> 

There is no support for such requirement in linux stacks.

Only solution for the driver is to copy all frames to 64-byte-aligned
bounce buffers.

^ permalink raw reply

* [BUG] af_packet: loop at reception when using fanout
From: Eric Leblond @ 2012-08-06 14:21 UTC (permalink / raw)
  To: netdev, David Miller

[-- Attachment #1: Type: text/plain, Size: 1640 bytes --]

Hello,

When using fanout mode on a AF_PACKET socket, the packet sent via one of
the fanout socket are sent back to one of the socket in the fanout set.
I've read the code and the error seems to be in dev.c.
The code check if skb->sk is not equal to ptype->af_packet_priv but in
the fanout case, we should check that skb->sk is not in the sockets of
the fanout set.

Here's how could look a possible implementation of the fix:

diff --git a/net/core/dev.c b/net/core/dev.c
index 1cb0d8a..63d144f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1654,7 +1654,12 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
                 */
                if ((ptype->dev == dev || !ptype->dev) &&
                    (ptype->af_packet_priv == NULL ||
-                    (struct sock *)ptype->af_packet_priv != skb->sk)) {
+                       (((struct sock *)ptype->af_packet_priv != skb->sk)
+                       &&
+                        /* MISSING CHECK: af_packet_priv  skb->sk one of the socket in fanout id of skb */
+                       ! packet_sk_in_fanout(ptype, skb->sk)
+                        )
+                       ) {
                        if (pt_prev) {
                                deliver_skb(skb2, pt_prev, skb->dev);
                                pt_prev = ptype;

If this is done, we will have to export one function from the af_packet
module and I don't like the idea. If it is correct way to do it I can
implement this and propose a patch.

BR,
-- 
Eric Leblond 
Blog: http://home.regit.org/ - Portfolio: http://regit.500px.com/

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply related

* [PATCH 8/8] bridge: use list_for_each_entry() in netpoll functions
From: Cong Wang @ 2012-08-06 14:23 UTC (permalink / raw)
  To: netdev; +Cc: Cong Wang, Stephen Hemminger
In-Reply-To: <1344263012-4031-1-git-send-email-amwang@redhat.com>

We don't delete 'p' from the list in the loop,
so we can just use list_for_each_entry().

Cc: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/bridge/br_device.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f41ba40..32211fa 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -206,21 +206,20 @@ static void br_poll_controller(struct net_device *br_dev)
 static void br_netpoll_cleanup(struct net_device *dev)
 {
 	struct net_bridge *br = netdev_priv(dev);
-	struct net_bridge_port *p, *n;
+	struct net_bridge_port *p;
 
-	list_for_each_entry_safe(p, n, &br->port_list, list) {
+	list_for_each_entry(p, &br->port_list, list)
 		br_netpoll_disable(p);
-	}
 }
 
 static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni,
 			    gfp_t gfp)
 {
 	struct net_bridge *br = netdev_priv(dev);
-	struct net_bridge_port *p, *n;
+	struct net_bridge_port *p;
 	int err = 0;
 
-	list_for_each_entry_safe(p, n, &br->port_list, list) {
+	list_for_each_entry(p, &br->port_list, list) {
 		if (!p->dev)
 			continue;
 		err = br_netpoll_enable(p, gfp);
-- 
1.7.7.6

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox