xfrm_device.c 8.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * xfrm_device.c - IPsec device offloading code.
 *
 * Copyright (c) 2015 secunet Security Networks AG
 *
 * Author:
 * Steffen Klassert <steffen.klassert@secunet.com>
 */

#include <linux/errno.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <net/dst.h>
#include <net/xfrm.h>
#include <linux/notifier.h>

21
#ifdef CONFIG_XFRM_OFFLOAD
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
static void __xfrm_transport_prep(struct xfrm_state *x, struct sk_buff *skb,
				  unsigned int hsize)
{
	struct xfrm_offload *xo = xfrm_offload(skb);

	skb_reset_mac_len(skb);
	pskb_pull(skb, skb->mac_len + hsize + x->props.header_len);

	if (xo->flags & XFRM_GSO_SEGMENT) {
		skb_reset_transport_header(skb);
		skb->transport_header -= x->props.header_len;
	}
}

static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
				    unsigned int hsize)

{
	struct xfrm_offload *xo = xfrm_offload(skb);

	if (xo->flags & XFRM_GSO_SEGMENT)
		skb->transport_header = skb->network_header + hsize;

	skb_reset_mac_len(skb);
	pskb_pull(skb, skb->mac_len + x->props.header_len);
}

/* Adjust pointers into the packet when IPsec is done at layer2 */
static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
{
52
	switch (x->outer_mode.encap) {
53
	case XFRM_MODE_TUNNEL:
54
		if (x->outer_mode.family == AF_INET)
55 56
			return __xfrm_mode_tunnel_prep(x, skb,
						       sizeof(struct iphdr));
57
		if (x->outer_mode.family == AF_INET6)
58 59 60 61
			return __xfrm_mode_tunnel_prep(x, skb,
						       sizeof(struct ipv6hdr));
		break;
	case XFRM_MODE_TRANSPORT:
62
		if (x->outer_mode.family == AF_INET)
63 64
			return __xfrm_transport_prep(x, skb,
						     sizeof(struct iphdr));
65
		if (x->outer_mode.family == AF_INET6)
66 67 68 69 70 71 72 73 74 75
			return __xfrm_transport_prep(x, skb,
						     sizeof(struct ipv6hdr));
		break;
	case XFRM_MODE_ROUTEOPTIMIZATION:
	case XFRM_MODE_IN_TRIGGER:
	case XFRM_MODE_BEET:
		break;
	}
}

76
struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
77 78
{
	int err;
79
	unsigned long flags;
80
	struct xfrm_state *x;
81
	struct sk_buff *skb2;
82
	struct softnet_data *sd;
83
	netdev_features_t esp_features = features;
84
	struct xfrm_offload *xo = xfrm_offload(skb);
85
	struct sec_path *sp;
86

87 88
	if (!xo)
		return skb;
89

90 91
	if (!(features & NETIF_F_HW_ESP))
		esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK);
92

93 94
	sp = skb_sec_path(skb);
	x = sp->xvec[sp->len - 1];
95 96 97
	if (xo->flags & XFRM_GRO || x->xso.flags & XFRM_OFFLOAD_INBOUND)
		return skb;

98 99 100 101 102 103 104 105 106 107
	local_irq_save(flags);
	sd = this_cpu_ptr(&softnet_data);
	err = !skb_queue_empty(&sd->xfrm_backlog);
	local_irq_restore(flags);

	if (err) {
		*again = true;
		return skb;
	}

108 109 110
	if (skb_is_gso(skb)) {
		struct net_device *dev = skb->dev;

111
		if (unlikely(x->xso.dev != dev)) {
112 113 114 115 116 117 118 119 120
			struct sk_buff *segs;

			/* Packet got rerouted, fixup features and segment it. */
			esp_features = esp_features & ~(NETIF_F_HW_ESP
							| NETIF_F_GSO_ESP);

			segs = skb_gso_segment(skb, esp_features);
			if (IS_ERR(segs)) {
				kfree_skb(skb);
121
				atomic_long_inc(&dev->tx_dropped);
122 123 124 125 126 127 128 129 130
				return NULL;
			} else {
				consume_skb(skb);
				skb = segs;
			}
		}
	}

	if (!skb->next) {
131
		esp_features |= skb->dev->gso_partial_features;
132
		xfrm_outer_mode_prep(x, skb);
133

134 135
		xo->flags |= XFRM_DEV_RESUME;

136
		err = x->type_offload->xmit(x, skb, esp_features);
137
		if (err) {
138 139 140
			if (err == -EINPROGRESS)
				return NULL;

141
			XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
142 143
			kfree_skb(skb);
			return NULL;
144 145 146
		}

		skb_push(skb, skb->data - skb_mac_header(skb));
147 148

		return skb;
149 150
	}

