Netdev List
 help / color / mirror / Atom feed
* [PATCH v3 3/3] Send cgroup_path in SCM_CGROUP
From: Jan Kaluza @ 2013-09-04  6:14 UTC (permalink / raw)
  To: davem
  Cc: LKML, netdev, eparis, rgb, tj, lizefan, containers, cgroups, viro,
	Jan Kaluza
In-Reply-To: <1378275261-4553-1-git-send-email-jkaluza@redhat.com>

Server-like processes in many cases need credentials and other
metadata of the peer, to decide if the calling process is allowed to
request a specific action, or the server just wants to log away this
type of information for auditing tasks.

The current practice to retrieve such process metadata is to look that
information up in procfs with the $PID received over SCM_CREDENTIALS.
This is sufficient for long-running tasks, but introduces a race which
cannot be worked around for short-living processes; the calling
process and all the information in /proc/$PID/ is gone before the
receiver of the socket message can look it up.

This introduces a new SCM type called SCM_CGROUP to allow the direct
attaching of "cgroup_path" to SCM, which is significantly more
efficient and will reliably avoid the race with the round-trip over
procfs.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>
---
 include/linux/socket.h |  1 +
 include/net/af_unix.h  |  1 +
 include/net/scm.h      | 15 +++++++++++++++
 net/core/scm.c         | 18 ++++++++++++++++++
 net/unix/af_unix.c     | 20 ++++++++++++++++++++
 5 files changed, 55 insertions(+)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 6c7ace0..621fff1 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -133,6 +133,7 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr
 #define SCM_AUDIT	0x04		/* rw: struct uaudit		*/
 #define SCM_PROCINFO	0x05	/* rw: comm + cmdline (NULL terminated
 					   array of char *) */
+#define SCM_CGROUP	0x06		/* rw: cgroup path */
 
 struct ucred {
 	__u32	pid;
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 05c7678..c49bf35 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -32,6 +32,7 @@ struct unix_skb_parms_scm {
 	unsigned int sessionid;
 	char *procinfo;
 	int procinfo_len;
+	char *cgroup_path;
 };
 
 struct unix_skb_parms {
diff --git a/include/net/scm.h b/include/net/scm.h
index 3346030..5398826 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -41,6 +41,7 @@ struct scm_cookie {
 	struct scm_creds	creds;		/* Skb credentials	*/
 	struct scm_audit	audit;		/* Skb audit	*/
 	struct scm_procinfo	procinfo;	/* Skb procinfo */
+	char *cgroup_path;
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Passed security ID 	*/
 #endif
@@ -52,6 +53,7 @@ extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
 extern int scm_get_current_procinfo(char **procinfo);
+extern int scm_get_current_cgroup_path(char **cgroup_path);
 
 #ifdef CONFIG_SECURITY_NETWORK
 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
@@ -86,6 +88,12 @@ static inline void scm_set_procinfo(struct scm_cookie *scm,
 	scm->procinfo.len = len;
 }
 
+static inline void scm_set_cgroup_path(struct scm_cookie *scm,
+				    char *cgroup_path)
+{
+	scm->cgroup_path = cgroup_path;
+}
+
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
 {
 	put_pid(scm->pid);
@@ -140,6 +148,9 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
 			security_release_secctx(secdata, seclen);
 		}
 	}
+
+	kfree(scm->cgroup_path);
+	scm->cgroup_path = NULL;
 }
 #else
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
@@ -172,6 +183,10 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 		put_cmsg(msg, SOL_SOCKET, SCM_AUDIT, sizeof(uaudits), &uaudits);
 		put_cmsg(msg, SOL_SOCKET, SCM_PROCINFO, scm->procinfo.len,
 				 scm->procinfo.procinfo);
+		if (scm->cgroup_path) {
+			put_cmsg(msg, SOL_SOCKET, SCM_CGROUP,
+				 strlen(scm->cgroup_path), scm->cgroup_path);
+		}
 	}
 
 	scm_destroy_cred(scm);
diff --git a/net/core/scm.c b/net/core/scm.c
index 09ec044..2d408b9 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -404,3 +404,21 @@ out:
 	return res;
 }
 EXPORT_SYMBOL(scm_get_current_procinfo);
+
+int scm_get_current_cgroup_path(char **cgroup_path)
+{
+	int ret = 0;
+
+	*cgroup_path = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!(*cgroup_path))
+		return -ENOMEM;
+
+	ret = task_cgroup_path(current, *cgroup_path, PATH_MAX);
+	if (ret < 0) {
+		kfree(*cgroup_path);
+		*cgroup_path = NULL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(scm_get_current_cgroup_path);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index ab0be13..b638083 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1344,6 +1344,7 @@ static void unix_destruct_scm(struct sk_buff *skb)
 	if (UNIXCB(skb).scm) {
 		scm.procinfo.procinfo = UNIXSCM(skb).procinfo;
 		scm.procinfo.len = UNIXSCM(skb).procinfo_len;
+		scm.cgroup_path = UNIXSCM(skb).cgroup_path;
 	}
 	if (UNIXCB(skb).fp)
 		unix_detach_fds(&scm, skb);
@@ -1420,6 +1421,14 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
 			return -ENOMEM;
 	}
 
+	UNIXSCM(skb).cgroup_path = NULL;
+	if (scm->cgroup_path) {
+		UNIXSCM(skb).cgroup_path = kstrdup(scm->cgroup_path,
+						   GFP_KERNEL);
+		if (!UNIXSCM(skb).cgroup_path)
+			return -ENOMEM;
+	}
+
 	skb->destructor = unix_destruct_scm;
 	return err;
 }
@@ -1443,6 +1452,7 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
 		UNIXSCM(skb).sessionid = audit_get_sessionid(current);
 		UNIXSCM(skb).procinfo_len = scm_get_current_procinfo(
 			&UNIXSCM(skb).procinfo);
+		scm_get_current_cgroup_path(&UNIXSCM(skb).cgroup_path);
 	}
 }
 
@@ -1849,6 +1859,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 						 GFP_KERNEL),
 					 UNIXSCM(skb).procinfo_len);
 		}
+		if (UNIXSCM(skb).cgroup_path) {
+			scm_set_cgroup_path(siocb->scm,
+					    kstrdup(UNIXSCM(skb).cgroup_path,
+						    GFP_KERNEL));
+		}
 	}
 	unix_set_secdata(siocb->scm, skb);
 
@@ -2042,6 +2057,11 @@ again:
 						GFP_KERNEL),
 						UNIXSCM(skb).procinfo_len);
 				}
