pktgen IPSEC 0/4
Subsystems (3)
PATCH 1/1 pktgen IPSEC 0/4
This is a set of patches that add ipsec functionality to pktgen. It is against Daves net-2.6.23
Robert, please take a closer look at this set and either sign off or comment for me to redo something. I have a short cycle before being busyed out where i can fix things.
Dave, I would like to push these to net-2.6.23 as soon as Robert Acks them.
cheers,
jamal
PATCH 1/1 pktgen IPSEC 1/4: Centralize pktgen packet overhead management
Manual labor still ... 1 of 4
cheers,
jamal
commit 38477d7ddfa58f58cce99bc902b4c18883647a71
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 06:43:00 2007 -0400
[PKTGEN] Centralize packet overhead tracking
Track the extra packet overhead for VLAN tags, MPLS, IPSEC etc
net/core/pktgen.c +15 -12
@@ -228,6 +228,7 @@ struct pktgen_dev {int min_pkt_size;/* = ETH_ZLEN; */ int max_pkt_size;/* = ETH_ZLEN; */ +int pkt_overhead;/* overhead for MPLS, VLANs, IPSEC etc */ int nfrags;__u32 delay_us;/* Default delay */ __u32 delay_ns;
@@ -2075,6 +2076,13 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us) pkt_dev->idle_acc += now - start; } +static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) +{ + pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); + pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev); +} +/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */
@@ -2323,9 +2331,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, datalen = (odev->hard_header_len +16 ) & ~0xf ; skb =alloc_skb (pkt_dev->cur_pkt_size +64 + datalen + - pkt_dev->nr_labels*sizeof (u32) + -VLAN_TAG_SIZE (pkt_dev) +SVLAN_TAG_SIZE (pkt_dev), -GFP_ATOMIC ); + pkt_dev->pkt_overhead,GFP_ATOMIC );if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ;
@@ -2368,7 +2374,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,/* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size -14 -20 -8 - - pkt_dev->nr_labels*sizeof (u32) -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead;if (datalen <sizeof (struct pktgen_hdr )) datalen =sizeof (struct pktgen_hdr );
@@ -2391,8 +2397,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, iph->check =ip_fast_csum ((void *)iph, iph->ihl); skb->protocol = protocol; skb->mac_header = (skb->network_header -ETH_HLEN - - pkt_dev->nr_labels *sizeof (u32) - -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev)); + pkt_dev->pkt_overhead); skb->dev = odev; skb->pkt_type =PACKET_HOST ;
@@ -2662,9 +2667,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,mod_cur_headers (pkt_dev); skb =alloc_skb (pkt_dev->cur_pkt_size +64 +16 + - pkt_dev->nr_labels*sizeof (u32) + -VLAN_TAG_SIZE (pkt_dev) +SVLAN_TAG_SIZE (pkt_dev), -GFP_ATOMIC ); + pkt_dev->pkt_overhead,GFP_ATOMIC );if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ;
@@ -2708,7 +2711,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,/* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size -14 -sizeof (struct ipv6hdr ) -sizeof (struct udphdr ) - - pkt_dev->nr_labels*sizeof (u32) -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead;if (datalen <sizeof (struct pktgen_hdr )) { datalen =sizeof (struct pktgen_hdr );
@@ -2738,8 +2741,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,ipv6_addr_copy (&iph->saddr, &pkt_dev->cur_in6_saddr); skb->mac_header = (skb->network_header -ETH_HLEN - - pkt_dev->nr_labels *sizeof (u32) - -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev)); + pkt_dev->pkt_overhead); skb->protocol = protocol; skb->dev = odev; skb->pkt_type =PACKET_HOST ;
@@ -2857,6 +2859,7 @@ static void pktgen_run(struct pktgen_thread *t) pkt_dev->started_at =getCurUs (); pkt_dev->next_tx_us =getCurUs ();/* Transmit immediately */ pkt_dev->next_tx_ns =0 ; +set_pkt_overhead (pkt_dev);strcpy (pkt_dev->result,"Starting" ); started++;
PATCH 1/1 pktgen IPSEC 2/4: Introduce pktgen sequential flows
2 of 4
cheers,
jamal
commit 882c296bb3f153e1ac770a874c75cfb2bab8481b
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 07:24:00 2007 -0400
[PKTGEN] Introduce sequential flows
By default all flows in pktgen are randomly selected. This patch introduces ability to have all defined flows to be sent sequentially. Robert defined randomness to be the default behavior.
net/core/pktgen.c +52 -8
@@ -181,6 +181,7 @@#define F_MPLS_RND (1<<8)/* Random MPLS labels */ #define F_VID_RND (1<<9)/* Random VLAN ID */ #define F_SVID_RND (1<<10)/* Random SVLAN ID */ +#define F_FLOW_SEQ (1<<11)/* Sequential flows */ /* Thread control flag bits */ #define T_TERMINATE (1<<0)
@@ -207,8 +208,12 @@ static struct proc_dir_entry *pg_proc_dir = NULL;struct flow_state {__be32 cur_daddr;int count; +__u32 flags; }; +/* flow flag bits */ +#define F_INIT (1<<0)/* flow has been initialized */ +struct pktgen_dev {/* * Try to keep frequent/infrequent used vars. separated.
@@ -342,6 +347,7 @@ struct pktgen_dev {unsigned cflows;/* Concurrent flows (config) */ unsigned lflow;/* Flow length (config) */ unsigned nflows;/* accumulated flows (stats) */ +unsigned curfl;/* current sequenced flow (state)*/ char result[512 ]; };
@@ -691,6 +697,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v)if (pkt_dev->flags &F_MPLS_RND )seq_printf (seq,"MPLS_RND " ); +if (pkt_dev->cflows) { +if (pkt_dev->flags &F_FLOW_SEQ ) +seq_printf (seq,"FLOW_SEQ " );/*in sequence flows*/ +else +seq_printf (seq,"FLOW_RND " ); + } +if (pkt_dev->flags &F_MACSRC_RND )seq_printf (seq,"MACSRC_RND " );
@@ -1182,6 +1195,9 @@ static ssize_t pktgen_if_write(struct file *file,else if (strcmp (f,"!SVID_RND" ) ==0 ) pkt_dev->flags &= ~F_SVID_RND ; +else if (strcmp (f,"FLOW_SEQ" ) ==0 ) + pkt_dev->flags |=F_FLOW_SEQ ; +else if (strcmp (f,"!IPV6" ) ==0 ) pkt_dev->flags &= ~F_IPV6 ;
@@ -1190,7 +1206,7 @@ static ssize_t pktgen_if_write(struct file *file,"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s" , f,"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " - "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n"); + "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ\n");return count; }sprintf (pg_result,"OK: flags=0x%x" , pkt_dev->flags);
@@ -2083,6 +2099,37 @@ static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev); } +static inline int f_seen (struct pktgen_dev *pkt_dev,int flow) +{ + +if (pkt_dev->flows[flow].flags &F_INIT ) +return 1 ; +else +return 0 ; +} + +static inline int f_pick (struct pktgen_dev *pkt_dev) +{ +int flow = pkt_dev->curfl; + +if (pkt_dev->flags &F_FLOW_SEQ ) { +if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { +/* reset time */ + pkt_dev->flows[flow].count =0 ; + pkt_dev->curfl +=1 ; +if (pkt_dev->curfl >= pkt_dev->cflows) + pkt_dev->curfl =0 ;/*reset */ + } + }else { + flow =random32 () % pkt_dev->cflows; + +if (pkt_dev->flows[flow].count > pkt_dev->lflow) + pkt_dev->flows[flow].count =0 ; + } + +return pkt_dev->curfl; +} +/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */
@@ -2092,12 +2139,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)__u32 imx;int flow =0 ; -if (pkt_dev->cflows) { - flow =random32 () % pkt_dev->cflows; - -if (pkt_dev->flows[flow].count > pkt_dev->lflow) - pkt_dev->flows[flow].count =0 ; - } +if (pkt_dev->cflows) + flow =f_pick (pkt_dev);/* Deal with source MAC */ if (pkt_dev->src_mac_count >1 ) {
@@ -2213,7 +2256,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->cur_saddr =htonl (t); } -if (pkt_dev->cflows && pkt_dev->flows[flow].count !=0 ) { +if (pkt_dev->cflows &&f_seen (pkt_dev, flow)) { pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; }else { imn =ntohl (pkt_dev->daddr_min);
@@ -2243,6 +2286,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) } }if (pkt_dev->cflows) { + pkt_dev->flows[flow].flags |=F_INIT ; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; pkt_dev->nflows++;
PATCH 1/1 pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
3 of 4 ..
cheers,
jamal
commit 677f1c1459218919f5aa2622625dc8709c2a98ce
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 07:28:59 2007 -0400
[XFRM] Introduce standalone SAD lookup
This allows other in-kernel functions to do SAD lookups. The only known user at the moment is pktgen.
include/net/xfrm.h +4 -0
@@ -920,6 +920,10 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); +extern struct xfrm_state *xfrm_stateonly_find (xfrm_address_t *daddr, +xfrm_address_t *saddr, +unsigned short family, +u8 mode,u8 proto,u32 reqid);extern int xfrm_state_check_expire (struct xfrm_state *x);extern void xfrm_state_insert (struct xfrm_state *x);extern int xfrm_state_add (struct xfrm_state *x);
net/xfrm/xfrm_state.c +35 -0
@@ -686,6 +686,41 @@ out:return x; } +struct xfrm_state * +xfrm_stateonly_find (xfrm_address_t *daddr,xfrm_address_t *saddr, +unsigned short family,u8 mode,u8 proto,u32 reqid) +{ +unsigned int h =xfrm_dst_hash (daddr, saddr, reqid, family); +struct xfrm_state *rx =NULL , *x =NULL ; +struct hlist_node *entry; + +spin_lock (&xfrm_state_lock); +hlist_for_each_entry (x, entry, xfrm_state_bydst+h, bydst) { +if (x->props.family == family && + x->props.reqid == reqid && + !(x->props.flags &XFRM_STATE_WILDRECV ) && +xfrm_state_addr_check (x, daddr, saddr, family) && + mode == x->props.mode && + proto == x->id.proto) { + +if (x->km.state !=XFRM_STATE_VALID ) +continue ; +else { + rx = x; +break ; + } + } + } + +if (rx) +xfrm_state_hold (rx); +spin_unlock (&xfrm_state_lock); + + +return rx; +} +EXPORT_SYMBOL (xfrm_stateonly_find); +static void __xfrm_state_insert (struct xfrm_state *x) {unsigned int h;
PATCH 1/1 pktgen IPSEC 4/4: Add IPSEC support to pktgen
4 of 4
cheers,
jamal
commit e035613eae587251b8c98b7d503eab207f1d26e2
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 07:43:30 2007 -0400
[PKTGEN] IPSEC support
Added transport mode ESP support for starters.
I will send more of these modes and types once i have resolved the tunnel mode isses.
net/core/pktgen.c +150 -2
@@ -152,6 +152,9 @@#include <net/checksum.h> #include <net/ipv6.h> #include <net/addrconf.h> +#ifdef CONFIG_XFRM +#include <net/xfrm.h> +#endif #include <asm/byteorder.h> #include <linux/rcupdate.h> #include <asm/bitops.h>
@@ -182,6 +185,7 @@#define F_VID_RND (1<<9)/* Random VLAN ID */ #define F_SVID_RND (1<<10)/* Random SVLAN ID */ #define F_FLOW_SEQ (1<<11)/* Sequential flows */ +#define F_IPSEC_ON (1<<12)/* ipsec on for flows */ /* Thread control flag bits */ #define T_TERMINATE (1<<0)
@@ -208,6 +212,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;struct flow_state {__be32 cur_daddr;int count; +#ifdef CONFIG_XFRM +struct xfrm_state *x; +#endif __u32 flags; };
@@ -348,7 +355,10 @@ struct pktgen_dev {unsigned lflow;/* Flow length (config) */ unsigned nflows;/* accumulated flows (stats) */ unsigned curfl;/* current sequenced flow (state)*/ - +#ifdef CONFIG_XFRM +__u8 ipsmode;/* IPSEC mode (config) */ +__u8 ipsproto;/* IPSEC type (config) */ +#endif char result[512 ]; };
@@ -704,6 +714,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)seq_printf (seq,"FLOW_RND " ); } +if (pkt_dev->flags &F_IPSEC_ON ) +seq_printf (seq,"IPSEC " ); +if (pkt_dev->flags &F_MACSRC_RND )seq_printf (seq,"MACSRC_RND " );
@@ -1198,6 +1211,11 @@ static ssize_t pktgen_if_write(struct file *file,else if (strcmp (f,"FLOW_SEQ" ) ==0 ) pkt_dev->flags |=F_FLOW_SEQ ; +#ifdef CONFIG_XFRM + else if (strcmp(f, "IPSEC") == 0) + pkt_dev->flags |= F_IPSEC_ON; +#endif + else if (strcmp(f, "!IPV6") == 0) pkt_dev->flags &= ~F_IPV6;
@@ -1206,7 +1224,7 @@ static ssize_t pktgen_if_write(struct file *file,"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s" , f,"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " - "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ\n"); + "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");return count; }sprintf (pg_result,"OK: flags=0x%x" , pkt_dev->flags);
@@ -2094,6 +2112,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) { + pkt_dev->pkt_overhead =0 ; pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev);
@@ -2130,6 +2149,31 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)return pkt_dev->curfl; } + +#ifdef CONFIG_XFRM +/* If there was already an IPSEC SA, we keep it as is, else +* we go look for it ... +*/ +inline +void get_ipsec_sa (struct pktgen_dev *pkt_dev,int flow) +{ +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 , + pkt_dev->ipsmode, + pkt_dev->ipsproto,0 ); +if (x) { + pkt_dev->flows[flow].x = x; +set_pkt_overhead (pkt_dev); + pkt_dev->pkt_overhead+=x->props.header_len; + } + + } +} +#endif /* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */
@@ -2289,6 +2333,10 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].flags |=F_INIT ; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; +#ifdef CONFIG_XFRM +if (pkt_dev->flags &F_IPSEC_ON ) +get_ipsec_sa (pkt_dev, flow); +#endif pkt_dev->nflows++; } }
@@ -2329,6 +2377,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].count++; } + +#ifdef CONFIG_XFRM +static int pktgen_output_ipsec (struct sk_buff *skb,struct pktgen_dev *pkt_dev) +{ +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int err =0 ; +struct iphdr *iph; + +if (!x) +return 0 ; +/* XXX: we dont support tunnel mode for now until +* we resolve the dst issue */ +if (x->props.mode !=XFRM_MODE_TRANSPORT ) +return 0 ; + +spin_lock (&x->lock); + iph =ip_hdr (skb); + + 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 inline void free_SAs (struct pktgen_dev *pkt_dev) +{ +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 ; + } + } + } +} + +static inline int process_ipsec (struct pktgen_dev *pkt_dev, +struct sk_buff *skb,__be16 protocol) +{ +if (pkt_dev->flags &F_IPSEC_ON ) { +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int nhead =0 ; +if (x) { +int ret; +__u8 *eth; + nhead = x->props.header_len -skb_headroom (skb); +if (nhead >0 ) { + ret =pskb_expand_head (skb, nhead,0 ,GFP_ATOMIC ); +if (ret <0 ) { +printk ("Error expanding ipsec packet %d\n" ,ret); +return 0 ; + } + } + +/* ipsec is not expecting ll header */ +skb_pull (skb,ETH_HLEN ); + ret =pktgen_output_ipsec (skb, pkt_dev); +if (ret) { +printk ("Error creating ipsec packet %d\n" ,ret); +kfree_skb (skb); +return 0 ; + } +/* restore ll */ + eth = (__u8 *)skb_push (skb,ETH_HLEN ); +memcpy (eth, pkt_dev->hh,12 ); + *(u16 *) & eth[12 ] = protocol; + } + } +return 1 ; +} +#endif +static void mpls_push (__be32 *mpls,struct pktgen_dev *pkt_dev) {unsigned i;
@@ -2512,6 +2645,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, pgh->tv_usec =htonl (timestamp.tv_usec); } +#ifdef CONFIG_XFRM +if (!process_ipsec (pkt_dev, skb, protocol)) +return NULL ; +#endif +return skb; }
@@ -3493,11 +3631,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) } pkt_dev->entry->proc_fops = &pktgen_if_fops; pkt_dev->entry->data = pkt_dev; +#ifdef CONFIG_XFRM + pkt_dev->ipsmode =XFRM_MODE_TRANSPORT ; + pkt_dev->ipsproto =IPPROTO_ESP ; +#endif return add_dev_to_thread (t, pkt_dev); out2:dev_put (pkt_dev->odev); out1: +#ifdef CONFIG_XFRM +free_SAs (pkt_dev ); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);
@@ -3592,6 +3737,9 @@ static int pktgen_remove_device(struct pktgen_thread *t,if (pkt_dev->entry)remove_proc_entry (pkt_dev->entry->name, pg_proc_dir); +#ifdef CONFIG_XFRM +free_SAs (pkt_dev); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);
PATCH 1/1 pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
In reply to jamalQuoted 7 lines · jamal
3 of 4 ..
[XFRM] Introduce standalone SAD lookup
This allows other in-kernel functions to do SAD lookups. The only known user at the moment is pktgen.Signed-off-by Jamal Hadi Salim <[email protected]>
xfrm is not my area.....
Cheers
--ro
Quoted 62 lines
include/net/xfrm.h +4
-0@@ -920,6 +920,10 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); +extern struct xfrm_state *xfrm_stateonly_find (xfrm_address_t *daddr, +xfrm_address_t *saddr, +unsigned short family, +u8 mode,u8 proto,u32 reqid);extern int xfrm_state_check_expire (struct xfrm_state *x);extern void xfrm_state_insert (struct xfrm_state *x);extern int xfrm_state_add (struct xfrm_state *x);net/xfrm/xfrm_state.c +35
-0@@ -686,6 +686,41 @@ out:return x; } +struct xfrm_state * +xfrm_stateonly_find (xfrm_address_t *daddr,xfrm_address_t *saddr, +unsigned short family,u8 mode,u8 proto,u32 reqid) +{ +unsigned int h =xfrm_dst_hash (daddr, saddr, reqid, family); +struct xfrm_state *rx =NULL , *x =NULL ; +struct hlist_node *entry; + +spin_lock (&xfrm_state_lock); +hlist_for_each_entry (x, entry, xfrm_state_bydst+h, bydst) { +if (x->props.family == family && + x->props.reqid == reqid && + !(x->props.flags &XFRM_STATE_WILDRECV ) && +xfrm_state_addr_check (x, daddr, saddr, family) && + mode == x->props.mode && + proto == x->id.proto) { + +if (x->km.state !=XFRM_STATE_VALID ) +continue ; +else { + rx = x; +break ; + } + } + } + +if (rx) +xfrm_state_hold (rx); +spin_unlock (&xfrm_state_lock); + + +return rx; +} +EXPORT_SYMBOL (xfrm_stateonly_find); +static void __xfrm_state_insert (struct xfrm_state *x) {unsigned int h;
PATCH 1/1 pktgen IPSEC 2/4: Introduce pktgen sequential flows
In reply to jamalQuoted 8 lines · jamal
2 of 4
cheers,
jamal
commit882c296bb3f153e1ac770a874c75cfb2bab8481bAuthor: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 07:24:00 2007 -0400
Quoted 8 lines
[PKTGEN] Introduce sequential flows
By default all flows in pktgen are randomly selected. This patch introduces ability to have all defined flows to be sent sequentially. Robert defined randomness to be the default behavior.
Signed-off-by Jamal Hadi Salim <[email protected]>
Cheers
--ro
Quoted 137 lines
net/core/pktgen.c +52
-8@@ -181,6 +181,7 @@#define F_MPLS_RND (1<<8)/* Random MPLS labels */ #define F_VID_RND (1<<9)/* Random VLAN ID */ #define F_SVID_RND (1<<10)/* Random SVLAN ID */ +#define F_FLOW_SEQ (1<<11)/* Sequential flows */ /* Thread control flag bits */ #define T_TERMINATE (1<<0)@@ -207,8 +208,12 @@ static struct proc_dir_entry *pg_proc_dir = NULL;struct flow_state {__be32 cur_daddr;int count; +__u32 flags; }; +/* flow flag bits */ +#define F_INIT (1<<0)/* flow has been initialized */ +struct pktgen_dev {/* * Try to keep frequent/infrequent used vars. separated. @@ -342,6 +347,7 @@ struct pktgen_dev {unsigned cflows;/* Concurrent flows (config) */ unsigned lflow;/* Flow length (config) */ unsigned nflows;/* accumulated flows (stats) */ +unsigned curfl;/* current sequenced flow (state)*/ char result[512 ]; };@@ -691,6 +697,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v)if (pkt_dev->flags &F_MPLS_RND )seq_printf (seq,"MPLS_RND " ); +if (pkt_dev->cflows) { +if (pkt_dev->flags &F_FLOW_SEQ ) +seq_printf (seq,"FLOW_SEQ " );/*in sequence flows*/ +else +seq_printf (seq,"FLOW_RND " ); + } +if (pkt_dev->flags &F_MACSRC_RND )seq_printf (seq,"MACSRC_RND " );@@ -1182,6 +1195,9 @@ static ssize_t pktgen_if_write(struct file *file,else if (strcmp (f,"!SVID_RND" ) ==0 ) pkt_dev->flags &= ~F_SVID_RND ; +else if (strcmp (f,"FLOW_SEQ" ) ==0 ) + pkt_dev->flags |=F_FLOW_SEQ ; +else if (strcmp (f,"!IPV6" ) ==0 ) pkt_dev->flags &= ~F_IPV6 ;@@ -1190,7 +1206,7 @@ static ssize_t pktgen_if_write(struct file *file,"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s" , f,"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " - "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n"); + "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ\n");return count; }sprintf (pg_result,"OK: flags=0x%x" , pkt_dev->flags);@@ -2083,6 +2099,37 @@ static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev); } +static inline int f_seen (struct pktgen_dev *pkt_dev,int flow) +{ + +if (pkt_dev->flows[flow].flags &F_INIT ) +return 1 ; +else +return 0 ; +} + +static inline int f_pick (struct pktgen_dev *pkt_dev) +{ +int flow = pkt_dev->curfl; + +if (pkt_dev->flags &F_FLOW_SEQ ) { +if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { +/* reset time */ + pkt_dev->flows[flow].count =0 ; + pkt_dev->curfl +=1 ; +if (pkt_dev->curfl >= pkt_dev->cflows) + pkt_dev->curfl =0 ;/*reset */ + } + }else { + flow =random32 () % pkt_dev->cflows; + +if (pkt_dev->flows[flow].count > pkt_dev->lflow) + pkt_dev->flows[flow].count =0 ; + } + +return pkt_dev->curfl; +} +/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */ @@ -2092,12 +2139,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)__u32 imx;int flow =0 ; -if (pkt_dev->cflows) { - flow =random32 () % pkt_dev->cflows; - -if (pkt_dev->flows[flow].count > pkt_dev->lflow) - pkt_dev->flows[flow].count =0 ; - } +if (pkt_dev->cflows) + flow =f_pick (pkt_dev);/* Deal with source MAC */ if (pkt_dev->src_mac_count >1 ) {@@ -2213,7 +2256,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->cur_saddr =htonl (t); } -if (pkt_dev->cflows && pkt_dev->flows[flow].count !=0 ) { +if (pkt_dev->cflows &&f_seen (pkt_dev, flow)) { pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; }else { imn =ntohl (pkt_dev->daddr_min);@@ -2243,6 +2286,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) } }if (pkt_dev->cflows) { + pkt_dev->flows[flow].flags |=F_INIT ; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; pkt_dev->nflows++;
PATCH 1/1 pktgen IPSEC 1/4: Centralize pktgen packet overhead management
In reply to jamalQuoted 6 lines · jamal
Manual labor still ... 1 of 4
[PKTGEN] Centralize packet overhead tracking
Track the extra packet overhead for VLAN tags, MPLS, IPSEC etcSigned-off-by Jamal Hadi Salim <[email protected]>
Thanks, Jamal.
I'll guess the ipsec part is to be considered work-in-progress and you're doing both the work and the progress.
Cheers
--ro
Quoted 94 lines
net/core/pktgen.c +15
-12@@ -228,6 +228,7 @@ struct pktgen_dev {int min_pkt_size;/* = ETH_ZLEN; */ int max_pkt_size;/* = ETH_ZLEN; */ +int pkt_overhead;/* overhead for MPLS, VLANs, IPSEC etc */ int nfrags;__u32 delay_us;/* Default delay */ __u32 delay_ns;@@ -2075,6 +2076,13 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us) pkt_dev->idle_acc += now - start; } +static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) +{ + pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); + pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev); +} +/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */ @@ -2323,9 +2331,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, datalen = (odev->hard_header_len +16 ) & ~0xf ; skb =alloc_skb (pkt_dev->cur_pkt_size +64 + datalen + - pkt_dev->nr_labels*sizeof (u32) + -VLAN_TAG_SIZE (pkt_dev) +SVLAN_TAG_SIZE (pkt_dev), -GFP_ATOMIC ); + pkt_dev->pkt_overhead,GFP_ATOMIC );if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ;@@ -2368,7 +2374,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,/* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size -14 -20 -8 - - pkt_dev->nr_labels*sizeof (u32) -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead;if (datalen <sizeof (struct pktgen_hdr )) datalen =sizeof (struct pktgen_hdr );@@ -2391,8 +2397,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, iph->check =ip_fast_csum ((void *)iph, iph->ihl); skb->protocol = protocol; skb->mac_header = (skb->network_header -ETH_HLEN - - pkt_dev->nr_labels *sizeof (u32) - -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev)); + pkt_dev->pkt_overhead); skb->dev = odev; skb->pkt_type =PACKET_HOST ;@@ -2662,9 +2667,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,mod_cur_headers (pkt_dev); skb =alloc_skb (pkt_dev->cur_pkt_size +64 +16 + - pkt_dev->nr_labels*sizeof (u32) + -VLAN_TAG_SIZE (pkt_dev) +SVLAN_TAG_SIZE (pkt_dev), -GFP_ATOMIC ); + pkt_dev->pkt_overhead,GFP_ATOMIC );if (!skb) {sprintf (pkt_dev->result,"No memory" );return NULL ;@@ -2708,7 +2711,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,/* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size -14 -sizeof (struct ipv6hdr ) -sizeof (struct udphdr ) - - pkt_dev->nr_labels*sizeof (u32) -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev); + pkt_dev->pkt_overhead;if (datalen <sizeof (struct pktgen_hdr )) { datalen =sizeof (struct pktgen_hdr );@@ -2738,8 +2741,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,ipv6_addr_copy (&iph->saddr, &pkt_dev->cur_in6_saddr); skb->mac_header = (skb->network_header -ETH_HLEN - - pkt_dev->nr_labels *sizeof (u32) - -VLAN_TAG_SIZE (pkt_dev) -SVLAN_TAG_SIZE (pkt_dev)); + pkt_dev->pkt_overhead); skb->protocol = protocol; skb->dev = odev; skb->pkt_type =PACKET_HOST ;@@ -2857,6 +2859,7 @@ static void pktgen_run(struct pktgen_thread *t) pkt_dev->started_at =getCurUs (); pkt_dev->next_tx_us =getCurUs ();/* Transmit immediately */ pkt_dev->next_tx_ns =0 ; +set_pkt_overhead (pkt_dev);strcpy (pkt_dev->result,"Starting" ); started++;
Re: [PATCH] pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
In reply to jamalLooks good too me, just a few minor nitpicks as usual :)
Quoted 9 lines · jamal
[XFRM] Introduce standalone SAD lookup
net/xfrm/xfrm_state.c +7
-0+struct xfrm_state * +xfrm_stateonly_find (xfrm_address_t *daddr,xfrm_address_t *saddr, +unsigned short family,u8 mode,u8 proto,u32 reqid) +{ +unsigned int h =xfrm_dst_hash (daddr, saddr, reqid, family); +struct xfrm_state *rx =NULL , *x =NULL ; +struct hlist_node *entry;
net/xfrm/xfrm_state.c out: · line 705
Quoted 10 lines
net/xfrm/xfrm_state.c +10
-0+ +spin_lock (&xfrm_state_lock); +hlist_for_each_entry (x, entry, xfrm_state_bydst+h, bydst) { +if (x->props.family == family && + x->props.reqid == reqid && + !(x->props.flags &XFRM_STATE_WILDRECV ) && +xfrm_state_addr_check (x, daddr, saddr, family) && + mode == x->props.mode && + proto == x->id.proto) { +
^^ please delete empty line
net/xfrm/xfrm_state.c out: · line 707
Quoted 2 lines
net/xfrm/xfrm_state.c +2
-0+if (x->km.state !=XFRM_STATE_VALID ) +continue ;
^ one indentation level too much
net/xfrm/xfrm_state.c out: · line 711
Quoted 4 lines
net/xfrm/xfrm_state.c +4
-0+else { + rx = x; +break ; + }
The whole thing could be compacted by moving the XFRM_STATE_VALID check to the first condition:
if (x->props.family == family &&
x->props.reqid == reqid &&
!(x->props.flags & XFRM_STATE_WILDRECV) &&
xfrm_state_addr_check(x, daddr, saddr, family) &&
mode == x->props.mode &&
proto == x->id.proto &&
x->km.state == XFRM_STATE_VALID) {
rx = x;
break;
}or alternatively turn the != XFRM_STATE_VALID into == if you want to keep the first condition similar to xfrm_state_find (but the mode and proto conditions are reversed anyways).
BTW, wouldn't it make sense to allow use of the SPI as well?
PATCH 1/1 pktgen IPSEC 4/4: Add IPSEC support to pktgen
In reply to jamalQuoted 8 lines · jamal
4 of 4
[PKTGEN] IPSEC support
Added transport mode ESP support for starters.
I will send more of these modes and types once i have resolved the tunnel mode isses.Signed-off-by Jamal Hadi Salim <[email protected]>
Cheers
--ro
Quoted 260 lines
net/core/pktgen.c +150
-2@@ -152,6 +152,9 @@#include <net/checksum.h> #include <net/ipv6.h> #include <net/addrconf.h> +#ifdef CONFIG_XFRM +#include <net/xfrm.h> +#endif #include <asm/byteorder.h> #include <linux/rcupdate.h> #include <asm/bitops.h> @@ -182,6 +185,7 @@#define F_VID_RND (1<<9)/* Random VLAN ID */ #define F_SVID_RND (1<<10)/* Random SVLAN ID */ #define F_FLOW_SEQ (1<<11)/* Sequential flows */ +#define F_IPSEC_ON (1<<12)/* ipsec on for flows */ /* Thread control flag bits */ #define T_TERMINATE (1<<0)@@ -208,6 +212,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;struct flow_state {__be32 cur_daddr;int count; +#ifdef CONFIG_XFRM +struct xfrm_state *x; +#endif __u32 flags; };@@ -348,7 +355,10 @@ struct pktgen_dev {unsigned lflow;/* Flow length (config) */ unsigned nflows;/* accumulated flows (stats) */ unsigned curfl;/* current sequenced flow (state)*/ - +#ifdef CONFIG_XFRM +__u8 ipsmode;/* IPSEC mode (config) */ +__u8 ipsproto;/* IPSEC type (config) */ +#endif char result[512 ]; };@@ -704,6 +714,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)seq_printf (seq,"FLOW_RND " ); } +if (pkt_dev->flags &F_IPSEC_ON ) +seq_printf (seq,"IPSEC " ); +if (pkt_dev->flags &F_MACSRC_RND )seq_printf (seq,"MACSRC_RND " );@@ -1198,6 +1211,11 @@ static ssize_t pktgen_if_write(struct file *file,else if (strcmp (f,"FLOW_SEQ" ) ==0 ) pkt_dev->flags |=F_FLOW_SEQ ; +#ifdef CONFIG_XFRM + else if (strcmp(f, "IPSEC") == 0) + pkt_dev->flags |= F_IPSEC_ON; +#endif + else if (strcmp(f, "!IPV6") == 0) pkt_dev->flags &= ~F_IPV6;@@ -1206,7 +1224,7 @@ static ssize_t pktgen_if_write(struct file *file,"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s" , f,"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " - "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ\n"); + "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");return count; }sprintf (pg_result,"OK: flags=0x%x" , pkt_dev->flags);@@ -2094,6 +2112,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) { + pkt_dev->pkt_overhead =0 ; pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev);@@ -2130,6 +2149,31 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)return pkt_dev->curfl; } + +#ifdef CONFIG_XFRM +/* If there was already an IPSEC SA, we keep it as is, else +* we go look for it ... +*/ +inline +void get_ipsec_sa (struct pktgen_dev *pkt_dev,int flow) +{ +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 , + pkt_dev->ipsmode, + pkt_dev->ipsproto,0 ); +if (x) { + pkt_dev->flows[flow].x = x; +set_pkt_overhead (pkt_dev); + pkt_dev->pkt_overhead+=x->props.header_len; + } + + } +} +#endif /* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */ @@ -2289,6 +2333,10 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].flags |=F_INIT ; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; +#ifdef CONFIG_XFRM +if (pkt_dev->flags &F_IPSEC_ON ) +get_ipsec_sa (pkt_dev, flow); +#endif pkt_dev->nflows++; } }@@ -2329,6 +2377,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].count++; } + +#ifdef CONFIG_XFRM +static int pktgen_output_ipsec (struct sk_buff *skb,struct pktgen_dev *pkt_dev) +{ +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int err =0 ; +struct iphdr *iph; + +if (!x) +return 0 ; +/* XXX: we dont support tunnel mode for now until +* we resolve the dst issue */ +if (x->props.mode !=XFRM_MODE_TRANSPORT ) +return 0 ; + +spin_lock (&x->lock); + iph =ip_hdr (skb); + + 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 inline void free_SAs (struct pktgen_dev *pkt_dev) +{ +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 ; + } + } + } +} + +static inline int process_ipsec (struct pktgen_dev *pkt_dev, +struct sk_buff *skb,__be16 protocol) +{ +if (pkt_dev->flags &F_IPSEC_ON ) { +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int nhead =0 ; +if (x) { +int ret; +__u8 *eth; + nhead = x->props.header_len -skb_headroom (skb); +if (nhead >0 ) { + ret =pskb_expand_head (skb, nhead,0 ,GFP_ATOMIC ); +if (ret <0 ) { +printk ("Error expanding ipsec packet %d\n" ,ret); +return 0 ; + } + } + +/* ipsec is not expecting ll header */ +skb_pull (skb,ETH_HLEN ); + ret =pktgen_output_ipsec (skb, pkt_dev); +if (ret) { +printk ("Error creating ipsec packet %d\n" ,ret); +kfree_skb (skb); +return 0 ; + } +/* restore ll */ + eth = (__u8 *)skb_push (skb,ETH_HLEN ); +memcpy (eth, pkt_dev->hh,12 ); + *(u16 *) & eth[12 ] = protocol; + } + } +return 1 ; +} +#endif +static void mpls_push (__be32 *mpls,struct pktgen_dev *pkt_dev) {unsigned i;@@ -2512,6 +2645,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, pgh->tv_usec =htonl (timestamp.tv_usec); } +#ifdef CONFIG_XFRM +if (!process_ipsec (pkt_dev, skb, protocol)) +return NULL ; +#endif +return skb; }@@ -3493,11 +3631,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) } pkt_dev->entry->proc_fops = &pktgen_if_fops; pkt_dev->entry->data = pkt_dev; +#ifdef CONFIG_XFRM + pkt_dev->ipsmode =XFRM_MODE_TRANSPORT ; + pkt_dev->ipsproto =IPPROTO_ESP ; +#endif return add_dev_to_thread (t, pkt_dev); out2:dev_put (pkt_dev->odev); out1: +#ifdef CONFIG_XFRM +free_SAs (pkt_dev ); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);@@ -3592,6 +3737,9 @@ static int pktgen_remove_device(struct pktgen_thread *t,if (pkt_dev->entry)remove_proc_entry (pkt_dev->entry->name, pg_proc_dir); +#ifdef CONFIG_XFRM +free_SAs (pkt_dev); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);
Re: [PATCH] pktgen IPSEC 1/4: Centralize pktgen packet overhead management
In reply to Robert OlssonQuoted 4 lines · Robert Olsson
I'll guess the ipsec part is to be considered work-in-progress and you're doing both the work and the progress.
;->
Much thanks Robert.
cheers,
jamal
Re: [PATCH] pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
In reply to Patrick McHardyQuoted 1 line · Patrick McHardy
Looks good too me, just a few minor nitpicks as usual :)
I like the nitpicks - they make the code better (as long as we put a time limit on them ;->)
Quoted 2 lines
^^ please delete empty line
will do.
Quoted 4 lines
net/xfrm/xfrm_state.c out: · line 707
Quoted 2 lines
net/xfrm/xfrm_state.c +2
-0+if (x->km.state !=XFRM_STATE_VALID ) +continue ;^ one indentation level too much
will fix.
Quoted 14 lines
The whole thing could be compacted by moving the
XFRM_STATE_VALIDcheck to the first condition:if (x->props.family == family && x->props.reqid == reqid && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && mode == x->props.mode && proto == x->id.proto && x->km.state == XFRM_STATE_VALID) { rx = x; break; }
Quoted 4 lines
or alternatively turn the !=
XFRM_STATE_VALIDinto == if you want to keep the first condition similar toxfrm_state_find(but the mode and proto conditions are reversed anyways).
Will do.
Quoted 1 line
BTW, wouldn't it make sense to allow use of the SPI as well?
SPI is the least user friendly parameter - but i could add it later. I want to add tunnel mode next then i can revisit SPI.
Thanks for taking the time to review this Patrick.
cheers,
jamal
Resend: [PATCH] pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
This takes into considerations Patricks feedback.
cheers,
jamal
commit 4fe3190756589ef8155eb97fe725f2564f1fc77d
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 12:35:39 2007 -0400
[XFRM] Introduce standalone SAD lookup
This allows other in-kernel functions to do SAD lookups. The only known user at the moment is pktgen.
include/net/xfrm.h +4 -0
@@ -920,6 +920,10 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); +extern struct xfrm_state *xfrm_stateonly_find (xfrm_address_t *daddr, +xfrm_address_t *saddr, +unsigned short family, +u8 mode,u8 proto,u32 reqid);extern int xfrm_state_check_expire (struct xfrm_state *x);extern void xfrm_state_insert (struct xfrm_state *x);extern int xfrm_state_add (struct xfrm_state *x);
net/xfrm/xfrm_state.c +31 -0
@@ -686,6 +686,37 @@ out:return x; } +struct xfrm_state * +xfrm_stateonly_find (xfrm_address_t *daddr,xfrm_address_t *saddr, +unsigned short family,u8 mode,u8 proto,u32 reqid) +{ +unsigned int h =xfrm_dst_hash (daddr, saddr, reqid, family); +struct xfrm_state *rx =NULL , *x =NULL ; +struct hlist_node *entry; + +spin_lock (&xfrm_state_lock); +hlist_for_each_entry (x, entry, xfrm_state_bydst+h, bydst) { +if (x->props.family == family && + x->props.reqid == reqid && + !(x->props.flags &XFRM_STATE_WILDRECV ) && +xfrm_state_addr_check (x, daddr, saddr, family) && + mode == x->props.mode && + proto == x->id.proto && + x->km.state ==XFRM_STATE_VALID ) { + rx = x; +break ; + } + } + +if (rx) +xfrm_state_hold (rx); +spin_unlock (&xfrm_state_lock); + + +return rx; +} +EXPORT_SYMBOL (xfrm_stateonly_find); +static void __xfrm_state_insert (struct xfrm_state *x) {unsigned int h;
Resend: [PATCH] pktgen IPSEC 4/4: Add IPSEC support to pktgen
In reply to jamalSorry Robert, I found a problem compiling when i turned off XFRM. This fixes it.
cheers,
jamal
commit bfd389bba7654aa118f0949ff0de45a3bce9700c
Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 18:59:33 2007 -0400
[PKTGEN] IPSEC support
Added transport mode ESP support for starters.
I will send more of these modes and types once i have resolved the tunnel mode isses.
net/core/pktgen.c +152 -2
@@ -152,6 +152,9 @@#include <net/checksum.h> #include <net/ipv6.h> #include <net/addrconf.h> +#ifdef CONFIG_XFRM +#include <net/xfrm.h> +#endif #include <asm/byteorder.h> #include <linux/rcupdate.h> #include <asm/bitops.h>
@@ -182,6 +185,7 @@#define F_VID_RND (1<<9)/* Random VLAN ID */ #define F_SVID_RND (1<<10)/* Random SVLAN ID */ #define F_FLOW_SEQ (1<<11)/* Sequential flows */ +#define F_IPSEC_ON (1<<12)/* ipsec on for flows */ /* Thread control flag bits */ #define T_TERMINATE (1<<0)
@@ -208,6 +212,9 @@ static struct proc_dir_entry *pg_proc_dir = NULL;struct flow_state {__be32 cur_daddr;int count; +#ifdef CONFIG_XFRM +struct xfrm_state *x; +#endif __u32 flags; };
@@ -348,7 +355,10 @@ struct pktgen_dev {unsigned lflow;/* Flow length (config) */ unsigned nflows;/* accumulated flows (stats) */ unsigned curfl;/* current sequenced flow (state)*/ - +#ifdef CONFIG_XFRM +__u8 ipsmode;/* IPSEC mode (config) */ +__u8 ipsproto;/* IPSEC type (config) */ +#endif char result[512 ]; };
@@ -704,6 +714,11 @@ static int pktgen_if_show(struct seq_file *seq, void *v)seq_printf (seq,"FLOW_RND " ); } +#ifdef CONFIG_XFRM +if (pkt_dev->flags &F_IPSEC_ON ) +seq_printf (seq,"IPSEC " ); +#endif +if (pkt_dev->flags &F_MACSRC_RND )seq_printf (seq,"MACSRC_RND " );
@@ -1198,6 +1213,11 @@ static ssize_t pktgen_if_write(struct file *file,else if (strcmp (f,"FLOW_SEQ" ) ==0 ) pkt_dev->flags |=F_FLOW_SEQ ; +#ifdef CONFIG_XFRM + else if (strcmp(f, "IPSEC") == 0) + pkt_dev->flags |= F_IPSEC_ON; +#endif + else if (strcmp(f, "!IPV6") == 0) pkt_dev->flags &= ~F_IPV6;
@@ -1206,7 +1226,7 @@ static ssize_t pktgen_if_write(struct file *file,"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s" , f,"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " - "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ\n"); + "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");return count; }sprintf (pg_result,"OK: flags=0x%x" , pkt_dev->flags);
@@ -2094,6 +2114,7 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)static inline void set_pkt_overhead (struct pktgen_dev *pkt_dev) { + pkt_dev->pkt_overhead =0 ; pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof (u32); pkt_dev->pkt_overhead +=VLAN_TAG_SIZE (pkt_dev); pkt_dev->pkt_overhead +=SVLAN_TAG_SIZE (pkt_dev);
@@ -2130,6 +2151,31 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)return pkt_dev->curfl; } + +#ifdef CONFIG_XFRM +/* If there was already an IPSEC SA, we keep it as is, else +* we go look for it ... +*/ +inline +void get_ipsec_sa (struct pktgen_dev *pkt_dev,int flow) +{ +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 , + pkt_dev->ipsmode, + pkt_dev->ipsproto,0 ); +if (x) { + pkt_dev->flows[flow].x = x; +set_pkt_overhead (pkt_dev); + pkt_dev->pkt_overhead+=x->props.header_len; + } + + } +} +#endif /* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */
@@ -2289,6 +2335,10 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].flags |=F_INIT ; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr; +#ifdef CONFIG_XFRM +if (pkt_dev->flags &F_IPSEC_ON ) +get_ipsec_sa (pkt_dev, flow); +#endif pkt_dev->nflows++; } }
@@ -2329,6 +2379,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) pkt_dev->flows[flow].count++; } + +#ifdef CONFIG_XFRM +static int pktgen_output_ipsec (struct sk_buff *skb,struct pktgen_dev *pkt_dev) +{ +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int err =0 ; +struct iphdr *iph; + +if (!x) +return 0 ; +/* XXX: we dont support tunnel mode for now until +* we resolve the dst issue */ +if (x->props.mode !=XFRM_MODE_TRANSPORT ) +return 0 ; + +spin_lock (&x->lock); + iph =ip_hdr (skb); + + 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 inline void free_SAs (struct pktgen_dev *pkt_dev) +{ +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 ; + } + } + } +} + +static inline int process_ipsec (struct pktgen_dev *pkt_dev, +struct sk_buff *skb,__be16 protocol) +{ +if (pkt_dev->flags &F_IPSEC_ON ) { +struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; +int nhead =0 ; +if (x) { +int ret; +__u8 *eth; + nhead = x->props.header_len -skb_headroom (skb); +if (nhead >0 ) { + ret =pskb_expand_head (skb, nhead,0 ,GFP_ATOMIC ); +if (ret <0 ) { +printk ("Error expanding ipsec packet %d\n" ,ret); +return 0 ; + } + } + +/* ipsec is not expecting ll header */ +skb_pull (skb,ETH_HLEN ); + ret =pktgen_output_ipsec (skb, pkt_dev); +if (ret) { +printk ("Error creating ipsec packet %d\n" ,ret); +kfree_skb (skb); +return 0 ; + } +/* restore ll */ + eth = (__u8 *)skb_push (skb,ETH_HLEN ); +memcpy (eth, pkt_dev->hh,12 ); + *(u16 *) & eth[12 ] = protocol; + } + } +return 1 ; +} +#endif +static void mpls_push (__be32 *mpls,struct pktgen_dev *pkt_dev) {unsigned i;
@@ -2512,6 +2647,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, pgh->tv_usec =htonl (timestamp.tv_usec); } +#ifdef CONFIG_XFRM +if (!process_ipsec (pkt_dev, skb, protocol)) +return NULL ; +#endif +return skb; }
@@ -3493,11 +3633,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) } pkt_dev->entry->proc_fops = &pktgen_if_fops; pkt_dev->entry->data = pkt_dev; +#ifdef CONFIG_XFRM + pkt_dev->ipsmode =XFRM_MODE_TRANSPORT ; + pkt_dev->ipsproto =IPPROTO_ESP ; +#endif return add_dev_to_thread (t, pkt_dev); out2:dev_put (pkt_dev->odev); out1: +#ifdef CONFIG_XFRM +free_SAs (pkt_dev ); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);
@@ -3592,6 +3739,9 @@ static int pktgen_remove_device(struct pktgen_thread *t,if (pkt_dev->entry)remove_proc_entry (pkt_dev->entry->name, pg_proc_dir); +#ifdef CONFIG_XFRM +free_SAs (pkt_dev); +#endif if (pkt_dev->flows)vfree (pkt_dev->flows);kfree (pkt_dev);
Re: [PATCH] pktgen IPSEC 1/4: Centralize pktgen packet overhead management
In reply to jamalFrom: jamal <[email protected]>
Date: Tue, 12 Jun 2007 08:00:28 -0400
Quoted 8 lines
commit
38477d7ddfa58f58cce99bc902b4c18883647a71Author: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 06:43:00 2007 -0400[PKTGEN] Centralize packet overhead tracking
Track the extra packet overhead for VLAN tags, MPLS, IPSEC etcSigned-off-by Jamal Hadi Salim <[email protected]>
Applied.
Re: [PATCH] pktgen IPSEC 2/4: Introduce pktgen sequential flows
In reply to jamalFrom: jamal <[email protected]>
Date: Tue, 12 Jun 2007 08:01:55 -0400
Quoted 4 lines
commit
882c296bb3f153e1ac770a874c75cfb2bab8481bAuthor: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 07:24:00 2007 -0400
Quoted 8 lines
[PKTGEN] Introduce sequential flows
By default all flows in pktgen are randomly selected. This patch introduces ability to have all defined flows to be sent sequentially. Robert defined randomness to be the default behavior.
Signed-off-by Jamal Hadi Salim <[email protected]>
Applied.
Re: Resend: [PATCH] pktgen IPSEC 3/4: Introduce xfrm SAD only lookup
In reply to jamalFrom: jamal <[email protected]>
Date: Tue, 12 Jun 2007 19:06:03 -0400
Quoted 9 lines
commit
4fe3190756589ef8155eb97fe725f2564f1fc77dAuthor: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 12:35:39 2007 -0400[XFRM] Introduce standalone SAD lookup
This allows other in-kernel functions to do SAD lookups. The only known user at the moment is pktgen.Signed-off-by Jamal Hadi Salim <[email protected]>
Applied.
David Miller
maintainerRe: Resend: [PATCH] pktgen IPSEC 4/4: Add IPSEC support to pktgen
In reply to jamalFrom: jamal <[email protected]>
Date: Tue, 12 Jun 2007 19:08:39 -0400
Quoted 10 lines
commit
bfd389bba7654aa118f0949ff0de45a3bce9700cAuthor: Jamal Hadi Salim <[email protected]> Date: Tue Jun 12 18:59:33 2007 -0400[PKTGEN] IPSEC support
Added transport mode ESP support for starters.
I will send more of these modes and types once i have resolved the tunnel mode isses.Signed-off-by Jamal Hadi Salim <[email protected]>
Also applied, thanks Jamal.