151 152 153 154
	skb2 = skb;

	do {
		struct sk_buff *nskb = skb2->next;
155 156

		esp_features |= skb->dev->gso_partial_features;
157
		skb_mark_not_on_list(skb2);
158 159

		xo = xfrm_offload(skb2);
160
		xo->flags |= XFRM_DEV_RESUME;
161

162
		xfrm_outer_mode_prep(x, skb2);
163 164

		err = x->type_offload->xmit(x, skb2, esp_features);
165 166 167
		if (!err) {
			skb2->next = nskb;
		} else if (err != -EINPROGRESS) {
168 169 170 171
			XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
			skb2->next = nskb;
			kfree_skb_list(skb2);
			return NULL;
172 173 174 175 176 177
		} else {
			if (skb == skb2)
				skb = nskb;

			if (!skb)
				return NULL;
178

179 180
			goto skip_push;
		}
181 182 183

		skb_push(skb2, skb2->data - skb_mac_header(skb2));

184
skip_push:
185 186 187 188
		skb2 = nskb;
	} while (skb2);

	return skb;
189 190 191
}
EXPORT_SYMBOL_GPL(validate_xmit_xfrm);

192 193 194 195 196 197 198 199 200 201 202
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
		       struct xfrm_user_offload *xuo)
{
	int err;
	struct dst_entry *dst;
	struct net_device *dev;
	struct xfrm_state_offload *xso = &x->xso;
	xfrm_address_t *saddr;
	xfrm_address_t *daddr;

	if (!x->type_offload)
203
		return -EINVAL;
204

205 206
	/* We don't yet support UDP encapsulation and TFC padding. */
	if (x->encap || x->tfcpad)
207
		return -EINVAL;
208 209 210 211 212 213 214 215 216 217 218

	dev = dev_get_by_index(net, xuo->ifindex);
	if (!dev) {
		if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
			saddr = &x->props.saddr;
			daddr = &x->id.daddr;
		} else {
			saddr = &x->id.daddr;
			daddr = &x->props.saddr;
		}

219
		dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
220 221
					x->props.family,
					xfrm_smark_get(0, x));
222 223 224 225 226 227 228 229 230 231
		if (IS_ERR(dst))
			return 0;

		dev = dst->dev;

		dev_hold(dev);
		dst_release(dst);
	}

	if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) {
232
		xso->dev = NULL;
233 234 235 236
		dev_put(dev);
		return 0;
	}

237 238 239 240 241 242 243
	if (x->props.flags & XFRM_STATE_ESN &&
	    !dev->xfrmdev_ops->xdo_dev_state_advance_esn) {
		xso->dev = NULL;
		dev_put(dev);
		return -EINVAL;
	}

244 245 246 247 248 249
	xso->dev = dev;
	xso->num_exthdrs = 1;
	xso->flags = xuo->flags;

	err = dev->xfrmdev_ops->xdo_dev_state_add(x);
	if (err) {
250 251
		xso->num_exthdrs = 0;
		xso->flags = 0;
252
		xso->dev = NULL;
253
		dev_put(dev);
254 255 256

		if (err != -EOPNOTSUPP)
			return err;
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
	}

	return 0;
}
EXPORT_SYMBOL_GPL(xfrm_dev_state_add);

bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
{
	int mtu;
	struct dst_entry *dst = skb_dst(skb);
	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
	struct net_device *dev = x->xso.dev;

	if (!x->type_offload || x->encap)
		return false;

273
	if ((!dev || (dev == xfrm_dst_path(dst)->dev)) &&
274 275
	    (!xdst->child->xfrm)) {
		mtu = xfrm_state_mtu(x, xdst->child_mtu_cached);
276 277 278
		if (skb->len <= mtu)
			goto ok;

279
		if (skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))
280 281 282 283 284 285 286 287 288 289 290 291
			goto ok;
	}

	return false;