+				if (UNIXSCM(skb).cgroup_path) {
+					scm_set_cgroup_path(siocb->scm,
+							    kstrdup(UNIXSCM(skb).cgroup_path,
+							    GFP_KERNEL));
+				}
 			}
 			check_creds = 1;
 		}
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v3 2/3] Send comm and cmdline in SCM_PROCINFO
From: Jan Kaluza @ 2013-09-04  6:14 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: Jan Kaluza, rgb-H+wXaHxf7aLQT0dZR+AlfA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, LKML,
	eparis-H+wXaHxf7aLQT0dZR+AlfA,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn, tj-DgEjT+Ai2ygdnm+yROfE0A,
	cgroups-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1378275261-4553-1-git-send-email-jkaluza-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Server-like processes in many cases need credentials and other
metadata of the peer, to decide if the calling process is allowed to
request a specific action, or the server just wants to log away this
type of information for auditing tasks.

The current practice to retrieve such process metadata is to look that
information up in procfs with the $PID received over SCM_CREDENTIALS.
This is sufficient for long-running tasks, but introduces a race which
cannot be worked around for short-living processes; the calling
process and all the information in /proc/$PID/ is gone before the
receiver of the socket message can look it up.

This introduces a new SCM type called SCM_PROCINFO to allow the direct
attaching of "comm" and "cmdline" to SCM, which is significantly more
efficient and will reliably avoid the race with the round-trip over
procfs.

To achieve that, new struct called unix_skb_parms_scm had to be created,
because otherwise unix_skb_parms would be too big.

scm_get_current_procinfo is inspired by ./fs/proc/base.c.

Signed-off-by: Jan Kaluza <jkaluza-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 include/linux/socket.h |  2 ++
 include/net/af_unix.h  | 11 +++++++--
 include/net/scm.h      | 24 +++++++++++++++++++
 net/core/scm.c         | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 net/unix/af_unix.c     | 57 +++++++++++++++++++++++++++++++++++++------
 5 files changed, 150 insertions(+), 9 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 505047a..6c7ace0 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -131,6 +131,8 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr
 #define SCM_CREDENTIALS 0x02		/* rw: struct ucred		*/
 #define SCM_SECURITY	0x03		/* rw: security label		*/
 #define SCM_AUDIT	0x04		/* rw: struct uaudit		*/
+#define SCM_PROCINFO	0x05	/* rw: comm + cmdline (NULL terminated
+					   array of char *) */
 
 struct ucred {
 	__u32	pid;
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 3b9d22a..05c7678 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -27,6 +27,13 @@ struct unix_address {
 	struct sockaddr_un name[0];
 };
 
+struct unix_skb_parms_scm {
+	kuid_t loginuid;
+	unsigned int sessionid;
+	char *procinfo;
+	int procinfo_len;
+};
+
 struct unix_skb_parms {
 	struct pid		*pid;		/* Skb credentials	*/
 	kuid_t			uid;
@@ -36,12 +43,12 @@ struct unix_skb_parms {
 	u32			secid;		/* Security ID		*/
 #endif
 	u32			consumed;
-	kuid_t			loginuid;
-	unsigned int		sessionid;
+	struct unix_skb_parms_scm *scm;
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms *)&((skb)->cb))
 #define UNIXSID(skb)	(&UNIXCB((skb)).secid)
+#define UNIXSCM(skb)	(*(UNIXCB((skb)).scm))
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
 #define unix_state_unlock(s)	spin_unlock(&unix_sk(s)->lock)
diff --git a/include/net/scm.h b/include/net/scm.h
index e349a25..3346030 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -30,11 +30,17 @@ struct scm_fp_list {
 	struct file		*fp[SCM_MAX_FD];
 };
 
+struct scm_procinfo {
+	char *procinfo;
+	int len;
+};
+
 struct scm_cookie {
 	struct pid		*pid;		/* Skb credentials */
 	struct scm_fp_list	*fp;		/* Passed files		*/
 	struct scm_creds	creds;		/* Skb credentials	*/
 	struct scm_audit	audit;		/* Skb audit	*/
+	struct scm_procinfo	procinfo;	/* Skb procinfo */
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Passed security ID 	*/
 #endif
@@ -45,6 +51,7 @@ extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
+extern int scm_get_current_procinfo(char **procinfo);
 
 #ifdef CONFIG_SECURITY_NETWORK
 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
@@ -72,10 +79,20 @@ static inline void scm_set_audit(struct scm_cookie *scm,
 	scm->audit.sessionid = sessionid;
 }
 
+static inline void scm_set_procinfo(struct scm_cookie *scm,
+				    char *procinfo, int len)
+{
+	scm->procinfo.procinfo = procinfo;
+	scm->procinfo.len = len;
+}
+
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
 {
 	put_pid(scm->pid);
 	scm->pid  = NULL;
+	kfree(scm->procinfo.procinfo);
+	scm->procinfo.procinfo = NULL;
+	scm->procinfo.len = 0;
 }
 
 static __inline__ void scm_destroy(struct scm_cookie *scm)
@@ -88,6 +105,8 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 			       struct scm_cookie *scm, bool forcecreds)
 {
+	char *procinfo;
+	int len;
 	memset(scm, 0, sizeof(*scm));
 	scm->creds.uid = INVALID_UID;
 	scm->creds.gid = INVALID_GID;
@@ -96,6 +115,9 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 			     current_gid());
 		scm_set_audit(scm, audit_get_loginuid(current),
 			      audit_get_sessionid(current));
+		len = scm_get_current_procinfo(&procinfo);
+		if (len > 0)
+			scm_set_procinfo(scm, procinfo, len);
 	}
 	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
@@ -148,6 +170,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 		};
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
 		put_cmsg(msg, SOL_SOCKET, SCM_AUDIT, sizeof(uaudits), &uaudits);
+		put_cmsg(msg, SOL_SOCKET, SCM_PROCINFO, scm->procinfo.len,
+				 scm->procinfo.procinfo);
 	}
 
 	scm_destroy_cred(scm);
diff --git a/net/core/scm.c b/net/core/scm.c
index 03795d0..09ec044 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -339,3 +339,68 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
 	return new_fpl;
 }
 EXPORT_SYMBOL(scm_fp_dup);
+
+int scm_get_current_procinfo(char **procinfo)
+{
+	int res = 0;
+	unsigned int len;
+	char *buffer = NULL;
+	struct mm_struct *mm;
+	int comm_len = strlen(current->comm);
+
+	*procinfo = NULL;
+
+	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	mm = get_task_mm(current);
+	if (!mm)
+		goto out;
+	if (!mm->arg_end)
+		goto out_mm;    /* Shh! No looking before we're done */
+
+	len = mm->arg_end - mm->arg_start;
+
+	if (len > PAGE_SIZE)
+		len = PAGE_SIZE;
+
+	res = access_process_vm(current, mm->arg_start, buffer, len, 0);
+
+	/* If the nul at the end of args has been overwritten, then
+	 * assume application is using setproctitle(3).
+	 */
+	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
+		len = strnlen(buffer, res);
+		if (len < res) {
+			res = len;
+		} else {
+			len = mm->env_end - mm->env_start;
+			if (len > PAGE_SIZE - res)
+				len = PAGE_SIZE - res;
+			res += access_process_vm(current, mm->env_start,
+						 buffer+res, len, 0);
+			res = strnlen(buffer, res);
+		}
+	}
+
+	/* strlen(comm) + \0 + len of cmdline */
+	len = comm_len + 1 + res;
+	*procinfo = kmalloc(len, GFP_KERNEL);
+	if (!*procinfo) {
+		res = -ENOMEM;
+		goto out_mm;
+	}
+
+	memcpy(*procinfo, current->comm, comm_len + 1); /* include \0 */
+	if (res > 0)
+		memcpy(*procinfo + comm_len + 1, buffer, res);
+	res = len;
+
+out_mm:
+	mmput(mm);
+out:
+	kfree(buffer);
+	return res;
+}
+EXPORT_SYMBOL(scm_get_current_procinfo);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index c410f76..ab0be13 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1341,9 +1341,14 @@ static void unix_destruct_scm(struct sk_buff *skb)
 	struct scm_cookie scm;
 	memset(&scm, 0, sizeof(scm));
 	scm.pid  = UNIXCB(skb).pid;
+	if (UNIXCB(skb).scm) {
+		scm.procinfo.procinfo = UNIXSCM(skb).procinfo;
+		scm.procinfo.len = UNIXSCM(skb).procinfo_len;
+	}
 	if (UNIXCB(skb).fp)
 		unix_detach_fds(&scm, skb);
 
+	kfree(UNIXCB(skb).scm);
 	/* Alas, it calls VFS */
 	/* So fscking what? fput() had been SMP-safe since the last Summer */
 	scm_destroy(&scm);
@@ -1390,15 +1395,31 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
 {
 	int err = 0;
 
+	if (!UNIXCB(skb).scm) {
+		UNIXCB(skb).scm = kmalloc(sizeof(struct unix_skb_parms_scm),
+					  GFP_KERNEL);
+		if (!UNIXCB(skb).scm)
+			return -ENOMEM;
+	}
+
 	UNIXCB(skb).pid  = get_pid(scm->pid);
 	UNIXCB(skb).uid = scm->creds.uid;
 	UNIXCB(skb).gid = scm->creds.gid;
-	UNIXCB(skb).loginuid = scm->audit.loginuid;
-	UNIXCB(skb).sessionid = scm->audit.sessionid;
+	UNIXSCM(skb).loginuid = scm->audit.loginuid;
+	UNIXSCM(skb).sessionid = scm->audit.sessionid;
 	UNIXCB(skb).fp = NULL;
 	if (scm->fp && send_fds)
 		err = unix_attach_fds(scm, skb);
 
+	UNIXSCM(skb).procinfo = NULL;
+	if (scm->procinfo.procinfo) {
+		UNIXSCM(skb).procinfo_len = scm->procinfo.len;
+		UNIXSCM(skb).procinfo = kmemdup(scm->procinfo.procinfo,
+					scm->procinfo.len, GFP_KERNEL);
+		if (!UNIXSCM(skb).procinfo)
+			return -ENOMEM;
+	}
+
 	skb->destructor = unix_destruct_scm;
 	return err;
 }
@@ -1418,8 +1439,10 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
 	    test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
 		UNIXCB(skb).pid  = get_pid(task_tgid(current));
 		current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
-		UNIXCB(skb).loginuid = audit_get_loginuid(current);
-		UNIXCB(skb).sessionid = audit_get_sessionid(current);
+		UNIXSCM(skb).loginuid = audit_get_loginuid(current);
+		UNIXSCM(skb).sessionid = audit_get_sessionid(current);
+		UNIXSCM(skb).procinfo_len = scm_get_current_procinfo(
+			&UNIXSCM(skb).procinfo);
 	}
 }
 
@@ -1816,7 +1839,17 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
 	}
 	scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
-	scm_set_audit(siocb->scm, UNIXCB(skb).loginuid, UNIXCB(skb).sessionid);
+	if (UNIXCB(skb).scm) {
+		scm_set_audit(siocb->scm, UNIXSCM(skb).loginuid,
+			      UNIXSCM(skb).sessionid);
+		if (UNIXSCM(skb).procinfo) {
+			scm_set_procinfo(siocb->scm,
+					 kmemdup(UNIXSCM(skb).procinfo,
+						 UNIXSCM(skb).procinfo_len,
+						 GFP_KERNEL),
+					 UNIXSCM(skb).procinfo_len);
+		}
+	}
 	unix_set_secdata(siocb->scm, skb);
 
 	if (!(flags & MSG_PEEK)) {
@@ -1998,8 +2031,18 @@ again:
 		} else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
 			/* Copy credentials */
 			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
-			scm_set_audit(siocb->scm, UNIXCB(skb).loginuid,
-				      UNIXCB(skb).sessionid);
+			if (UNIXCB(skb).scm) {
+				scm_set_audit(siocb->scm,
+					      UNIXSCM(skb).loginuid,
+					      UNIXSCM(skb).sessionid);
+				if (UNIXSCM(skb).procinfo) {
+					scm_set_procinfo(siocb->scm,
+						kmemdup(UNIXSCM(skb).procinfo,
+						UNIXSCM(skb).procinfo_len,
+						GFP_KERNEL),
+						UNIXSCM(skb).procinfo_len);
+				}
+			}
 			check_creds = 1;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v3 1/3] Send loginuid and sessionid in SCM_AUDIT
From: Jan Kaluza @ 2013-09-04  6:14 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: Jan Kaluza, rgb-H+wXaHxf7aLQT0dZR+AlfA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, LKML,
	eparis-H+wXaHxf7aLQT0dZR+AlfA,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn, tj-DgEjT+Ai2ygdnm+yROfE0A,
	cgroups-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1378275261-4553-1-git-send-email-jkaluza-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Server-like processes in many cases need credentials and other
metadata of the peer, to decide if the calling process is allowed to
request a specific action, or the server just wants to log away this
type of information for auditing tasks.

The current practice to retrieve such process metadata is to look that
information up in procfs with the $PID received over SCM_CREDENTIALS.
This is sufficient for long-running tasks, but introduces a race which
cannot be worked around for short-living processes; the calling
process and all the information in /proc/$PID/ is gone before the
receiver of the socket message can look it up.

This introduces a new SCM type called SCM_AUDIT to allow the direct
attaching of "loginuid" and "sessionid" to SCM, which is significantly more
efficient and will reliably avoid the race with the round-trip over
procfs.

Signed-off-by: Jan Kaluza <jkaluza-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 include/linux/socket.h |  6 ++++++
 include/net/af_unix.h  |  2 ++
 include/net/scm.h      | 28 ++++++++++++++++++++++++++--
 net/unix/af_unix.c     |  7 +++++++
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 445ef75..505047a 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -130,6 +130,7 @@ static inline struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr
 #define	SCM_RIGHTS	0x01		/* rw: access rights (array of int) */
 #define SCM_CREDENTIALS 0x02		/* rw: struct ucred		*/
 #define SCM_SECURITY	0x03		/* rw: security label		*/
