Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aef2b45f authored by David S. Miller's avatar David S. Miller
Browse files


Conflicts:
	net/xfrm/xfrm_policy.c

Steffen Klassert says:

====================
This pull request has a merge conflict between commits be7928d2
("net: xfrm: xfrm_policy: fix inline not at beginning of declaration") and
da7c224b ("net: xfrm: xfrm_policy: silence compiler warning") from
the net-next tree and commit 2f3ea9a9 ("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: default avatarDavid S. Miller <davem@davemloft.net>
parents 2afe02ee 6bae9190
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -108,7 +108,9 @@ Examples:
                              MPLS_RND, VID_RND, SVID_RND
                              QUEUE_MAP_RND # queue map random
                              QUEUE_MAP_CPU # queue map mirrors smp_processor_id()
                              IPSEC # Make IPsec encapsulation for packet

 pgset spi SPI_VALUE     Set specific SA used to transform packet.

 pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
                         cycle through the port range.
@@ -177,6 +179,18 @@ Note when adding devices to a specific CPU there good idea to also assign
/proc/irq/XX/smp_affinity so the TX-interrupts gets bound to the same CPU.
as this reduces cache bouncing when freeing skb's.

Enable IPsec
============
Default IPsec transformation with ESP encapsulation plus Transport mode
could be enabled by simply setting:

pgset "flag IPSEC"
pgset "flows 1"

To avoid breaking existing testbed scripts for using AH type and tunnel mode,
user could use "pgset spi SPI_VALUE" to specify which formal of transformation
to employ.


Current commands and configuration options
==========================================
@@ -225,6 +239,7 @@ flag
  UDPDST_RND
  MACSRC_RND
  MACDST_RND
  IPSEC

dst_min
dst_max
+2 −0
Original line number Diff line number Diff line
@@ -1421,6 +1421,8 @@ struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
				       xfrm_address_t *saddr,
				       unsigned short family,
				       u8 mode, u8 proto, u32 reqid);
struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
					      unsigned short family);
int xfrm_state_check_expire(struct xfrm_state *x);
void xfrm_state_insert(struct xfrm_state *x);
int xfrm_state_add(struct xfrm_state *x);
+66 −14
Original line number Diff line number Diff line
@@ -389,6 +389,9 @@ struct pktgen_dev {
#ifdef CONFIG_XFRM
	__u8	ipsmode;		/* IPSEC mode (config) */
	__u8	ipsproto;		/* IPSEC type (config) */
	__u32	spi;
	struct dst_entry dst;
	struct dst_ops dstops;
#endif
	char result[512];
};
@@ -654,8 +657,11 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
	}

#ifdef CONFIG_XFRM
	if (pkt_dev->flags & F_IPSEC_ON)
	if (pkt_dev->flags & F_IPSEC_ON) {
		seq_printf(seq,  "IPSEC  ");
		if (pkt_dev->spi)
			seq_printf(seq, "spi:%u", pkt_dev->spi);
	}
#endif

	if (pkt_dev->flags & F_MACSRC_RND)
@@ -1476,7 +1482,18 @@ static ssize_t pktgen_if_write(struct file *file,
		sprintf(pg_result, "OK: flows=%u", pkt_dev->cflows);
		return count;
	}
#ifdef CONFIG_XFRM
	if (!strcmp(name, "spi")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
			return len;

		i += len;
		pkt_dev->spi = value;
		sprintf(pg_result, "OK: spi=%u", pkt_dev->spi);
		return count;
	}