ok:
	if (dev && dev->xfrmdev_ops && dev->xfrmdev_ops->xdo_dev_offload_ok)
		return x->xso.dev->xfrmdev_ops->xdo_dev_offload_ok(skb, x);

	return true;
}
EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);
292 293 294 295 296 297 298 299 300 301

void xfrm_dev_resume(struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	int ret = NETDEV_TX_BUSY;
	struct netdev_queue *txq;
	struct softnet_data *sd;
	unsigned long flags;

	rcu_read_lock();
302
	txq = netdev_core_pick_tx(dev, skb, NULL);
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340

	HARD_TX_LOCK(dev, txq, smp_processor_id());
	if (!netif_xmit_frozen_or_stopped(txq))
		skb = dev_hard_start_xmit(skb, dev, txq, &ret);
	HARD_TX_UNLOCK(dev, txq);

	if (!dev_xmit_complete(ret)) {
		local_irq_save(flags);
		sd = this_cpu_ptr(&softnet_data);
		skb_queue_tail(&sd->xfrm_backlog, skb);
		raise_softirq_irqoff(NET_TX_SOFTIRQ);
		local_irq_restore(flags);
	}
	rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(xfrm_dev_resume);

void xfrm_dev_backlog(struct softnet_data *sd)
{
	struct sk_buff_head *xfrm_backlog = &sd->xfrm_backlog;
	struct sk_buff_head list;
	struct sk_buff *skb;

	if (skb_queue_empty(xfrm_backlog))
		return;

	__skb_queue_head_init(&list);

	spin_lock(&xfrm_backlog->lock);
	skb_queue_splice_init(xfrm_backlog, &list);
	spin_unlock(&xfrm_backlog->lock);

	while (!skb_queue_empty(&list)) {
		skb = __skb_dequeue(&list);
		xfrm_dev_resume(skb);
	}

}
341
#endif
342

343
static int xfrm_api_check(struct net_device *dev)
344
{
345
#ifdef CONFIG_XFRM_OFFLOAD
346 347 348 349
	if ((dev->features & NETIF_F_HW_ESP_TX_CSUM) &&
	    !(dev->features & NETIF_F_HW_ESP))
		return NOTIFY_BAD;

350 351 352 353 354 355 356 357 358 359
	if ((dev->features & NETIF_F_HW_ESP) &&
	    (!(dev->xfrmdev_ops &&
	       dev->xfrmdev_ops->xdo_dev_state_add &&
	       dev->xfrmdev_ops->xdo_dev_state_delete)))
		return NOTIFY_BAD;
#else
	if (dev->features & (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM))
		return NOTIFY_BAD;
#endif

360 361 362
	return NOTIFY_DONE;
}

363 364 365 366 367
static int xfrm_dev_register(struct net_device *dev)
{
	return xfrm_api_check(dev);
}

368 369
static int xfrm_dev_feat_change(struct net_device *dev)
{
370
	return xfrm_api_check(dev);
371 372 373 374
}

static int xfrm_dev_down(struct net_device *dev)
{
375
	if (dev->features & NETIF_F_HW_ESP)
376 377 378 379 380
		xfrm_dev_state_flush(dev_net(dev), dev, true);

	return NOTIFY_DONE;
}

381 382 383 384 385
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);

	switch (event) {
386 387 388 389 390 391
	case NETDEV_REGISTER:
		return xfrm_dev_register(dev);

	case NETDEV_FEAT_CHANGE:
		return xfrm_dev_feat_change(dev);

392
	case NETDEV_DOWN:
393
		return xfrm_dev_down(dev);
394 395 396 397 398 399 400 401
	}
	return NOTIFY_DONE;
}

static struct notifier_block xfrm_dev_notifier = {
	.notifier_call	= xfrm_dev_event,
};

402
void __init xfrm_dev_init(void)
403 404 405
{
	register_netdevice_notifier(&xfrm_dev_notifier);
}