+#define SCM_AUDIT	0x04		/* rw: struct uaudit		*/
 
 struct ucred {
 	__u32	pid;
@@ -137,6 +138,11 @@ struct ucred {
 	__u32	gid;
 };
 
+struct uaudit {
+	__u32	loginuid;
+	__u32	sessionid;
+};
+
 /* Supported address families. */
 #define AF_UNSPEC	0
 #define AF_UNIX		1	/* Unix domain sockets 		*/
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index a175ba4..3b9d22a 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -36,6 +36,8 @@ struct unix_skb_parms {
 	u32			secid;		/* Security ID		*/
 #endif
 	u32			consumed;
+	kuid_t			loginuid;
+	unsigned int		sessionid;
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms *)&((skb)->cb))
diff --git a/include/net/scm.h b/include/net/scm.h
index 8de2d37..e349a25 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -6,6 +6,7 @@
 #include <linux/security.h>
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
+#include <linux/audit.h>
 
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
@@ -18,6 +19,11 @@ struct scm_creds {
 	kgid_t	gid;
 };
 
+struct scm_audit {
+	kuid_t loginuid;
+	unsigned int sessionid;
+};
+
 struct scm_fp_list {
 	short			count;
 	short			max;
@@ -28,6 +34,7 @@ struct scm_cookie {
 	struct pid		*pid;		/* Skb credentials */
 	struct scm_fp_list	*fp;		/* Passed files		*/
 	struct scm_creds	creds;		/* Skb credentials	*/
+	struct scm_audit	audit;		/* Skb audit	*/
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Passed security ID 	*/
 #endif
@@ -58,6 +65,13 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
 	scm->creds.gid = gid;
 }
 
+static inline void scm_set_audit(struct scm_cookie *scm,
+				    kuid_t loginuid, unsigned int sessionid)
+{
+	scm->audit.loginuid = loginuid;
+	scm->audit.sessionid = sessionid;
+}
+
 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
 {
 	put_pid(scm->pid);
@@ -77,8 +91,12 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 	memset(scm, 0, sizeof(*scm));
 	scm->creds.uid = INVALID_UID;
 	scm->creds.gid = INVALID_GID;
-	if (forcecreds)
-		scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
+	if (forcecreds) {
+		scm_set_cred(scm, task_tgid(current), current_uid(),
+			     current_gid());
+		scm_set_audit(scm, audit_get_loginuid(current),
+			      audit_get_sessionid(current));
+	}
 	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
 		return 0;
@@ -123,7 +141,13 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 			.uid = from_kuid_munged(current_ns, scm->creds.uid),
 			.gid = from_kgid_munged(current_ns, scm->creds.gid),
 		};
+		struct uaudit uaudits = {
+			.loginuid = from_kuid_munged(current_ns,
+						     scm->audit.loginuid),
+			.sessionid = scm->audit.sessionid,
+		};
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
+		put_cmsg(msg, SOL_SOCKET, SCM_AUDIT, sizeof(uaudits), &uaudits);
 	}
 
 	scm_destroy_cred(scm);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 86de99a..c410f76 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1393,6 +1393,8 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
 	UNIXCB(skb).pid  = get_pid(scm->pid);
 	UNIXCB(skb).uid = scm->creds.uid;
 	UNIXCB(skb).gid = scm->creds.gid;
+	UNIXCB(skb).loginuid = scm->audit.loginuid;
+	UNIXCB(skb).sessionid = scm->audit.sessionid;
 	UNIXCB(skb).fp = NULL;
 	if (scm->fp && send_fds)
 		err = unix_attach_fds(scm, skb);
@@ -1416,6 +1418,8 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
 	    test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) {
 		UNIXCB(skb).pid  = get_pid(task_tgid(current));
 		current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid);
+		UNIXCB(skb).loginuid = audit_get_loginuid(current);
+		UNIXCB(skb).sessionid = audit_get_sessionid(current);
 	}
 }
 
@@ -1812,6 +1816,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
 	}
 	scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
+	scm_set_audit(siocb->scm, UNIXCB(skb).loginuid, UNIXCB(skb).sessionid);
 	unix_set_secdata(siocb->scm, skb);
 
 	if (!(flags & MSG_PEEK)) {
@@ -1993,6 +1998,8 @@ again:
 		} else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
 			/* Copy credentials */
 			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
+			scm_set_audit(siocb->scm, UNIXCB(skb).loginuid,
+				      UNIXCB(skb).sessionid);
 			check_creds = 1;
 		}
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v3 0/3] Send audit/procinfo/cgroup data in socket-level control message
From: Jan Kaluza @ 2013-09-04  6:14 UTC (permalink / raw)
  To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
  Cc: Jan Kaluza, rgb-H+wXaHxf7aLQT0dZR+AlfA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, LKML,
	eparis-H+wXaHxf7aLQT0dZR+AlfA,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn, tj-DgEjT+Ai2ygdnm+yROfE0A,
	cgroups-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1377614400-27122-1-git-send-email-jkaluza-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Hi,

this patchset against net-next (applies also to linux-next) adds 3 new types
of "Socket"-level control message (SCM_AUDIT, SCM_PROCINFO and SCM_CGROUP).

Server-like processes in many cases need credentials and other
metadata of the peer, to decide if the calling process is allowed to
request a specific action, or the server just wants to log away this
type of information for auditing tasks.

The current practice to retrieve such process metadata is to look that
information up in procfs with the $PID received over SCM_CREDENTIALS.
This is sufficient for long-running tasks, but introduces a race which
cannot be worked around for short-living processes; the calling
process and all the information in /proc/$PID/ is gone before the
receiver of the socket message can look it up.