#endif
	if (!strcmp(name, "flowlen")) {
		len = num_arg(&user_buffer[i], 10, &value);
		if (len < 0)
@@ -2233,6 +2250,13 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
	struct xfrm_state *x = pkt_dev->flows[flow].x;
	struct pktgen_net *pn = net_generic(dev_net(pkt_dev->odev), pg_net_id);
	if (!x) {

		if (pkt_dev->spi) {
			/* We need as quick as possible to find the right SA
			 * Searching with minimum criteria to archieve this.
			 */
			x = xfrm_state_lookup_byspi(pn->net, htonl(pkt_dev->spi), AF_INET);
		} else {
			/* slow path: we dont already have xfrm_state */
			x = xfrm_stateonly_find(pn->net, DUMMY_MARK,
						(xfrm_address_t *)&pkt_dev->cur_daddr,
@@ -2240,6 +2264,7 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
						AF_INET,
						pkt_dev->ipsmode,
						pkt_dev->ipsproto, 0);
		}
		if (x) {
			pkt_dev->flows[flow].x = x;
			set_pkt_overhead(pkt_dev);
@@ -2475,31 +2500,47 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)


#ifdef CONFIG_XFRM
static u32 pktgen_dst_metrics[RTAX_MAX + 1] = {

	[RTAX_HOPLIMIT] = 0x5, /* Set a static hoplimit */
};

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 net *net = dev_net(pkt_dev->odev);

	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)
	if ((x->props.mode != XFRM_MODE_TRANSPORT) && (pkt_dev->spi == 0))
		return 0;

	spin_lock(&x->lock);
	/* But when user specify an valid SPI, transformation
	 * supports both transport/tunnel mode + ESP/AH type.
	 */
	if ((x->props.mode == XFRM_MODE_TUNNEL) && (pkt_dev->spi != 0))
		skb->_skb_refdst = (unsigned long)&pkt_dev->dst | SKB_DST_NOREF;

	rcu_read_lock_bh();
	err = x->outer_mode->output(x, skb);
	if (err)
	rcu_read_unlock_bh();
	if (err) {
		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
		goto error;
	}
	err = x->type->output(x, skb);
	if (err)
	if (err) {
		XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEPROTOERROR);
		goto error;

	}
	spin_lock_bh(&x->lock);
	x->curlft.bytes += skb->len;
	x->curlft.packets++;
	spin_unlock_bh(&x->lock);
error:
	spin_unlock(&x->lock);
	return err;
}

@@ -3542,6 +3583,17 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
#ifdef CONFIG_XFRM
	pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
	pkt_dev->ipsproto = IPPROTO_ESP;

	/* xfrm tunnel mode needs additional dst to extract outter
	 * ip header protocol/ttl/id field, here creat a phony one.
	 * instead of looking for a valid rt, which definitely hurting
	 * performance under such circumstance.
	 */
	pkt_dev->dstops.family = AF_INET;
	pkt_dev->dst.dev = pkt_dev->odev;
	dst_init_metrics(&pkt_dev->dst, pktgen_dst_metrics, false);
	pkt_dev->dst.child = &pkt_dev->dst;
	pkt_dev->dst.ops = &pkt_dev->dstops;
#endif

	return add_dev_to_thread(t, pkt_dev);
+16 −16
Original line number Diff line number Diff line
@@ -1316,9 +1316,9 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
			error = (x->km.state == XFRM_STATE_ERROR ?
				 -EINVAL : -EAGAIN);
			xfrm_state_put(x);
		}
		else if (error == -ESRCH)
		} else if (error == -ESRCH) {
			error = -EAGAIN;
		}

		if (!tmpl->optional)
			goto fail;
+33 −11
Original line number Diff line number Diff line
@@ -890,7 +890,7 @@ xfrm_stateonly_find(struct net *net, u32 mark,
	unsigned int h;
	struct xfrm_state *rx = NULL, *x = NULL;

	spin_lock(&net->xfrm.xfrm_state_lock);
	spin_lock_bh(&net->xfrm.xfrm_state_lock);
	h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
	hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
		if (x->props.family == family &&
@@ -908,13 +908,35 @@ xfrm_stateonly_find(struct net *net, u32 mark,

	if (rx)
		xfrm_state_hold(rx);
	spin_unlock(&net->xfrm.xfrm_state_lock);
	spin_unlock_bh(&net->xfrm.xfrm_state_lock);


	return rx;
}
EXPORT_SYMBOL(xfrm_stateonly_find);

struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
					      unsigned short family)
{
	struct xfrm_state *x;
	struct xfrm_state_walk *w;

	spin_lock_bh(&net->xfrm.xfrm_state_lock);
	list_for_each_entry(w, &net->xfrm.state_all, all) {
		x = container_of(w, struct xfrm_state, km);
		if (x->props.family != family ||
			x->id.spi != spi)
			continue;

		spin_unlock_bh(&net->xfrm.xfrm_state_lock);
		xfrm_state_hold(x);
		return x;
	}
	spin_unlock_bh(&net->xfrm.xfrm_state_lock);
	return NULL;
}
EXPORT_SYMBOL(xfrm_state_lookup_byspi);

static void __xfrm_state_insert(struct xfrm_state *x)
{
	struct net *net = xs_net(x);
+3 −3

File changed.

Contains only whitespace changes.

+3 −3

File changed.

Contains only whitespace changes.

+1 −1

File changed.

Contains only whitespace changes.

Loading