diff options
author | David S. Miller <davem@davemloft.net> | 2018-01-26 10:22:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-26 10:22:53 -0500 |
commit | a81e4affe1789a3d1010f219ad53382a760aa2ea (patch) | |
tree | 73ea99e882beec7435f49b370ef5d8527ac361ef | |
parent | 5b09179e7fa2849a0c95d14bb69416693e0ed0c3 (diff) | |
parent | 50bd870a9e5cca9fcf5fb4c130c373643d7d9906 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says:
====================
pull request (net-next): ipsec-next 2018-01-26
One last patch for this development cycle:
1) Add ESN support for IPSec HW offload.
From Yossef Efraim.
Please pull or let me know if there are problems.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/networking/xfrm_device.txt | 3 | ||||
-rw-r--r-- | include/linux/netdevice.h | 1 | ||||
-rw-r--r-- | include/net/xfrm.h | 12 | ||||
-rw-r--r-- | net/xfrm/xfrm_device.c | 11 | ||||
-rw-r--r-- | net/xfrm/xfrm_replay.c | 2 |
5 files changed, 27 insertions, 2 deletions
diff --git a/Documentation/networking/xfrm_device.txt b/Documentation/networking/xfrm_device.txt index 2d9d588cd34b..50c34ca65efe 100644 --- a/Documentation/networking/xfrm_device.txt +++ b/Documentation/networking/xfrm_device.txt | |||
@@ -41,6 +41,7 @@ struct xfrmdev_ops { | |||
41 | void (*xdo_dev_state_free) (struct xfrm_state *x); | 41 | void (*xdo_dev_state_free) (struct xfrm_state *x); |
42 | bool (*xdo_dev_offload_ok) (struct sk_buff *skb, | 42 | bool (*xdo_dev_offload_ok) (struct sk_buff *skb, |
43 | struct xfrm_state *x); | 43 | struct xfrm_state *x); |
44 | void (*xdo_dev_state_advance_esn) (struct xfrm_state *x); | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | The NIC driver offering ipsec offload will need to implement these | 47 | The NIC driver offering ipsec offload will need to implement these |
@@ -117,6 +118,8 @@ the stack in xfrm_input(). | |||
117 | 118 | ||
118 | hand the packet to napi_gro_receive() as usual | 119 | hand the packet to napi_gro_receive() as usual |
119 | 120 | ||
121 | In ESN mode, xdo_dev_state_advance_esn() is called from xfrm_replay_advance_esn(). | ||
122 | Driver will check packet seq number and update HW ESN state machine if needed. | ||
120 | 123 | ||
121 | When the SA is removed by the user, the driver's xdo_dev_state_delete() | 124 | When the SA is removed by the user, the driver's xdo_dev_state_delete() |
122 | is asked to disable the offload. Later, xdo_dev_state_free() is called | 125 | is asked to disable the offload. Later, xdo_dev_state_free() is called |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 24a62d590350..cd46d3d63aa0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -851,6 +851,7 @@ struct xfrmdev_ops { | |||
851 | void (*xdo_dev_state_free) (struct xfrm_state *x); | 851 | void (*xdo_dev_state_free) (struct xfrm_state *x); |
852 | bool (*xdo_dev_offload_ok) (struct sk_buff *skb, | 852 | bool (*xdo_dev_offload_ok) (struct sk_buff *skb, |
853 | struct xfrm_state *x); | 853 | struct xfrm_state *x); |
854 | void (*xdo_dev_state_advance_esn) (struct xfrm_state *x); | ||
854 | }; | 855 | }; |
855 | #endif | 856 | #endif |
856 | 857 | ||
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 2e6d4fe6b0ba..7d2077665c0b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -1904,6 +1904,14 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, | |||
1904 | struct xfrm_user_offload *xuo); | 1904 | struct xfrm_user_offload *xuo); |
1905 | bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x); | 1905 | bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x); |
1906 | 1906 | ||
1907 | static inline void xfrm_dev_state_advance_esn(struct xfrm_state *x) | ||
1908 | { | ||
1909 | struct xfrm_state_offload *xso = &x->xso; | ||
1910 | |||
1911 | if (xso->dev && xso->dev->xfrmdev_ops->xdo_dev_state_advance_esn) | ||
1912 | xso->dev->xfrmdev_ops->xdo_dev_state_advance_esn(x); | ||
1913 | } | ||
1914 | |||
1907 | static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) | 1915 | static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) |
1908 | { | 1916 | { |
1909 | struct xfrm_state *x = dst->xfrm; | 1917 | struct xfrm_state *x = dst->xfrm; |
@@ -1974,6 +1982,10 @@ static inline bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x | |||
1974 | return false; | 1982 | return false; |
1975 | } | 1983 | } |
1976 | 1984 | ||
1985 | static inline void xfrm_dev_state_advance_esn(struct xfrm_state *x) | ||
1986 | { | ||
1987 | } | ||
1988 | |||
1977 | static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) | 1989 | static inline bool xfrm_dst_offload_ok(struct dst_entry *dst) |
1978 | { | 1990 | { |
1979 | return false; | 1991 | return false; |
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 92b4648e75ca..8e70291e586a 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c | |||
@@ -147,8 +147,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, | |||
147 | if (!x->type_offload) | 147 | if (!x->type_offload) |
148 | return -EINVAL; | 148 | return -EINVAL; |
149 | 149 | ||
150 | /* We don't yet support UDP encapsulation, TFC padding and ESN. */ | 150 | /* We don't yet support UDP encapsulation and TFC padding. */ |
151 | if (x->encap || x->tfcpad || (x->props.flags & XFRM_STATE_ESN)) | 151 | if (x->encap || x->tfcpad) |
152 | return -EINVAL; | 152 | return -EINVAL; |
153 | 153 | ||
154 | dev = dev_get_by_index(net, xuo->ifindex); | 154 | dev = dev_get_by_index(net, xuo->ifindex); |
@@ -178,6 +178,13 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, | |||
178 | return 0; | 178 | return 0; |
179 | } | 179 | } |
180 | 180 | ||
181 | if (x->props.flags & XFRM_STATE_ESN && | ||
182 | !dev->xfrmdev_ops->xdo_dev_state_advance_esn) { | ||
183 | xso->dev = NULL; | ||
184 | dev_put(dev); | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
181 | xso->dev = dev; | 188 | xso->dev = dev; |
182 | xso->num_exthdrs = 1; | 189 | xso->num_exthdrs = 1; |
183 | xso->flags = xuo->flags; | 190 | xso->flags = xuo->flags; |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 02501817227b..1d38c6acf8af 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -551,6 +551,8 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) | |||
551 | bitnr = replay_esn->replay_window - (diff - pos); | 551 | bitnr = replay_esn->replay_window - (diff - pos); |
552 | } | 552 | } |
553 | 553 | ||
554 | xfrm_dev_state_advance_esn(x); | ||
555 | |||
554 | nr = bitnr >> 5; | 556 | nr = bitnr >> 5; |
555 | bitnr = bitnr & 0x1F; | 557 | bitnr = bitnr & 0x1F; |
556 | replay_esn->bmp[nr] |= (1U << bitnr); | 558 | replay_esn->bmp[nr] |= (1U << bitnr); |