Changes introduced in this patchset can also increase performance
of such server-like processes, because current way of opening and
parsing /proc/$PID/* files is much more expensive than receiving these
metadata using SCM.

Changes in v3:
- Better description of patches (Thanks to Kay Sievers)

Changes in v2:
- use PATH_MAX instead of PAGE_SIZE in SCM_CGROUP patch
- describe each patch individually

Jan Kaluza (3):
  Send loginuid and sessionid in SCM_AUDIT
  Send comm and cmdline in SCM_PROCINFO
  Send cgroup_path in SCM_CGROUP

 include/linux/socket.h |  9 ++++++
 include/net/af_unix.h  | 10 ++++++
 include/net/scm.h      | 67 ++++++++++++++++++++++++++++++++++++++--
 net/core/scm.c         | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
 net/unix/af_unix.c     | 70 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 237 insertions(+), 2 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* Re: xen-netback: count number required slots for an skb more carefully
From: Matt Wilson @ 2013-09-04  6:04 UTC (permalink / raw)
  To: annie li
  Cc: Wei Liu, David Vrabel, xen-devel, Konrad Rzeszutek Wilk,
	Boris Ostrovsky, Ian Campbell, netdev, msw
In-Reply-To: <52269A37.7030600@oracle.com>

On Wed, Sep 04, 2013 at 10:25:59AM +0800, annie li wrote:
> On 2013-9-4 5:53, Wei Liu wrote:
[...]
> >Matt, do you fancy sending the final version? IIRC the commit message
> >needs to be re-written. I personally still prefer Matt's solution as
> >it a) make efficient use of the ring, b) uses ring pointers to
> >calculate slots which is most accurate, c) removes the dependence on
> >MAX_SKB_FRAGS in guest RX path.
> >
> >Anyway, we should get this fixed ASAP.
> 
> Totally agree. This issue is easy to be reproduced with large MTU.
> It is better to upstream the fix soon in case others hit it and
> waste time to fix it.

I'd like to go with Xi's proposed patch that I posed earlier. The main
thing that's kept me from sending a final version is lack of time to
retest against a newer kernel.

Could someone help out with that? I probably can't get to it until the
end of the week.

Sorry for the delay. :-(

--msw

^ permalink raw reply

* Re: [PATCH net-next 3/5] driver/net: enic: Try DMA 64 first, then failover to DMA
From: Govindarajulu Varadarajan @ 2013-09-04  6:01 UTC (permalink / raw)
  To: Govindarajulu Varadarajan
  Cc: davem, netdev, linux-kernel, benve, ssujith, nistrive, umalhi
In-Reply-To: <1378273638-7780-4-git-send-email-govindarajulu90@gmail.com>

Hi Dave

The subject for this should be "driver/net: enic: Try DMA 64 first, then
failover to DMA 32"

The "32" got truncated, please add this while committing. Let me know if
you want me to send another patch.

thanks
//govind

On Wed, 4 Sep 2013, Govindarajulu Varadarajan wrote:

> In servers with more than 1.1 TB of RAM, the existing 40/32 bit DMA
> could cause failure as the DMA-able address could go outside the range
> addressable using 40/32 bits.
>
> The following patch first tried 64 bit DMA if possible, failover to 32
> bit.
>
> Signed-off-by: Sujith Sankar <ssujith@cisco.com>
> Signed-off-by: Christian Benvenuti <benve@cisco.com>
> Signed-off-by: Govindarajulu Varadarajan <govindarajulu90@gmail.com>

^ permalink raw reply

* Re: [PATCH v2 net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Eric Dumazet @ 2013-09-04  5:59 UTC (permalink / raw)
  To: Jason Wang
  Cc: David Miller, netdev, Yuchung Cheng, Neal Cardwell,
	Michael S. Tsirkin
In-Reply-To: <5226C4A0.6040709@redhat.com>

On Wed, 2013-09-04 at 13:26 +0800, Jason Wang wrote:

> I see both degradation and jitter when using fq with virtio-net. Guest
> to guest performance drops from 8Gb/s to 3Gb/s-7Gb/s. Guest to local
> host drops from 8Gb/s to 4Gb/s-6Gb/s. Guest to external host with ixgbe
> drops from 9Gb/s to 7Gb/s
> 
> I didn't meet the issue when using sfq or disabling pacing.
> 
> So it looks like it was caused by the inaccuracy and jitter of the
> pacing estimation in a virt guest?

Well, using virtio-net means you use FQ without pacing.

Make sure you do not have reorders because of a bug in queue selection.

TCP stack has the ooo_okay thing, I do not think a VM can get it.

nstat >/dev/null ; <your test> ; nstat

And tcpdump would certainly help ;)

^ permalink raw reply

* [PATCH net-next 5/5] driver/net: enic: update enic maintainers and driver
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan
In-Reply-To: <1378273638-7780-1-git-send-email-govindarajulu90@gmail.com>

Signed-off-by: Govindarajulu Varadarajan <govindarajulu90@gmail.com>
Signed-off-by: Sujith Sankar <ssujith@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
 MAINTAINERS                            | 3 ++-
 drivers/net/ethernet/cisco/enic/enic.h | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 705bb96..ecb83cd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2076,7 +2076,8 @@ F:	drivers/usb/chipidea/
 
 CISCO VIC ETHERNET NIC DRIVER
 M:	Christian Benvenuti <benve@cisco.com>
-M:	Roopa Prabhu <roprabhu@cisco.com>
+M:	Sujith Sankar <ssujith@cisco.com>
+M:	Govindarajulu Varadarajan <govindarajulu90@gmail.com>
 M:	Neel Patel <neepatel@cisco.com>
 M:	Nishank Trivedi <nistrive@cisco.com>
 S:	Supported
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index 34b637a..e9f7c65 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,7 +32,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.1.1.43"
+#define DRV_VERSION		"2.1.1.50"
 #define DRV_COPYRIGHT		"Copyright 2008-2013 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
-- 
1.8.4

^ permalink raw reply related

* [PATCH net-next 4/5] driver/net: enic: Exposing symbols for Cisco's low latency driver
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan
In-Reply-To: <1378273638-7780-1-git-send-email-govindarajulu90@gmail.com>

This patch exposes symbols for usnic low latency driver that can be used to 
register and unregister vNics as well to traverse the resources on vNics.

Signed-off-by: Upinder Malhi <umalhi@cisco.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
 drivers/net/ethernet/cisco/enic/vnic_dev.c | 10 ++++++++++
 drivers/net/ethernet/cisco/enic/vnic_dev.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c
index 97455c5..69dd925 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.c
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c
@@ -175,6 +175,7 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
 {
 	return vdev->res[type].count;
 }
+EXPORT_SYMBOL(vnic_dev_get_res_count);
 
 void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
 	unsigned int index)
@@ -193,6 +194,7 @@ void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
 		return (char __iomem *)vdev->res[type].vaddr;
 	}
 }
+EXPORT_SYMBOL(vnic_dev_get_res);
 
 static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
 	unsigned int desc_count, unsigned int desc_size)
@@ -942,6 +944,7 @@ void vnic_dev_unregister(struct vnic_dev *vdev)
 		kfree(vdev);
 	}
 }
+EXPORT_SYMBOL(vnic_dev_unregister);
 
 struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
 	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
@@ -969,6 +972,13 @@ err_out:
 	vnic_dev_unregister(vdev);
 	return NULL;
 }
+EXPORT_SYMBOL(vnic_dev_register);
+
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev)
+{
+	return vdev->pdev;
+}
+EXPORT_SYMBOL(vnic_dev_get_pdev);
 
 int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len)
 {
diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h
index f3d9b79..e670029 100644
--- a/drivers/net/ethernet/cisco/enic/vnic_dev.h
+++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h
@@ -127,6 +127,7 @@ int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
 struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
 	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
 	unsigned int num_bars);
+struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev);
 int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len);
 int vnic_dev_enable2(struct vnic_dev *vdev, int active);
 int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status);
-- 
1.8.4

^ permalink raw reply related

* [PATCH net-next 3/5] driver/net: enic: Try DMA 64 first, then failover to DMA
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan
In-Reply-To: <1378273638-7780-1-git-send-email-govindarajulu90@gmail.com>

In servers with more than 1.1 TB of RAM, the existing 40/32 bit DMA
could cause failure as the DMA-able address could go outside the range
addressable using 40/32 bits.

The following patch first tried 64 bit DMA if possible, failover to 32
bit.

Signed-off-by: Sujith Sankar <ssujith@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: Govindarajulu Varadarajan <govindarajulu90@gmail.com>
---
 drivers/net/ethernet/cisco/enic/enic_main.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 93898ba..7b756cf9 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2080,11 +2080,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_set_master(pdev);
 
 	/* Query PCI controller on system for DMA addressing
-	 * limitation for the device.  Try 40-bit first, and
+	 * limitation for the device.  Try 64-bit first, and
 	 * fail to 32-bit.
 	 */
 
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
 	if (err) {
 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (err) {
@@ -2098,10 +2098,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			goto err_out_release_regions;
 		}
 	} else {
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 		if (err) {
 			dev_err(dev, "Unable to obtain %u-bit DMA "
-				"for consistent allocations, aborting\n", 40);
+				"for consistent allocations, aborting\n", 64);
 			goto err_out_release_regions;
 		}
 		using_dac = 1;
