public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: jamal <hadi@cyberus.ca>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>, netdev@vger.kernel.org
Subject: Re: [IPSEC]: searching  SAD without assumming L3 details
Date: Wed, 06 Sep 2006 08:14:54 -0400	[thread overview]
Message-ID: <1157544895.5039.33.camel@jzny2> (raw)
In-Reply-To: <20060906112644.GA22930@gondor.apana.org.au>

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

On Wed, 2006-06-09 at 21:26 +1000, Herbert Xu wrote:
> On Wed, Sep 06, 2006 at 07:20:39AM -0400, jamal wrote:
> >
> > > Any reason why xfrm_state_find can't be used? 
> > 
> > xfrm_state_find is overkill (if you compare the two functionalities). 
> 
> Could you show me how you plan to use this in pktgen? 

Older patch attached - has a few bugs; just ignore them.

> Perhaps we can
> move it to the slow path where it wouldn't matter whether it's an
> overkill or not.  There should be no reason to be looking up an SA
> in the pktgen fast path.

It is needed if you want replay protection - unless you can come with
some clever way to handle it without violating the integrity. 
For non replay protection, thats easy: We just do one lookup and reclone
the packet within pktgen - maybe thats what you meant by "slow path"?

cheers,
jamal

[-- Attachment #2: pig3 --]
[-- Type: text/plain, Size: 9865 bytes --]

    Add IPSEC support to pktgen. Currently only IPV4 and ESP/Transport
    mode. IPV6 next. And Tunnel mode to follow after some discussions with
    Herbert and Dave.

---
commit 0721d8f9d3e1a9a8f5f038365ae12ec605a2d5d6
tree 3069707bec44c992c0bfdbe871c7e3bd68d37882
parent 1a4c28d2bd2fcf82b84bffdb7be47aa9224483d0
author Jamal Hadi Salim <hadi@znyx.com> Tue, 22 Aug 2006 21:43:37 -0400
committer Jamal Hadi Salim <hadi@jzny2.(none)> Tue, 22 Aug 2006 21:43:37 -0400

 net/core/pktgen.c |  169 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 156 insertions(+), 13 deletions(-)

diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 67ed14d..5fc725d 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -148,6 +148,7 @@ #include <linux/etherdevice.h>
 #include <net/checksum.h>
 #include <net/ipv6.h>
 #include <net/addrconf.h>
+#include <net/xfrm.h>
 #include <asm/byteorder.h>
 #include <linux/rcupdate.h>
 #include <asm/bitops.h>
@@ -178,6 +179,8 @@ #define F_MACDST_RND  (1<<5)	/* MAC-Dst 
 #define F_TXSIZE_RND  (1<<6)	/* Transmit size is random */
 #define F_IPV6        (1<<7)	/* Interface in IPV6 Mode */
 #define F_MPLS_RND    (1<<8)	/* Random MPLS labels */
+#define F_FLOW_RND    (1<<9)	/* Random flows */
+#define F_IPSEC_ON    (1<<10)	/* Run ipsec when possible */
 
 /* Thread control flag bits */
 #define T_TERMINATE   (1<<0)
@@ -200,6 +203,7 @@ #define MAX_CFLOWS  65536
 
 struct flow_state {
 	__u32 cur_daddr;
+	struct xfrm_state *x;
 	int count;
 };
 
@@ -226,6 +230,7 @@ struct pktgen_dev {
 
 	int min_pkt_size;	/* = ETH_ZLEN; */
 	int max_pkt_size;	/* = ETH_ZLEN; */
+	int pkt_overhead;	/* overhead in case of MPLS or IPSEC */
 	int nfrags;
 	__u32 delay_us;		/* Default delay */
 	__u32 delay_ns;
@@ -324,6 +329,8 @@ struct pktgen_dev {
 					 */
 	struct flow_state *flows;
 	unsigned cflows;	/* Concurrent flows (config) */
+	unsigned nextfl;	/* next flow when not random */
+	unsigned curfl;		/* current running flow */
 	unsigned lflow;		/* Flow length  (config) */
 	unsigned nflows;	/* accumulated flows (stats) */
 };
@@ -667,6 +674,14 @@ static int pktgen_if_show(struct seq_fil
 	if (pkt_dev->flags & F_MPLS_RND)
 		seq_printf(seq,  "MPLS_RND  ");
 
+	if (pkt_dev->flags & F_FLOW_RND)
+		seq_printf(seq,  "FLOW_RND  ");
+	else
+		seq_printf(seq,  "FLOW_SQN  "); /*in sequence */
+
+	if (pkt_dev->flags & F_IPSEC_ON)
+		seq_printf(seq,  "IPSEC_ON  ");
+
 	if (pkt_dev->flags & F_MACSRC_RND)
 		seq_printf(seq, "MACSRC_RND  ");
 
@@ -1140,6 +1155,12 @@ static ssize_t pktgen_if_write(struct fi
 		else if (strcmp(f, "!MPLS_RND") == 0)
 			pkt_dev->flags &= ~F_MPLS_RND;
 
+		else if (strcmp(f, "IPSEC_ON") == 0)
+			pkt_dev->flags |= F_IPSEC_ON;
+
+		else if (strcmp(f, "!IPSEC_ON") == 0)
+			pkt_dev->flags &= ~F_IPSEC_ON;
+
 		else {
 			sprintf(pg_result,
 				"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
@@ -1447,6 +1468,10 @@ static ssize_t pktgen_if_write(struct fi
 					  n == pkt_dev->nr_labels-1 ? "" : ",");
 		return count;
 	}
+	if (!strcmp(name, "ipsec")) {
+		/*XXX: Add the "OK: ipsec on" thing */
+		pkt_dev->flags |= F_IPSEC_ON;
+	}
 
 	sprintf(pkt_dev->result, "No such parameter \"%s\"", name);
 	return -EINVAL;
@@ -1879,11 +1904,26 @@ static void mod_cur_headers(struct pktge
 	__u32 imx;
 	int flow = 0;
 
+	pkt_dev->pkt_overhead = 0;
 	if (pkt_dev->cflows) {
-		flow = pktgen_random() % pkt_dev->cflows;
+		if (pkt_dev->flags & F_FLOW_RND) {
+			flow = pktgen_random() % pkt_dev->cflows;
+			if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+				pkt_dev->flows[flow].count = 0;
+		} else {
+			flow = pkt_dev->nextfl;
+			if (pkt_dev->flows[flow].count > pkt_dev->lflow) {
+				/* reset time */
+				pkt_dev->nextfl+=1;
+				if (pkt_dev->nextfl > pkt_dev->cflows)
+					 pkt_dev->nextfl = 0; /*reset */
+
+				flow = pkt_dev->nextfl;
+			}
 
-		if (pkt_dev->flows[flow].count > pkt_dev->lflow)
-			pkt_dev->flows[flow].count = 0;
+		}
+		pkt_dev->curfl = flow;
+		pkt_dev->nextfl+=1;
 	}
 
 	/*  Deal with source MAC */
@@ -1947,6 +1987,9 @@ static void mod_cur_headers(struct pktge
 				pkt_dev->labels[i] = MPLS_STACK_BOTTOM |
 						     (pktgen_random() &
 						      htonl(0x000fffff));
+
+		pkt_dev->pkt_overhead+=pkt_dev->nr_labels*sizeof(u32);
+
 	}
 
 	if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) {
@@ -2068,9 +2111,62 @@ static void mod_cur_headers(struct pktge
 		pkt_dev->cur_pkt_size = t;
 	}
 
+	if (pkt_dev->cflows && pkt_dev->flags & F_IPSEC_ON) {
+		struct xfrm_state *x = pkt_dev->flows[flow].x;
+	       	if (!x) {
+			/*slow path: we dont already have xfrm_state*/
+			x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr, (xfrm_address_t *)&pkt_dev->cur_saddr, AF_INET,XFRM_MODE_TRANSPORT, IPPROTO_ESP);
+			if (x) {
+				pkt_dev->flows[flow].x = x;
+				pkt_dev->pkt_overhead+=x->props.header_len;
+			}
+
+		}
+	}
+
+	/* XXX: Should this be moved into if stmt above? 
+	 * Talk to Monsieur Robert
+	*/
 	pkt_dev->flows[flow].count++;
 }
 
+/* In case of errors we are gonna bail out on the packet ..
+ * Also: We only support transport mode at the moment..
+ * Talk to Herbert/Dave about making the tunnel mode pieces
+ * independent of dst ..
+ **/
+static int pktgen_handle_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
+{
+	struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+	int err = 0;
+
+	if (!x)
+		return 0;
+	/* XXX: we dont support tunnel mode for now until
+	 * we resolve the dst issue */
+	if (x->props.mode) 
+		return 0;
+	/* error injection 
+	return -1;
+	*/ 
+	spin_lock(&x->lock);
+
+	err = x->mode->output(x, skb);
+	if (err)
+		goto error;
+	err = x->type->output(x, skb);
+	if (err)
+		goto error;
+
+	x->curlft.bytes +=skb->len;
+	x->curlft.packets++;
+	spin_unlock(&x->lock);
+
+error:
+	spin_unlock(&x->lock);
+	return err;
+}
+
 static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
 {
 	unsigned i;
@@ -2092,9 +2188,7 @@ static struct sk_buff *fill_packet_ipv4(
 	struct pktgen_hdr *pgh = NULL;
 	__be16 protocol = __constant_htons(ETH_P_IP);
 	__be32 *mpls;
-
-	if (pkt_dev->nr_labels)
-		protocol = __constant_htons(ETH_P_MPLS_UC);
+	int nhead;
 
 	/* Update any of the values, used when we're incrementing various
 	 * fields.
@@ -2102,8 +2196,12 @@ static struct sk_buff *fill_packet_ipv4(
 	mod_cur_headers(pkt_dev);
 
 	datalen = (odev->hard_header_len + 16) & ~0xf;
+
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
-			pkt_dev->nr_labels*sizeof(u32), GFP_ATOMIC);
+			pkt_dev->pkt_overhead, GFP_ATOMIC);
+	/*XXX: We need to check for cases where the MTU maybe
+	 * exceeded
+	*/
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
 		return NULL;
@@ -2113,10 +2211,15 @@ static struct sk_buff *fill_packet_ipv4(
 
 	/*  Reserve for ethernet and IP header  */
 	eth = (__u8 *) skb_push(skb, 14);
-	mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
-	if (pkt_dev->nr_labels)
+
+	if (pkt_dev->nr_labels) {
+		protocol = __constant_htons(ETH_P_MPLS_UC);
+		mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32));
 		mpls_push(mpls, pkt_dev);
+	}
+
 	iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
+	skb->nh.iph = iph;
 	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
 	memcpy(eth, pkt_dev->hh, 12);
@@ -2124,7 +2227,7 @@ static struct sk_buff *fill_packet_ipv4(
 
 	/* Eth + IPh + UDPh + mpls */
 	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
-		  pkt_dev->nr_labels*sizeof(u32);
+		  pkt_dev->pkt_overhead;
 	if (datalen < sizeof(struct pktgen_hdr))
 		datalen = sizeof(struct pktgen_hdr);
 
@@ -2146,10 +2249,11 @@ static struct sk_buff *fill_packet_ipv4(
 	iph->check = 0;
 	iph->check = ip_fast_csum((void *)iph, iph->ihl);
 	skb->protocol = protocol;
-	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
+	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->pkt_overhead;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 
+
 	if (pkt_dev->nfrags <= 0)
 		pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
 	else {
@@ -2216,6 +2320,30 @@ static struct sk_buff *fill_packet_ipv4(
 		pgh->tv_sec = htonl(timestamp.tv_sec);
 		pgh->tv_usec = htonl(timestamp.tv_usec);
 	}
+	// Finally let ipsec at it ;->
+	if (pkt_dev->flags & F_IPSEC_ON) {
+		struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+		if (x) {
+			int ret;
+			nhead = x->props.header_len - skb_headroom(skb);
+			if (nhead >0)
+				pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
+			/* ipsec is not expecting ll header */
+			skb_pull(skb, 14);
+			ret = pktgen_handle_ipsec(skb, pkt_dev);
+			if (ret) {
+				printk("Error creating ipsec packet %d\n",ret);
+				kfree_skb(skb);
+				return NULL;	
+			}
+		 	/* restore ll */
+			eth = (__u8 *) skb_push(skb, 14);
+			memcpy(eth, pkt_dev->hh, 12);
+			*(u16 *) & eth[12] = protocol;
+
+		}
+	}
+
 	pkt_dev->seq_num++;
 
 	return skb;
@@ -3177,8 +3305,9 @@ static int pktgen_add_device(struct pktg
 
 	if (!pktgen_setup_dev(pkt_dev)) {
 		printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
-		if (pkt_dev->flows)
+		if (pkt_dev->flows) {
 			vfree(pkt_dev->flows);
+		}
 		kfree(pkt_dev);
 		return -ENODEV;
 	}
@@ -3187,8 +3316,9 @@ static int pktgen_add_device(struct pktg
 	if (!pe) {
 		printk("pktgen: cannot create %s/%s procfs entry.\n",
 		       PG_PROC_DIR, ifname);
-		if (pkt_dev->flows)
+		if (pkt_dev->flows) {
 			vfree(pkt_dev->flows);
+		}
 		kfree(pkt_dev);
 		return -EINVAL;
 	}
@@ -3312,8 +3442,21 @@ static int pktgen_remove_device(struct p
 
 	remove_proc_entry(pkt_dev->ifname, pg_proc_dir);
 
+	if (pkt_dev->cflows) {
+		/* let go of the SAs if we have them */
+		int i = 0;
+		for (;  i < pkt_dev->nflows; i++){
+			struct xfrm_state *x = pkt_dev->flows[i].x;
+			if (x) {
+				xfrm_state_put(x);
+				pkt_dev->flows[i].x = NULL;
+			}
+		}
+	}
+
 	if (pkt_dev->flows)
 		vfree(pkt_dev->flows);
+
 	kfree(pkt_dev);
 	return 0;
 }

  reply	other threads:[~2006-09-06 12:15 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-02 13:43 [IPSEC]: searching SAD without assumming L3 details jamal
2006-09-02 15:04 ` James Morris
2006-09-02 17:16   ` jamal
2006-09-02 18:11     ` jamal
2006-09-02 19:24     ` James Morris
2006-09-05 23:38 ` Herbert Xu
2006-09-06 11:20   ` jamal
2006-09-06 11:26     ` Herbert Xu
2006-09-06 12:14       ` jamal [this message]
2006-09-06 12:30         ` jamal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1157544895.5039.33.camel@jzny2 \
    --to=hadi@cyberus.ca \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox