aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-01-14 02:14:25 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-14 02:14:25 -0500
commitaef2b45fe459428d1861a74b08f3f57e87411f56 (patch)
treec2a4438c1b65afd6f805efe274817b9f04270dae /net/core
parent2afe02eed1ac565e5ba90254706e67f670ae41a2 (diff)
parent6bae919003602729d6f5920315bf71ca78bd9e48 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Conflicts: net/xfrm/xfrm_policy.c Steffen Klassert says: ==================== This pull request has a merge conflict between commits be7928d20bab ("net: xfrm: xfrm_policy: fix inline not at beginning of declaration") and da7c224b1baa ("net: xfrm: xfrm_policy: silence compiler warning") from the net-next tree and commit 2f3ea9a95c58 ("xfrm: checkpatch erros with inline keyword position") from the ipsec-next tree. The version from net-next can be used, like it is done in linux-next. 1) Checkpatch cleanups, from Weilong Chen. 2) Fix lockdep complaints when pktgen is used with IPsec, from Fan Du. 3) Update pktgen to allow any combination of IPsec transport/tunnel mode and AH/ESP/IPcomp type, from Fan Du. 4) Make pktgen_dst_metrics static, Fengguang Wu. 5) Compile fix for pktgen when CONFIG_XFRM is not set, from Fan Du. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/pktgen.c80
1 files changed, 66 insertions, 14 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index a797fff7f222..fa3e128eb5e9 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -389,6 +389,9 @@ struct pktgen_dev {
389#ifdef CONFIG_XFRM 389#ifdef CONFIG_XFRM
390 __u8 ipsmode; /* IPSEC mode (config) */ 390 __u8 ipsmode; /* IPSEC mode (config) */
391 __u8 ipsproto; /* IPSEC type (config) */ 391 __u8 ipsproto; /* IPSEC type (config) */
392 __u32 spi;
393 struct dst_entry dst;
394 struct dst_ops dstops;
392#endif 395#endif
393 char result[512]; 396 char result[512];
394}; 397};
@@ -654,8 +657,11 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
654 } 657 }
655 658
656#ifdef CONFIG_XFRM 659#ifdef CONFIG_XFRM
657 if (pkt_dev->flags & F_IPSEC_ON) 660 if (pkt_dev->flags & F_IPSEC_ON) {
658 seq_printf(seq, "IPSEC "); 661 seq_printf(seq, "IPSEC ");
662 if (pkt_dev->spi)
663 seq_printf(seq, "spi:%u", pkt_dev->spi);
664 }
659#endif 665#endif
660 666
661 if (pkt_dev->flags & F_MACSRC_RND) 667 if (pkt_dev->flags & F_MACSRC_RND)
@@ -1476,7 +1482,18 @@ static ssize_t pktgen_if_write(struct file *file,
1476 sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows); 1482 sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);
1477 return count; 1483 return count;
1478 } 1484 }
1485#ifdef CONFIG_XFRM
1486 if (!strcmp(name, "spi")) {
1487 len = num_arg(&user_buffer[i], 10, &value);
1488 if (len < 0)
1489 return len;
1479 1490
1491 i += len;
1492 pkt_dev->spi = value;
1493 sprintf(pg_result, "OK: spi=%u", pkt_dev->spi);
1494 return count;
1495 }
1496#endif
1480 if (!strcmp(name, "flowlen")) { 1497 if (!strcmp(name, "flowlen")) {
1481 len = num_arg(&user_buffer[i], 10, &value); 1498 len = num_arg(&user_buffer[i], 10, &value);
1482 if (len < 0) 1499 if (len < 0)
@@ -2233,13 +2250,21 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
2233 struct xfrm_state *x = pkt_dev->flows[flow].x; 2250 struct xfrm_state *x = pkt_dev->flows[flow].x;
2234 struct pktgen_net *pn = net_generic(dev_net(pkt_dev->odev), pg_net_id); 2251 struct pktgen_net *pn = net_generic(dev_net(pkt_dev->odev), pg_net_id);
2235 if (!x) { 2252 if (!x) {
2236 /*slow path: we dont already have xfrm_state*/ 2253
2237 x = xfrm_stateonly_find(pn->net, DUMMY_MARK, 2254 if (pkt_dev->spi) {
2238 (xfrm_address_t *)&pkt_dev->cur_daddr, 2255 /* We need as quick as possible to find the right SA
2239 (xfrm_address_t *)&pkt_dev->cur_saddr, 2256 * Searching with minimum criteria to archieve this.
2240 AF_INET, 2257 */
2241 pkt_dev->ipsmode, 2258 x = xfrm_state_lookup_byspi(pn->net, htonl(pkt_dev->spi), AF_INET);
2242 pkt_dev->ipsproto, 0); 2259 } else {
2260 /* slow path: we dont already have xfrm_state */
2261 x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
2262 (xfrm_address_t *)&pkt_dev->cur_daddr,
2263 (xfrm_address_t *)&pkt_dev->cur_saddr,
2264 AF_INET,
2265 pkt_dev->ipsmode,
2266 pkt_dev->ipsproto, 0);
2267 }
2243 if (x) { 2268 if (x) {
2244 pkt_dev->flows[flow].x = x; 2269 pkt_dev->flows[flow].x = x;
2245 set_pkt_overhead(pkt_dev); 2270 set_pkt_overhead(pkt_dev);
@@ -2475,31 +2500,47 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
2475 2500
2476 2501
2477#ifdef CONFIG_XFRM 2502#ifdef CONFIG_XFRM
2503static u32 pktgen_dst_metrics[RTAX_MAX + 1] = {
2504
2505 [RTAX_HOPLIMIT] = 0x5, /* Set a static hoplimit */
2506};
2507
2478static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) 2508static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2479{ 2509{
2480 struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; 2510 struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
2481 int err = 0; 2511 int err = 0;
2512 struct net *net = dev_net(pkt_dev->odev);
2482 2513
2483 if (!x) 2514 if (!x)
2484 return 0; 2515 return 0;
2485 /* XXX: we dont support tunnel mode for now until 2516 /* XXX: we dont support tunnel mode for now until
2486 * we resolve the dst issue */ 2517 * we resolve the dst issue */
2487 if (x->props.mode != XFRM_MODE_TRANSPORT) 2518 if ((x->props.mode != XFRM_MODE_TRANSPORT) && (pkt_dev->spi == 0))
2488 return 0; 2519 return 0;
2489 2520
2490 spin_lock(&x->lock); 2521 /* But when user specify an valid SPI, transformation
2522 * supports both transport/tunnel mode + ESP/AH type.
2523 */
2524 if ((x->props.mode == XFRM_MODE_TUNNEL) && (pkt_dev->spi != 0))
2525 skb->_skb_refdst = (unsigned long)&pkt_dev->dst | SKB_DST_NOREF;
2491 2526
2527 rcu_read_lock_bh();
2492 err = x->outer_mode->output(x, skb); 2528 err = x->outer_mode->output(x, skb);
2493 if (err) 2529 rcu_read_unlock_bh();
2530 if (err) {
2531 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
2494 goto error; 2532 goto error;
2533 }
2495 err = x->type->output(x, skb); 2534 err = x->type->output(x, skb);
2496 if (err) 2535 if (err) {
2536 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEPROTOERROR);
2497 goto error; 2537 goto error;
2498 2538 }
2539 spin_lock_bh(&x->lock);
2499 x->curlft.bytes += skb->len; 2540 x->curlft.bytes += skb->len;
2500 x->curlft.packets++; 2541 x->curlft.packets++;
2542 spin_unlock_bh(&x->lock);
2501error: 2543error:
2502 spin_unlock(&x->lock);
2503 return err; 2544 return err;
2504} 2545}
2505 2546
@@ -3542,6 +3583,17 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
3542#ifdef CONFIG_XFRM 3583#ifdef CONFIG_XFRM
3543 pkt_dev->ipsmode = XFRM_MODE_TRANSPORT; 3584 pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
3544 pkt_dev->ipsproto = IPPROTO_ESP; 3585 pkt_dev->ipsproto = IPPROTO_ESP;
3586
3587 /* xfrm tunnel mode needs additional dst to extract outter
3588 * ip header protocol/ttl/id field, here creat a phony one.
3589 * instead of looking for a valid rt, which definitely hurting
3590 * performance under such circumstance.
3591 */
3592 pkt_dev->dstops.family = AF_INET;
3593 pkt_dev->dst.dev = pkt_dev->odev;
3594 dst_init_metrics(&pkt_dev->dst, pktgen_dst_metrics, false);
3595 pkt_dev->dst.child = &pkt_dev->dst;
3596 pkt_dev->dst.ops = &pkt_dev->dstops;
3545#endif 3597#endif
3546 3598
3547 return add_dev_to_thread(t, pkt_dev); 3599 return add_dev_to_thread(t, pkt_dev);