-- 
1.8.4

^ permalink raw reply related

* [PATCH net-next 2/5] driver/net: enic: record q_number and rss_hash for skb
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan
In-Reply-To: <1378273638-7780-1-git-send-email-govindarajulu90@gmail.com>

The following patch sets the skb->rxhash and skb->q_number.
This is used by RPS and RFS. Kernel can make use of hw provided hash
instead of calculating the hash.

Signed-off-by: Govindarajulu Varadarajan <govindarajulu90@gmail.com>
Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
---
 drivers/net/ethernet/cisco/enic/enic_main.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 1ab3f18..93898ba 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1034,6 +1034,14 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 
 		skb_put(skb, bytes_written);
 		skb->protocol = eth_type_trans(skb, netdev);
+		skb_record_rx_queue(skb, q_number);
+		if (netdev->features & NETIF_F_RXHASH) {
+			skb->rxhash = rss_hash;
+			if (rss_type & (NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX |
+					NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 |
+					NIC_CFG_RSS_HASH_TYPE_TCP_IPV4))
+				skb->l4_rxhash = true;
+		}
 
 		if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) {
 			skb->csum = htons(checksum);
@@ -2209,6 +2217,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	netif_set_real_num_tx_queues(netdev, enic->wq_count);
+	netif_set_real_num_rx_queues(netdev, enic->rq_count);
 
 	/* Setup notification timer, HW reset task, and wq locks
 	 */
@@ -2258,6 +2267,8 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ENIC_SETTING(enic, TSO))
 		netdev->hw_features |= NETIF_F_TSO |
 			NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+	if (ENIC_SETTING(enic, RSS))
+		netdev->hw_features |= NETIF_F_RXHASH;
 	if (ENIC_SETTING(enic, RXCSUM))
 		netdev->hw_features |= NETIF_F_RXCSUM;
 
-- 
1.8.4

^ permalink raw reply related

* [PATCH net-next 1/5] driver/net: enic: Add multi tx support for enic
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan
In-Reply-To: <1378273638-7780-1-git-send-email-govindarajulu90@gmail.com>

The following patch adds multi tx support for enic.

Signed-off-by: Nishank Trivedi <nistrive@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: Govindarajulu Varadarajan <govindarajulu90@gmail.com>
---
 drivers/net/ethernet/cisco/enic/enic.h      |  2 +-
 drivers/net/ethernet/cisco/enic/enic_main.c | 36 +++++++++++++++++++----------
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index be16731..34b637a 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -37,7 +37,7 @@
 
 #define ENIC_BARS_MAX		6
 
-#define ENIC_WQ_MAX		1
+#define ENIC_WQ_MAX		8
 #define ENIC_RQ_MAX		8
 #define ENIC_CQ_MAX		(ENIC_WQ_MAX + ENIC_RQ_MAX)
 #define ENIC_INTR_MAX		(ENIC_CQ_MAX + 2)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index bcf15b1..1ab3f18 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -128,10 +128,10 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
 		completed_index, enic_wq_free_buf,
 		opaque);
 
-	if (netif_queue_stopped(enic->netdev) &&
+	if (netif_tx_queue_stopped(netdev_get_tx_queue(enic->netdev, q_number)) &&
 	    vnic_wq_desc_avail(&enic->wq[q_number]) >=
 	    (MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS))
-		netif_wake_queue(enic->netdev);
+		netif_wake_subqueue(enic->netdev, q_number);
 
 	spin_unlock(&enic->wq_lock[q_number]);
 
@@ -292,10 +292,15 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data)
 static irqreturn_t enic_isr_msix_wq(int irq, void *data)
 {
 	struct enic *enic = data;
-	unsigned int cq = enic_cq_wq(enic, 0);
-	unsigned int intr = enic_msix_wq_intr(enic, 0);
+	unsigned int cq;
+	unsigned int intr;
 	unsigned int wq_work_to_do = -1; /* no limit */
 	unsigned int wq_work_done;
+	unsigned int wq_irq;
+
+	wq_irq = (u32)irq - enic->msix_entry[enic_msix_wq_intr(enic, 0)].vector;
+	cq = enic_cq_wq(enic, wq_irq);
+	intr = enic_msix_wq_intr(enic, wq_irq);
 
 	wq_work_done = vnic_cq_service(&enic->cq[cq],
 		wq_work_to_do, enic_wq_service, NULL);
@@ -511,14 +516,18 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
 	struct net_device *netdev)
 {
 	struct enic *enic = netdev_priv(netdev);
-	struct vnic_wq *wq = &enic->wq[0];
+	struct vnic_wq *wq;
 	unsigned long flags;
+	unsigned int txq_map;
 
 	if (skb->len <= 0) {
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
+	txq_map = skb_get_queue_mapping(skb) % enic->wq_count;
+	wq = &enic->wq[txq_map];
+
 	/* Non-TSO sends must fit within ENIC_NON_TSO_MAX_DESC descs,
 	 * which is very likely.  In the off chance it's going to take
 	 * more than * ENIC_NON_TSO_MAX_DESC, linearize the skb.
@@ -531,23 +540,23 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
 		return NETDEV_TX_OK;
 	}
 
-	spin_lock_irqsave(&enic->wq_lock[0], flags);
+	spin_lock_irqsave(&enic->wq_lock[txq_map], flags);
 
 	if (vnic_wq_desc_avail(wq) <
 	    skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) {
-		netif_stop_queue(netdev);
+		netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map));
 		/* This is a hard error, log it */
 		netdev_err(netdev, "BUG! Tx ring full when queue awake!\n");
-		spin_unlock_irqrestore(&enic->wq_lock[0], flags);
+		spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags);
 		return NETDEV_TX_BUSY;
 	}
 
 	enic_queue_wq_skb(enic, wq, skb);
 
 	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
