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

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


Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2017-04-20

This adds the basic infrastructure for IPsec hardware
offloading, it creates a configuration API and adjusts
the packet path.

1) Add the needed netdev features to configure IPsec offloads.

2) Add the IPsec hardware offloading API.

3) Prepare the ESP packet path for hardware offloading.

4) Add gso handlers for esp4 and esp6, this implements
   the software fallback for GSO packets.

5) Add xfrm replay handler functions for offloading.

6) Change ESP to use a synchronous crypto algorithm on
   offloading, we don't have the option for asynchronous
   returns when we handle IPsec at layer2.

7) Add a xfrm validate function to validate_xmit_skb. This
   implements the software fallback for non GSO packets.

8) Set the inner_network and inner_transport members of
   the SKB, as well as encapsulation, to reflect the actual
   positions of these headers, and removes them only once
   encryption is done on the payload.
   From Ilan Tayari.

9) Prepare the ESP GRO codepath for hardware offloading.

10) Fix incorrect null pointer check in esp6.
    From Colin Ian King.

11) Fix for the GSO software fallback path to detect the
    fallback correctly.
    From Ilan Tayari.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 77999328 8f92e03e
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -54,8 +54,9 @@ enum {
					 */
	NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
	NETIF_F_GSO_SCTP_BIT,		/* ... SCTP fragmentation */
	NETIF_F_GSO_ESP_BIT,		/* ... ESP with TSO */
	/**/NETIF_F_GSO_LAST =		/* last bit, see GSO_MASK */
		NETIF_F_GSO_SCTP_BIT,
		NETIF_F_GSO_ESP_BIT,

	NETIF_F_FCOE_CRC_BIT,		/* FCoE CRC32 */
	NETIF_F_SCTP_CRC_BIT,		/* SCTP checksum offload */
@@ -73,6 +74,8 @@ enum {
	NETIF_F_HW_L2FW_DOFFLOAD_BIT,	/* Allow L2 Forwarding in Hardware */

	NETIF_F_HW_TC_BIT,		/* Offload TC infrastructure */
	NETIF_F_HW_ESP_BIT,		/* Hardware ESP transformation offload */
	NETIF_F_HW_ESP_TX_CSUM_BIT,	/* ESP with TX checksum offload */

	/*
	 * Add your fresh new feature above and remember to update
@@ -129,11 +132,14 @@ enum {
#define NETIF_F_GSO_PARTIAL	 __NETIF_F(GSO_PARTIAL)
#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
#define NETIF_F_GSO_SCTP	__NETIF_F(GSO_SCTP)
#define NETIF_F_GSO_ESP		__NETIF_F(GSO_ESP)
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
#define NETIF_F_HW_VLAN_STAG_RX	__NETIF_F(HW_VLAN_STAG_RX)
#define NETIF_F_HW_VLAN_STAG_TX	__NETIF_F(HW_VLAN_STAG_TX)
#define NETIF_F_HW_L2FW_DOFFLOAD	__NETIF_F(HW_L2FW_DOFFLOAD)
#define NETIF_F_HW_TC		__NETIF_F(HW_TC)
#define NETIF_F_HW_ESP		__NETIF_F(HW_ESP)
#define NETIF_F_HW_ESP_TX_CSUM	__NETIF_F(HW_ESP_TX_CSUM)

#define for_each_netdev_feature(mask_addr, bit)	\
	for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
+15 −0
Original line number Diff line number Diff line
@@ -823,6 +823,16 @@ struct netdev_xdp {
	};
};

#ifdef CONFIG_XFRM_OFFLOAD
struct xfrmdev_ops {
	int	(*xdo_dev_state_add) (struct xfrm_state *x);
	void	(*xdo_dev_state_delete) (struct xfrm_state *x);
	void	(*xdo_dev_state_free) (struct xfrm_state *x);
	bool	(*xdo_dev_offload_ok) (struct sk_buff *skb,
				       struct xfrm_state *x);
};
#endif

/*
 * This structure defines the management hooks for network devices.
 * The following hooks can be defined; unless noted otherwise, they are
@@ -1696,6 +1706,10 @@ struct net_device {
	const struct ndisc_ops *ndisc_ops;
#endif

#ifdef CONFIG_XFRM
	const struct xfrmdev_ops *xfrmdev_ops;
#endif

	const struct header_ops *header_ops;

	unsigned int		flags;
@@ -4070,6 +4084,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
	BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
	BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
	BUILD_BUG_ON(SKB_GSO_SCTP    != (NETIF_F_GSO_SCTP >> NETIF_F_GSO_SHIFT));
	BUILD_BUG_ON(SKB_GSO_ESP != (NETIF_F_GSO_ESP >> NETIF_F_GSO_SHIFT));

	return (features & feature) == feature;
}
+2 −0
Original line number Diff line number Diff line
@@ -492,6 +492,8 @@ enum {
	SKB_GSO_TUNNEL_REMCSUM = 1 << 14,

	SKB_GSO_SCTP = 1 << 15,

	SKB_GSO_ESP = 1 << 16,
};

#if BITS_PER_LONG > 32
+19 −0
Original line number Diff line number Diff line
@@ -10,4 +10,23 @@ static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
	return (struct ip_esp_hdr *)skb_transport_header(skb);
}

struct esp_info {
	struct	ip_esp_hdr *esph;
	__be64	seqno;
	int	tfclen;
	int	tailen;
	int	plen;
	int	clen;
	int 	len;
	int 	nfrags;
	__u8	proto;
	bool	inplace;
};

int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp_input_done2(struct sk_buff *skb, int err);
int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp);
int esp6_input_done2(struct sk_buff *skb, int err);
#endif
+102 −6
Original line number Diff line number Diff line
@@ -120,6 +120,13 @@ struct xfrm_state_walk {
	struct xfrm_address_filter *filter;
};

struct xfrm_state_offload {
	struct net_device	*dev;
	unsigned long		offload_handle;
	unsigned int		num_exthdrs;
	u8			flags;
};

/* Full description of state of transformer. */
struct xfrm_state {
	possible_net_t		xs_net;
@@ -207,6 +214,8 @@ struct xfrm_state {
	struct xfrm_lifetime_cur curlft;
	struct tasklet_hrtimer	mtimer;

	struct xfrm_state_offload xso;

	/* used to fix curlft->add_time when changing date */
	long		saved_tmo;

@@ -222,6 +231,8 @@ struct xfrm_state {
	struct xfrm_mode	*inner_mode_iaf;
	struct xfrm_mode	*outer_mode;

	const struct xfrm_type_offload	*type_offload;

	/* Security context */
	struct xfrm_sec_ctx	*security;

@@ -319,7 +330,9 @@ struct xfrm_state_afinfo {
	__be16				eth_proto;
	struct module			*owner;
	const struct xfrm_type		*type_map[IPPROTO_MAX];
	const struct xfrm_type_offload	*type_offload_map[IPPROTO_MAX];
	struct xfrm_mode		*mode_map[XFRM_MODE_MAX];

	int			(*init_flags)(struct xfrm_state *x);
	void			(*init_tempsel)(struct xfrm_selector *sel,
						const struct flowi *fl);
@@ -380,6 +393,18 @@ struct xfrm_type {
int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);

struct xfrm_type_offload {
	char		*description;
	struct module	*owner;
	u8		proto;
	void		(*encap)(struct xfrm_state *, struct sk_buff *pskb);
	int		(*input_tail)(struct xfrm_state *x, struct sk_buff *skb);
	int		(*xmit)(struct xfrm_state *, struct sk_buff *pskb, netdev_features_t features);
};

int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family);
int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);

struct xfrm_mode {
	/*
	 * Remove encapsulation header.
@@ -428,6 +453,16 @@ struct xfrm_mode {
	 */
	int (*output)(struct xfrm_state *x, struct sk_buff *skb);

	/*
	 * Adjust pointers into the packet and do GSO segmentation.
	 */
	struct sk_buff *(*gso_segment)(struct xfrm_state *x, struct sk_buff *skb, netdev_features_t features);

	/*
	 * Adjust pointers into the packet when IPsec is done at layer2.
	 */
	void (*xmit)(struct xfrm_state *x, struct sk_buff *skb);

	struct xfrm_state_afinfo *afinfo;
	struct module *owner;
	unsigned int encap;
@@ -1532,6 +1567,7 @@ struct xfrmk_spdinfo {
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
int xfrm_state_delete(struct xfrm_state *x);
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
@@ -1614,6 +1650,11 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
}
#endif

struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
				    const xfrm_address_t *saddr,
				    const xfrm_address_t *daddr,
				    int family);

struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);

void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
@@ -1819,6 +1860,61 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
}
#endif

#ifdef CONFIG_XFRM_OFFLOAD
void __net_init xfrm_dev_init(void);
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
		       struct xfrm_user_offload *xuo);
bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);

static inline void xfrm_dev_state_delete(struct xfrm_state *x)
{
	struct xfrm_state_offload *xso = &x->xso;

	if (xso->dev)
		xso->dev->xfrmdev_ops->xdo_dev_state_delete(x);
}

static inline void xfrm_dev_state_free(struct xfrm_state *x)
{
	struct xfrm_state_offload *xso = &x->xso;
	 struct net_device *dev = xso->dev;

	if (dev && dev->xfrmdev_ops) {
		dev->xfrmdev_ops->xdo_dev_state_free(x);
		xso->dev = NULL;
		dev_put(dev);
	}
}
#else
static inline void __net_init xfrm_dev_init(void)
{
}

static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
{
	return 0;
}

static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo)
{
	return 0;
}

static inline void xfrm_dev_state_delete(struct xfrm_state *x)
{
}

static inline void xfrm_dev_state_free(struct xfrm_state *x)
{
}

static inline bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
{
	return false;
}
#endif

static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
{
	if (attrs[XFRMA_MARK])
Loading