rpms/kernel-xen-2.6/F-7 linux-2.6-xen-add-packet_auxdata-cmsg-1.patch, NONE, 1.1 linux-2.6-xen-add-packet_auxdata-cmsg-2.patch, NONE, 1.1 linux-2.6-xen-af_packet-no-skb_checksum_setup.patch, NONE, 1.1 kernel-xen.spec, 1.41, 1.42

Eduardo Habkost (ehabkost) fedora-extras-commits at redhat.com
Fri Aug 10 12:32:17 UTC 2007


Author: ehabkost

Update of /cvs/pkgs/rpms/kernel-xen-2.6/F-7
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv13685

Modified Files:
	kernel-xen.spec 
Added Files:
	linux-2.6-xen-add-packet_auxdata-cmsg-1.patch 
	linux-2.6-xen-add-packet_auxdata-cmsg-2.patch 
	linux-2.6-xen-af_packet-no-skb_checksum_setup.patch 
Log Message:
Add af_packet.c checksum/auxdata patches from Herbert


linux-2.6-xen-add-packet_auxdata-cmsg-1.patch:

--- NEW FILE linux-2.6-xen-add-packet_auxdata-cmsg-1.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: [RHEL5 PATCH] [PACKET]: Add PACKET_AUXDATA cmsg
Date: Wed, 10 Jan 2007 20:17:36 +1100
Message-Id: <20070110091736.GA28579 at gondor.apana.org.au>
Changelog: xen: Add PACKET_AUXDATA cmsg


Hi:

RHEL5 BZ 219681

This patch forms part of the solution to #219681 where the DHCP server
can't serve any requests from clients running (in different domains)
on the same Xen host.

I've sent a similar patch (without the Xen-specific code) upstream.

This obsoletes the previous patch that computed the checksums in
kernel-space.

[PACKET]: Add PACKET_AUXDATA cmsg

HCP servers/clients using AF_PACKET) to be able to serve another
client on the same Xen host.

The problem is that packets between different domains on the same
Xen host only have partial checksums.  Unfortunately this piece of
information is not passed along in AF_PACKET unless you're using
the mmap interface.  Since dhcpd doesn't support packet-mmap, UDP
packets from the same host come out with apparently bogus checksums.

This patch adds a mechanism for AF_PACKET recvmsg(2) to return the
status along with the packet.  It does so by adding a new cmsg that
contains this information along with some other relevant data such
as the original packet length.

I didn't include the time stamp information since there is already
a cmsg for that.

This patch also changes the mmap code to set the CSUMNOTREADY flag
on all packets instead of just outoing packets on cooked sockets.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Index: linux-2.6.20.i386/include/linux/if_packet.h
===================================================================
--- linux-2.6.20.i386.orig/include/linux/if_packet.h
+++ linux-2.6.20.i386/include/linux/if_packet.h
@@ -41,6 +41,7 @@ struct sockaddr_ll
 #define PACKET_RX_RING			5
 #define PACKET_STATISTICS		6
 #define PACKET_COPY_THRESH		7
+#define PACKET_AUXDATA			8
 
 struct tpacket_stats
 {
@@ -48,6 +49,15 @@ struct tpacket_stats
 	unsigned int	tp_drops;
 };
 
+struct tpacket_auxdata
+{
+	__u32		tp_status;
+	__u32		tp_len;
+	__u32		tp_snaplen;
+	__u16		tp_mac;
+	__u16		tp_net;
+};
+
 struct tpacket_hdr
 {
 	unsigned long	tp_status;
Index: linux-2.6.20.i386/net/packet/af_packet.c
===================================================================
--- linux-2.6.20.i386.orig/net/packet/af_packet.c
+++ linux-2.6.20.i386/net/packet/af_packet.c
@@ -200,7 +200,8 @@ struct packet_sock {
 #endif
 	struct packet_type	prot_hook;
 	spinlock_t		bind_lock;
-	char			running;	/* prot_hook is attached*/
+	unsigned int		running:1,	/* prot_hook is attached*/
+				auxdata:1;
 	int			ifindex;	/* bound device		*/
 	__be16			num;
 #ifdef CONFIG_PACKET_MULTICAST
@@ -214,6 +215,10 @@ struct packet_sock {
 #endif
 };
 
+#define PACKET_SKB_CB(__skb)	((struct tpacket_auxdata *)((__skb)->cb))
+
+extern int skb_checksum_setup(struct sk_buff *skb);
+
 #ifdef CONFIG_PACKET_MMAP
 
 static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
@@ -462,6 +467,7 @@ static int packet_rcv(struct sk_buff *sk
 	u8 * skb_head = skb->data;
 	int skb_len = skb->len;
 	unsigned int snaplen, res;
+	struct tpacket_auxdata *aux;
 
 	if (skb->pkt_type == PACKET_LOOPBACK)
 		goto drop;
@@ -523,6 +529,18 @@ static int packet_rcv(struct sk_buff *sk
 	if (dev->hard_header_parse)
 		sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
 
+	if (skb_checksum_setup(skb))
+		goto drop_n_acct;
+
+	aux = PACKET_SKB_CB(skb);
+	aux->tp_status = TP_STATUS_USER;
+	if (skb->ip_summed == CHECKSUM_HW)
+		aux->tp_status |= TP_STATUS_CSUMNOTREADY;
+	aux->tp_len = skb->len;
+	aux->tp_snaplen = snaplen;
+	aux->tp_mac = 0;
+	aux->tp_net = skb->nh.raw - skb->data;
+
 	if (pskb_trim(skb, snaplen))
 		goto drop_n_acct;
 
@@ -582,8 +600,6 @@ static int tpacket_rcv(struct sk_buff *s
 		else if (skb->pkt_type == PACKET_OUTGOING) {
 			/* Special case: outgoing packets have ll header at head */
 			skb_pull(skb, skb->nh.raw - skb->data);
-			if (skb->ip_summed == CHECKSUM_PARTIAL)
-				status |= TP_STATUS_CSUMNOTREADY;
 		}
 	}
 
@@ -595,6 +611,11 @@ static int tpacket_rcv(struct sk_buff *s
 	if (snaplen > res)
 		snaplen = res;
 
+	if (skb_checksum_setup(skb))
+		goto drop;
+	if (skb->ip_summed == CHECKSUM_HW)
+		status |= TP_STATUS_CSUMNOTREADY;
+
 	if (sk->sk_type == SOCK_DGRAM) {
 		macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
 	} else {
@@ -1119,6 +1140,11 @@ static int packet_recvmsg(struct kiocb *
 	if (msg->msg_name)
 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
 
+	if (pkt_sk(sk)->auxdata) {
+		struct tpacket_auxdata *aux = PACKET_SKB_CB(skb);
+		put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(*aux), aux);
+	}
+
 	/*
 	 *	Free or return the buffer as appropriate. Again this
 	 *	hides all the races and re-entrancy issues from us.
@@ -1317,6 +1343,7 @@ static int
 packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
+	struct packet_sock *po = pkt_sk(sk);
 	int ret;
 
 	if (level != SOL_PACKET)
@@ -1369,6 +1396,18 @@ packet_setsockopt(struct socket *sock, i
 		return 0;
 	}
 #endif
+	case PACKET_AUXDATA:
+	{
+		int val;
+
+		if (optlen < sizeof(val))
+			return -EINVAL;
+		if (copy_from_user(&val, optval, sizeof(val)))
+			return -EFAULT;
+
+		po->auxdata = !!val;
+		return 0;
+	}
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -1378,8 +1417,11 @@ static int packet_getsockopt(struct sock
 			     char __user *optval, int __user *optlen)
 {
 	int len;
+	int val;
 	struct sock *sk = sock->sk;
 	struct packet_sock *po = pkt_sk(sk);
+	void *data;
+	struct tpacket_stats st;
 
 	if (level != SOL_PACKET)
 		return -ENOPROTOOPT;
@@ -1392,9 +1434,6 @@ static int packet_getsockopt(struct sock
 		
 	switch(optname)	{
 	case PACKET_STATISTICS:
-	{
-		struct tpacket_stats st;
-
 		if (len > sizeof(struct tpacket_stats))
 			len = sizeof(struct tpacket_stats);
 		spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1403,16 +1442,23 @@ static int packet_getsockopt(struct sock
 		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		st.tp_packets += st.tp_drops;
 
-		if (copy_to_user(optval, &st, len))
-			return -EFAULT;
+		data = &st;
+		break;
+	case PACKET_AUXDATA:
+		if (len > sizeof(int))
+			len = sizeof(int);
+		val = po->auxdata;
+
+		data = &val;
 		break;
-	}
 	default:
 		return -ENOPROTOOPT;
 	}
 
 	if (put_user(len, optlen))
 		return -EFAULT;
+	if (copy_to_user(optval, data, len))
+		return -EFAULT;
 	return 0;
 }
 

linux-2.6-xen-add-packet_auxdata-cmsg-2.patch:

--- NEW FILE linux-2.6-xen-add-packet_auxdata-cmsg-2.patch ---
From: Herbert Xu <herbert.xu at redhat.com>
Subject: Re: Help on BZ 223505 tcpdump causes ppc64 to enter xmon
Date: Wed, 24 Jan 2007 10:23:55 +1100
Message-Id: <20070123232355.GA4724 at gondor.apana.org.au>

On Wed, Jan 24, 2007 at 09:03:24AM +1100, Herbert Xu wrote:
> 
> OK, I've found the problem.  The skb->cb buffer is already being
> used for sockaddr_ll which the aux data is overwriting.  Let me
> fix this up by getting them to share the buffer.

The obvious fix of putting them together in the cb doesn't quite work
because sockaddr_ll's last member can be as large as MAX_ADDR_LEN (32).
In fact this means that older kernels with skb->cb less than 44 bytes
may in fact be vulnerable if net devices with an address length of 32
bytes exist.

[PACKET]: Fix skb->cb clobbering between aux and sockaddr

Both aux data and sockaddr tries to use the same buffer which
obviously doesn't work.  We just happen to have 4 bytes free in
the skb->cb if you take away the maximum length of sockaddr_ll.
That's just enough to store the one piece of info from aux data
that we can't generate at recvmsg(2) time.

This is what the following patch does.

Signed-off-by: Herbert Xu <herbert at gondor.apana.org.au>

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
Index: linux-2.6.20.i386/net/packet/af_packet.c
===================================================================
--- linux-2.6.20.i386.orig/net/packet/af_packet.c
+++ linux-2.6.20.i386/net/packet/af_packet.c
@@ -60,6 +60,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_packet.h>
 #include <linux/wireless.h>
+#include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <net/ip.h>
 #include <net/protocol.h>
@@ -215,7 +216,15 @@ struct packet_sock {
 #endif
 };
 
-#define PACKET_SKB_CB(__skb)	((struct tpacket_auxdata *)((__skb)->cb))
+struct packet_skb_cb {
+	unsigned int origlen;
+	union {
+		struct sockaddr_pkt pkt;
+		struct sockaddr_ll ll;
+	} sa;
+};
+
+#define PACKET_SKB_CB(__skb)	((struct packet_skb_cb *)((__skb)->cb))
 
 extern int skb_checksum_setup(struct sk_buff *skb);
 
@@ -298,7 +307,7 @@ static int packet_rcv_spkt(struct sk_buf
 	/* drop conntrack reference */
 	nf_reset(skb);
 
-	spkt = (struct sockaddr_pkt*)skb->cb;
+	spkt = &PACKET_SKB_CB(skb)->sa.pkt;
 
 	skb_push(skb, skb->data-skb->mac.raw);
 
@@ -467,7 +476,6 @@ static int packet_rcv(struct sk_buff *sk
 	u8 * skb_head = skb->data;
 	int skb_len = skb->len;
 	unsigned int snaplen, res;
-	struct tpacket_auxdata *aux;
 
 	if (skb->pkt_type == PACKET_LOOPBACK)
 		goto drop;
@@ -518,7 +526,10 @@ static int packet_rcv(struct sk_buff *sk
 		skb = nskb;
 	}
 
-	sll = (struct sockaddr_ll*)skb->cb;
+	BUILD_BUG_ON(sizeof(*PACKET_SKB_CB(skb)) + MAX_ADDR_LEN - 8 >
+		     sizeof(skb->cb));
+
+	sll = &PACKET_SKB_CB(skb)->sa.ll;
 	sll->sll_family = AF_PACKET;
 	sll->sll_hatype = dev->type;
 	sll->sll_protocol = skb->protocol;
@@ -532,14 +543,7 @@ static int packet_rcv(struct sk_buff *sk
 	if (skb_checksum_setup(skb))
 		goto drop_n_acct;
 
-	aux = PACKET_SKB_CB(skb);
-	aux->tp_status = TP_STATUS_USER;
-	if (skb->ip_summed == CHECKSUM_HW)
-		aux->tp_status |= TP_STATUS_CSUMNOTREADY;
-	aux->tp_len = skb->len;
-	aux->tp_snaplen = snaplen;
-	aux->tp_mac = 0;
-	aux->tp_net = skb->nh.raw - skb->data;
+	PACKET_SKB_CB(skb)->origlen = skb->len;
 
 	if (pskb_trim(skb, snaplen))
 		goto drop_n_acct;
@@ -1113,7 +1117,7 @@ static int packet_recvmsg(struct kiocb *
 	 *	it in now.
 	 */
 
-	sll = (struct sockaddr_ll*)skb->cb;
+	sll = &PACKET_SKB_CB(skb)->sa.ll;
 	if (sock->type == SOCK_PACKET)
 		msg->msg_namelen = sizeof(struct sockaddr_pkt);
 	else
@@ -1138,11 +1142,21 @@ static int packet_recvmsg(struct kiocb *
 	sock_recv_timestamp(msg, sk, skb);
 
 	if (msg->msg_name)
-		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+		memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
+		       msg->msg_namelen);
 
 	if (pkt_sk(sk)->auxdata) {
-		struct tpacket_auxdata *aux = PACKET_SKB_CB(skb);
-		put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(*aux), aux);
+		struct tpacket_auxdata aux;
+
+		aux.tp_status = TP_STATUS_USER;
+		if (skb->ip_summed == CHECKSUM_HW)
+			aux.tp_status |= TP_STATUS_CSUMNOTREADY;
+		aux.tp_len = PACKET_SKB_CB(skb)->origlen;
+		aux.tp_snaplen = skb->len;
+		aux.tp_mac = 0;
+		aux.tp_net = skb->nh.raw - skb->data;
+
+		put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
 	}
 
 	/*

linux-2.6-xen-af_packet-no-skb_checksum_setup.patch:

--- NEW FILE linux-2.6-xen-af_packet-no-skb_checksum_setup.patch ---
Date: Thu, 9 Aug 2007 21:02:40 +0800
From: Herbert Xu <herbert.xu at redhat.com>
To: Eduardo Pereira Habkost <ehabkost at redhat.com>
Subject: Re: Checksum patches on 2.6.20-xen-3.1.0

Hi Eduardo:

I've just tracked 248821 down to a pair of calls to
skb_checksum_setup in net/packet/af_packet.c that are 
no longer necessary.  So please add this patch to
linux-2.6-kill_skbuff_hack.patch for rawhide/FC7.

Thanks,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
Index: linux/net/packet/af_packet.c
===================================================================
--- linux/net/packet/af_packet.c.orig
+++ linux/net/packet/af_packet.c
@@ -226,8 +226,6 @@ struct packet_skb_cb {
 
 #define PACKET_SKB_CB(__skb)	((struct packet_skb_cb *)((__skb)->cb))
 
-extern int skb_checksum_setup(struct sk_buff *skb);
-
 #ifdef CONFIG_PACKET_MMAP
 
 static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
@@ -540,9 +538,6 @@ static int packet_rcv(struct sk_buff *sk
 	if (dev->hard_header_parse)
 		sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
 
-	if (skb_checksum_setup(skb))
-		goto drop_n_acct;
-
 	PACKET_SKB_CB(skb)->origlen = skb->len;
 
 	if (pskb_trim(skb, snaplen))
@@ -615,8 +610,6 @@ static int tpacket_rcv(struct sk_buff *s
 	if (snaplen > res)
 		snaplen = res;
 
-	if (skb_checksum_setup(skb))
-		goto drop;
 	if (skb->ip_summed == CHECKSUM_HW)
 		status |= TP_STATUS_CSUMNOTREADY;
 


Index: kernel-xen.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel-xen-2.6/F-7/kernel-xen.spec,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- kernel-xen.spec	9 Aug 2007 21:20:35 -0000	1.41
+++ kernel-xen.spec	10 Aug 2007 12:31:44 -0000	1.42
@@ -404,6 +404,10 @@
 Patch958: linux-2.6-xen-iscsi-x86_64-no_iommu_init.patch
 Patch960: linux-2.6-xen-blkfront-wait-add.patch
 Patch961: linux-2.6-xen-backwards-time.patch
+Patch962: linux-2.6-xen-add-packet_auxdata-cmsg-1.patch
+Patch963: linux-2.6-xen-add-packet_auxdata-cmsg-2.patch
+Patch964: linux-2.6-xen-af_packet-no-skb_checksum_setup.patch
+
 
 #
 # Patches 1000 to 5000 are reserved for bugfixes to drivers and filesystems
@@ -930,6 +934,9 @@
 %patch958 -p1
 %patch960 -p1
 %patch961 -p1
+%patch962 -p1
+%patch963 -p1
+%patch964 -p1
 %endif
 
 #
@@ -2046,6 +2053,10 @@
 #  - tux.
 
 %changelog
+* Fri Aug 10 2007 Eduardo Habkost <ehabkost at redhat.com>
+- Add af_packet.c checksum patches from Herbert Xu, to avoid problems with
+  DHCP clients running on the same Xen host
+
 * Thu Aug 09 2007 Eduardo Habkost <ehabkost at redhat.com>
 - Add linux-2.6-xen-backwards-time.patch from linux-2.6.18-xen.hg
   changeset 87bb8705768a. This should fix bug #236307




More information about the scm-commits mailing list