-		netif_stop_queue(netdev);
+		netif_tx_stop_queue(netdev_get_tx_queue(netdev, txq_map));
 
-	spin_unlock_irqrestore(&enic->wq_lock[0], flags);
+	spin_unlock_irqrestore(&enic->wq_lock[txq_map], flags);
 
 	return NETDEV_TX_OK;
 }
@@ -1369,7 +1378,7 @@ static int enic_open(struct net_device *netdev)
 
 	enic_set_rx_mode(netdev);
 
-	netif_wake_queue(netdev);
+	netif_tx_wake_all_queues(netdev);
 
 	for (i = 0; i < enic->rq_count; i++)
 		napi_enable(&enic->napi[i]);
@@ -2032,7 +2041,8 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * instance data is initialized to zero.
 	 */
 
-	netdev = alloc_etherdev(sizeof(struct enic));
+	netdev = alloc_etherdev_mqs(sizeof(struct enic),
+				    ENIC_RQ_MAX, ENIC_WQ_MAX);
 	if (!netdev)
 		return -ENOMEM;
 
@@ -2198,6 +2208,8 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto err_out_dev_close;
 	}
 
+	netif_set_real_num_tx_queues(netdev, enic->wq_count);
+
 	/* Setup notification timer, HW reset task, and wq locks
 	 */
 
-- 
1.8.4

^ permalink raw reply related

* [PATCH net-next 0/5] driver/net: enic: enic driver updates
From: Govindarajulu Varadarajan @ 2013-09-04  5:47 UTC (permalink / raw)
  To: davem, netdev, linux-kernel
  Cc: benve, ssujith, nistrive, umalhi, Govindarajulu Varadarajan

This series includes support for multi-tx, rss_hash, RPS, RFS, DMA64, 
export symbols for cisco low latency driver and update the driver version and 
driver maintainers.

Govindarajulu Varadarajan (5):
  driver/net: enic: Add multi tx support for enic
  driver/net: enic: record q_number and rss_hash for skb
  driver/net: enic: Try DMA 64 first, then failover to DMA
  driver/net: enic: Exposing symbols for Cisco's low latency driver
  driver/net: enic: update enic maintainers and driver

 MAINTAINERS                                 |  3 +-
 drivers/net/ethernet/cisco/enic/enic.h      |  4 +--
 drivers/net/ethernet/cisco/enic/enic_main.c | 55 ++++++++++++++++++++---------
 drivers/net/ethernet/cisco/enic/vnic_dev.c  | 10 ++++++
 drivers/net/ethernet/cisco/enic/vnic_dev.h  |  1 +
 5 files changed, 54 insertions(+), 19 deletions(-)

-- 
1.8.4

^ permalink raw reply

* Re: [PATCH v2 net-next] pkt_sched: fq: Fair Queue packet scheduler
From: Jason Wang @ 2013-09-04  5:26 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: David Miller, netdev, Yuchung Cheng, Neal Cardwell,
	Michael S. Tsirkin
In-Reply-To: <1377816595.8277.54.camel@edumazet-glaptop>

On 08/30/2013 06:49 AM, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> - Uses perfect flow match (not stochastic hash like SFQ/FQ_codel)
> - Uses the new_flow/old_flow separation from FQ_codel
> - New flows get an initial credit allowing IW10 without added delay.
> - Special FIFO queue for high prio packets (no need for PRIO + FQ)
> - Uses a hash table of RB trees to locate the flows at enqueue() time
> - Smart on demand gc (at enqueue() time, RB tree lookup evicts old
>   unused flows)
> - Dynamic memory allocations.
> - Designed to allow millions of concurrent flows per Qdisc.
> - Small memory footprint : ~8K per Qdisc, and 104 bytes per flow.
> - Single high resolution timer for throttled flows (if any).
> - One RB tree to link throttled flows.
> - Ability to have a max rate per flow. We might add a socket option
>   to add per socket limitation.
>
> Attempts have been made to add TCP pacing in TCP stack, but this
> seems to add complex code to an already complex stack.
>
> TCP pacing is welcomed for flows having idle times, as the cwnd
> permits TCP stack to queue a possibly large number of packets.
>
[...]
>
> FQ gets a bunch of tunables as :
>
>   limit : max number of packets on whole Qdisc (default 10000)
>
>   flow_limit : max number of packets per flow (default 100)
>
>   quantum : the credit per RR round (default is 2 MTU)
>
>   initial_quantum : initial credit for new flows (default is 10 MTU)
>
>   maxrate : max per flow rate (default : unlimited)
>
>   buckets : number of RB trees (default : 1024) in hash table.
>                (consumes 8 bytes per bucket)
>
>   [no]pacing : disable/enable pacing (default is enable)
>
> All of them can be changed on a live qdisc.
>
> $ tc qd add dev eth0 root fq help
> Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]
>               [ quantum BYTES ] [ initial_quantum BYTES ]
>               [ maxrate RATE  ] [ buckets NUMBER ]
>               [ [no]pacing ]
>
> $ tc -s -d qd
> qdisc fq 8002: dev eth0 root refcnt 32 limit 10000p flow_limit 100p buckets 256 quantum 3028 initial_quantum 15140
>  Sent 216532416 bytes 148395 pkt (dropped 0, overlimits 0 requeues 14)
>  backlog 0b 0p requeues 14
>   511 flows, 511 inactive, 0 throttled
>   110 gc, 0 highprio, 0 retrans, 1143 throttled, 0 flows_plimit
>
>
> [1] Except if initial srtt is overestimated, as if using
> cached srtt in tcp metrics. We'll provide a fix for this issue.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Yuchung Cheng <ycheng@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> ---
> v2: added initial_quantum support

I see both degradation and jitter when using fq with virtio-net. Guest
to guest performance drops from 8Gb/s to 3Gb/s-7Gb/s. Guest to local
host drops from 8Gb/s to 4Gb/s-6Gb/s. Guest to external host with ixgbe
drops from 9Gb/s to 7Gb/s

I didn't meet the issue when using sfq or disabling pacing.

So it looks like it was caused by the inaccuracy and jitter of the
pacing estimation in a virt guest?

^ permalink raw reply

* Re: [PATCH net-next v2] tcp: Change return value of tcp_rcv_established()
From: David Miller @ 2013-09-04  4:55 UTC (permalink / raw)
  To: subramanian.vijay; +Cc: netdev
In-Reply-To: <1378236202-27486-1-git-send-email-subramanian.vijay@gmail.com>

From: Vijay Subramanian <subramanian.vijay@gmail.com>
Date: Tue,  3 Sep 2013 12:23:22 -0700

> tcp_rcv_established() returns only one value namely 0. We change the return
> value to void (as suggested by David Miller).
> 
> After commit 0c24604b (tcp: implement RFC 5961 4.2), we no longer send RSTs in
> response to SYNs. We can remove the check and processing on the return value of
> tcp_rcv_established().
> 
> We also fix jtcp_rcv_established() in tcp_probe.c to match that of
> tcp_rcv_established().
> 
> 
> Signed-off-by: Vijay Subramanian <subramanian.vijay@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] net: tcp_probe: adapt tbuf size for recent changes
From: David Miller @ 2013-09-04  4:55 UTC (permalink / raw)
  To: dborkman; +Cc: netdev
In-Reply-To: <1378225442-6676-1-git-send-email-dborkman@redhat.com>

From: Daniel Borkmann <dborkman@redhat.com>
Date: Tue,  3 Sep 2013 18:24:02 +0200

> With recent changes in tcp_probe module (e.g. f925d0a62d ("net: tcp_probe:
> add IPv6 support")) we also need to take into account that tbuf needs to
> be updated as format string will be further expanded. tbuf sits on the stack
> in tcpprobe_read() function that is invoked when user space reads procfs
> file /proc/net/tcpprobe, hence not fast path as in jtcp_rcv_established().
> Having a size similarly as in sctp_probe module of 256 bytes is fully
> sufficient for that, we need theoretical maximum of 252 bytes otherwise we
> could get truncated.
> 
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 1/1] qlcnic: Fix sparse warning.
From: David Miller @ 2013-09-04  4:54 UTC (permalink / raw)
  To: sucheta.chakraborty; +Cc: netdev, Dept-HSGLinuxNICDev
In-Reply-To: <1378199257-9514-1-git-send-email-sucheta.chakraborty@qlogic.com>

From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Date: Tue, 3 Sep 2013 05:07:37 -0400

> This patch fixes warning "warning: symbol 'qlcnic_set_dcb_ops' was
> not declared. Should it be static?"
> 
> Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>

Applied.

^ permalink raw reply

* Re: [patch] qlcnic: remove a stray semicolon
From: David Miller @ 2013-09-04  4:54 UTC (permalink / raw)
  To: dan.carpenter
  Cc: himanshu.madhani, rajesh.borundia, shahed.shaikh,
	jitendra.kalsaria, sony.chacko, sucheta.chakraborty, linux-driver,
	netdev, kernel-janitors
In-Reply-To: <20130903091347.GA4630@elgon.mountain>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 3 Sep 2013 12:13:47 +0300

> Just remove a small semicolon.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply

* Re: [patch] x25: add a sanity check parsing X.25 facilities
From: David Miller @ 2013-09-04  4:54 UTC (permalink / raw)
  To: dan.carpenter; +Cc: andrew.hendry, linux-x25, netdev, kernel-janitors
In-Reply-To: <20130903090340.GB4351@elgon.mountain>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 3 Sep 2013 12:03:40 +0300

> This was found with a manual audit and I don't have a reproducer.  We
> limit ->calling_len and ->called_len when we get them from
> copy_from_user() in x25_ioctl() so when they come from skb->data then
> we should cap them there as well.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply

* Re: [patch] caif: add a sanity check to the tty name
From: David Miller @ 2013-09-04  4:54 UTC (permalink / raw)
  To: dan.carpenter; +Cc: dmitry.tarnyagin, netdev, kernel-janitors
In-Reply-To: <20130903090232.GA4351@elgon.mountain>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Tue, 3 Sep 2013 12:02:32 +0300

> "tty->name" and "name" are a 64 character buffers.  My static checker
> complains because we add the "cf" on the front so it look like we are
> copying a 66 character string into a 64 character buffer.
> 
> Also if the name is larger than IFNAMSIZ (16) it triggers a BUG_ON()
> inside the call to alloc_netdev().
> 
> This is all under CAP_SYS_ADMIN so it's not a security fix, it just adds
> a little robustness.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply

* Re: [PATCH] ibmveth: Fix little endian issues
From: David Miller @ 2013-09-04  4:53 UTC (permalink / raw)
  To: anton; +Cc: santil, netdev
In-Reply-To: <20130903095532.507dcb44@kryten>

From: Anton Blanchard <anton@samba.org>
Date: Tue, 3 Sep 2013 09:55:32 +1000

> 
> The hypervisor is big endian, so little endian kernel builds need
> to byteswap.
> 
> Signed-off-by: Anton Blanchard <anton@samba.org>

Applied.

^ permalink raw reply

* Re: [PATCH V2] net: netx-eth: remove unnecessary casting
From: David Miller @ 2013-09-04  4:53 UTC (permalink / raw)
  To: jg1.han; +Cc: netdev, sergei.shtylyov
In-Reply-To: <001101cea837$b49bf370$1dd3da50$%han@samsung.com>

From: Jingoo Han <jg1.han@samsung.com>
Date: Tue, 03 Sep 2013 08:54:04 +0900

> Casting from 'void *' is unnecessary, because casting from 'void *'
> to any pointer type is automatic.
> 
> Reported-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next] net: correctly interlink lower/upper devices
From: David Miller @ 2013-09-04  4:53 UTC (permalink / raw)
  To: vfalico; +Cc: netdev, edumazet, jiri, alexander.h.duyck, amwang
In-Reply-To: <1378132011-2910-1-git-send-email-vfalico@redhat.com>

From: Veaceslav Falico <vfalico@redhat.com>
Date: Mon,  2 Sep 2013 16:26:51 +0200

> Currently we're linking upper devices to lower ones, which results in
> upside-down relationship: upper devices seeing lower devices via its upper
> lists.
> 
> Fix this by correctly linking lower devices to the upper ones.
> 
> Signed-off-by: Veaceslav Falico <vfalico@redhat.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 0/5] cnic: Remove duplicate bnx2x definitions
From: David Miller @ 2013-09-04  4:53 UTC (permalink / raw)
  To: mchan; +Cc: netdev
In-Reply-To: <1378147352-9076-1-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Mon, 2 Sep 2013 11:42:27 -0700

> Adapt the code to use existing macros and struct fields in bnx2x.h to
> avoid duplication.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next 0/5] tunnels: harmonize skb scrubbing during encapsulation/decapsulation
From: David Miller @ 2013-09-04  4:52 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: pshelar, netdev, jesse, dev
In-Reply-To: <1378128898-15136-1-git-send-email-nicolas.dichtel@6wind.com>

From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Mon,  2 Sep 2013 15:34:53 +0200

> We talk recently about harmonizing tunnels so they behave consistently wrt. SKB
> orphaning, cleaning netfilter state, etc.
> The goal of this serie is to achieve this.
> 
> Note that I test only ipip, sit and ip6_tunnels modules.
> 
> v2: add patch 2/5
>     rebase on head
>     remove 'RFC' prefix

Series applied.

^ permalink raw reply


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