History

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 2017-08-21 1) Support RX checksum with IPsec crypto offload for esp4/esp6. From Ilan Tayari. 2) Fixup IPv6 checksums when doing IPsec crypto offload. From Yossi Kuperman. 3) Auto load the xfrom offload modules if a user installs a SA that requests IPsec offload. From Ilan Tayari. 4) Clear RX offload informations in xfrm_input to not confuse the TX path with stale offload informations. From Ilan Tayari. 5) Allow IPsec GSO for local sockets if the crypto operation will be offloaded. 6) Support setting of an output mark to the xfrm_state. This mark can be used to to do the tunnel route lookup. From Lorenzo Colitti. ====================

David S. Miller committed 9 years ago

Commit a43dce92 parents 0c45d7f 077fbac16 files · +121 −37Browse files

Unified · Split

16 files
  1. include/net/xfrm.h +28 −4
  2. include/uapi/linux/xfrm.h +1 −0
  3. net/core/sock.c +1 −1
  4. net/ipv4/esp4.c +11 −3
  5. net/ipv4/esp4_offload.c +4 −1
  6. net/ipv4/xfrm4_policy.c +9 −5
  7. net/ipv6/esp6.c +13 −3
  8. net/ipv6/esp6_offload.c +4 −1
  9. net/ipv6/xfrm6_input.c +3 −1
  10. net/ipv6/xfrm6_policy.c +6 −3
  11. net/xfrm/xfrm_device.c +3 −2
  12. net/xfrm/xfrm_input.c +2 −0
  13. net/xfrm/xfrm_output.c +3 −0
  14. net/xfrm/xfrm_policy.c +9 −8
  15. net/xfrm/xfrm_state.c +12 −4
  16. net/xfrm/xfrm_user.c +12 −1
include/net/xfrm.h+28−4
@@ -43,6 +43,8 @@ · 42 unmodified lines
4343 MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
4444 #define MODULE_ALIAS_XFRM_TYPE(family, proto) \
4545 MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
46+#define MODULE_ALIAS_XFRM_OFFLOAD_TYPE(family, proto) \
47+ MODULE_ALIAS("xfrm-offload-" __stringify(family) "-" __stringify(proto))
4648
4749 #ifdef CONFIG_XFRM_STATISTICS
4850 #define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
@@ -163,6 +165,7 @@ struct xfrm_state { · 114 unmodified lines
163165 int header_len;
164166 int trailer_len;
165167 u32 extra_flags;
168+ u32 output_mark;
166169 } props;
167170
168171 struct xfrm_lifetime_cfg lft;
@@ -296,10 +299,12 @@ struct xfrm_policy_afinfo { · 127 unmodified lines
296299 struct dst_entry *(*dst_lookup)(struct net *net,
297300 int tos, int oif,
298301 const xfrm_address_t *saddr,
299− const xfrm_address_t *daddr);
302+ const xfrm_address_t *daddr,
303+ u32 mark);
300304 int (*get_saddr)(struct net *net, int oif,
301305 xfrm_address_t *saddr,
302− xfrm_address_t *daddr);
306+ xfrm_address_t *daddr,
307+ u32 mark);
303308 void (*decode_session)(struct sk_buff *skb,
304309 struct flowi *fl,
305310 int reverse);
@@ -1558,7 +1563,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); · 1252 unmodified lines
15581563 u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
15591564 int xfrm_init_replay(struct xfrm_state *x);
15601565 int xfrm_state_mtu(struct xfrm_state *x, int mtu);
1561−int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
1566+int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
15621567 int xfrm_init_state(struct xfrm_state *x);
15631568 int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
15641569 int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
@@ -1638,7 +1643,7 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) · 73 unmodified lines
16381643 struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
16391644 const xfrm_address_t *saddr,
16401645 const xfrm_address_t *daddr,
1641− int family);
1646+ int family, u32 mark);
16421647
16431648 struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
16441649
@@ -1856,6 +1861,20 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, · 211 unmodified lines
18561861 struct xfrm_user_offload *xuo);
18571862 bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
18581863
1864+static inline bool xfrm_dst_offload_ok(struct dst_entry *dst)
1865+{
1866+ struct xfrm_state *x = dst->xfrm;
1867+
1868+ if (!x || !x->type_offload)
1869+ return false;
1870+
1871+ if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) &&
1872+ !dst->child->xfrm)
1873+ return true;
1874+
1875+ return false;
1876+}
1877+
18591878 static inline void xfrm_dev_state_delete(struct xfrm_state *x)
18601879 {
18611880 struct xfrm_state_offload *xso = &x->xso;
@@ -1898,6 +1917,11 @@ static inline bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x · 36 unmodified lines
18981917 {
18991918 return false;
19001919 }
1920+
1921+static inline bool xfrm_dst_offload_ok(struct dst_entry *dst)
1922+{
1923+ return false;
1924+}
19011925 #endif
19021926
19031927 static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
include/uapi/linux/xfrm.h+1−0
@@ -304,6 +304,7 @@ enum xfrm_attr_type_t { · 303 unmodified lines
304304 XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
305305 XFRMA_PAD,
306306 XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
307+ XFRMA_OUTPUT_MARK, /* __u32 */
307308 __XFRMA_MAX
308309
309310 #define XFRMA_MAX (__XFRMA_MAX - 1)
net/core/sock.c+1−1
@@ -1776,7 +1776,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) · 1775 unmodified lines
17761776 sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
17771777 sk->sk_route_caps &= ~sk->sk_route_nocaps;
17781778 if (sk_can_gso(sk)) {
1779− if (dst->header_len) {
1779+ if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
17801780 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
17811781 } else {
17821782 sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
net/ipv4/esp4.c+11−3
@@ -510,7 +510,8 @@ int esp_input_done2(struct sk_buff *skb, int err) · 509 unmodified lines
510510 int elen = skb->len - hlen;
511511 int ihl;
512512 u8 nexthdr[2];
513− int padlen;
513+ int padlen, trimlen;
514+ __wsum csumdiff;
514515
515516 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
516517 kfree(ESP_SKB_CB(skb)->tmp);
@@ -568,8 +569,15 @@ int esp_input_done2(struct sk_buff *skb, int err) · 51 unmodified lines
568569 skb->ip_summed = CHECKSUM_UNNECESSARY;
569570 }
570571
571− pskb_trim(skb, skb->len - alen - padlen - 2);
572− __skb_pull(skb, hlen);
572+ trimlen = alen + padlen + 2;
573+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
574+ csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
575+ skb->csum = csum_block_sub(skb->csum, csumdiff,
576+ skb->len - trimlen);
577+ }
578+ pskb_trim(skb, skb->len - trimlen);
579+
580+ skb_pull_rcsum(skb, hlen);
573581 if (x->props.mode == XFRM_MODE_TUNNEL)
574582 skb_reset_transport_header(skb);
575583 else
net/ipv4/esp4_offload.c+4−1
@@ -182,11 +182,13 @@ out: · 181 unmodified lines
182182 static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
183183 {
184184 struct crypto_aead *aead = x->data;
185+ struct xfrm_offload *xo = xfrm_offload(skb);
185186
186187 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
187188 return -EINVAL;
188189
189− skb->ip_summed = CHECKSUM_NONE;
190+ if (!(xo->flags & CRYPTO_DONE))
191+ skb->ip_summed = CHECKSUM_NONE;
190192
191193 return esp_input_done2(skb, 0);
192194 }
@@ -303,3 +305,4 @@ module_init(esp4_offload_init); · 110 unmodified lines
303305 module_exit(esp4_offload_exit);
304306 MODULE_LICENSE("GPL");
305307 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
308+MODULE_ALIAS_XFRM_OFFLOAD_TYPE(AF_INET, XFRM_PROTO_ESP);
net/ipv4/xfrm4_policy.c+9−5
@@ -20,7 +20,8 @@ · 19 unmodified lines
2020 static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
2121 int tos, int oif,
2222 const xfrm_address_t *saddr,
23− const xfrm_address_t *daddr)
23+ const xfrm_address_t *daddr,
24+ u32 mark)
2425 {
2526 struct rtable *rt;
2627
@@ -28,6 +29,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, · 1 unmodified line
2829 fl4->daddr = daddr->a4;
2930 fl4->flowi4_tos = tos;
3031 fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);
32+ fl4->flowi4_mark = mark;
3133 if (saddr)
3234 fl4->saddr = saddr->a4;
3335
@@ -42,20 +44,22 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, · 8 unmodified lines
4244
4345 static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
4446 const xfrm_address_t *saddr,
45− const xfrm_address_t *daddr)
47+ const xfrm_address_t *daddr,
48+ u32 mark)
4649 {
4750 struct flowi4 fl4;
4851
49− return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr);
52+ return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
5053 }
5154
5255 static int xfrm4_get_saddr(struct net *net, int oif,
53− xfrm_address_t *saddr, xfrm_address_t *daddr)
56+ xfrm_address_t *saddr, xfrm_address_t *daddr,
57+ u32 mark)
5458 {
5559 struct dst_entry *dst;
5660 struct flowi4 fl4;
5761
58− dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr);
62+ dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
5963 if (IS_ERR(dst))
6064 return -EHOSTUNREACH;
6165
net/ipv6/esp6.c+13−3
@@ -470,7 +470,8 @@ int esp6_input_done2(struct sk_buff *skb, int err) · 469 unmodified lines
470470 int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
471471 int elen = skb->len - hlen;
472472 int hdr_len = skb_network_header_len(skb);
473− int padlen;
473+ int padlen, trimlen;
474+ __wsum csumdiff;
474475 u8 nexthdr[2];
475476
476477 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
@@ -492,8 +493,17 @@ int esp6_input_done2(struct sk_buff *skb, int err) · 15 unmodified lines
492493
493494 /* ... check padding bits here. Silly. :-) */
494495
495− pskb_trim(skb, skb->len - alen - padlen - 2);
496− __skb_pull(skb, hlen);
496+ trimlen = alen + padlen + 2;
497+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
498+ skb_postpull_rcsum(skb, skb_network_header(skb),
499+ skb_network_header_len(skb));
500+ csumdiff = skb_checksum(skb, skb->len - trimlen, trimlen, 0);
501+ skb->csum = csum_block_sub(skb->csum, csumdiff,
502+ skb->len - trimlen);
503+ }
504+ pskb_trim(skb, skb->len - trimlen);
505+
506+ skb_pull_rcsum(skb, hlen);
497507 if (x->props.mode == XFRM_MODE_TUNNEL)
498508 skb_reset_transport_header(skb);
499509 else
net/ipv6/esp6_offload.c+4−1
@@ -209,11 +209,13 @@ out: · 208 unmodified lines
209209 static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
210210 {
211211 struct crypto_aead *aead = x->data;
212+ struct xfrm_offload *xo = xfrm_offload(skb);
212213
213214 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
214215 return -EINVAL;
215216
216− skb->ip_summed = CHECKSUM_NONE;
217+ if (!(xo->flags & CRYPTO_DONE))
218+ skb->ip_summed = CHECKSUM_NONE;
217219
218220 return esp6_input_done2(skb, 0);
219221 }
@@ -332,3 +334,4 @@ module_init(esp6_offload_init); · 112 unmodified lines
332334 module_exit(esp6_offload_exit);
333335 MODULE_LICENSE("GPL");
334336 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
337+MODULE_ALIAS_XFRM_OFFLOAD_TYPE(AF_INET6, XFRM_PROTO_ESP);
net/ipv6/xfrm6_input.c+3−1
@@ -34,6 +34,7 @@ EXPORT_SYMBOL(xfrm6_rcv_spi); · 33 unmodified lines
3434 int xfrm6_transport_finish(struct sk_buff *skb, int async)
3535 {
3636 struct xfrm_offload *xo = xfrm_offload(skb);
37+ int nhlen = skb->data - skb_network_header(skb);
3738
3839 skb_network_header(skb)[IP6CB(skb)->nhoff] =
3940 XFRM_MODE_SKB_CB(skb)->protocol;
@@ -43,8 +44,9 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) · 3 unmodified lines
4344 return 1;
4445 #endif
4546
46− __skb_push(skb, skb->data - skb_network_header(skb));
47+ __skb_push(skb, nhlen);
4748 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
49+ skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
4850
4951 if (xo && (xo->flags & XFRM_GRO)) {
5052 skb_mac_header_rebuild(skb);
net/ipv6/xfrm6_policy.c+6−3
@@ -27,7 +27,8 @@ · 26 unmodified lines
2727
2828 static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
2929 const xfrm_address_t *saddr,
30− const xfrm_address_t *daddr)
30+ const xfrm_address_t *daddr,
31+ u32 mark)
3132 {
3233 struct flowi6 fl6;
3334 struct dst_entry *dst;
@@ -36,6 +37,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif, · 2 unmodified lines
3637 memset(&fl6, 0, sizeof(fl6));
3738 fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);
3839 fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
40+ fl6.flowi6_mark = mark;
3941 memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
4042 if (saddr)
4143 memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -52,12 +54,13 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif, · 10 unmodified lines
5254 }
5355
5456 static int xfrm6_get_saddr(struct net *net, int oif,
55− xfrm_address_t *saddr, xfrm_address_t *daddr)
57+ xfrm_address_t *saddr, xfrm_address_t *daddr,
58+ u32 mark)
5659 {
5760 struct dst_entry *dst;
5861 struct net_device *dev;
5962
60− dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);
63+ dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
6164 if (IS_ERR(dst))
6265 return -EHOSTUNREACH;
6366
net/xfrm/xfrm_device.c+3−2
@@ -63,7 +63,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, · 62 unmodified lines
6363 xfrm_address_t *daddr;
6464
6565 if (!x->type_offload)
66− return 0;
66+ return -EINVAL;
6767
6868 /* We don't yet support UDP encapsulation, TFC padding and ESN. */
6969 if (x->encap || x->tfcpad || (x->props.flags & XFRM_STATE_ESN))
@@ -79,7 +79,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, · 9 unmodified lines
7979 daddr = &x->props.saddr;
8080 }
8181
82− dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, x->props.family);
82+ dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
83+ x->props.family, x->props.output_mark);
8384 if (IS_ERR(dst))
8485 return 0;
8586
net/xfrm/xfrm_input.c+2−0
@@ -424,6 +424,7 @@ resume: · 423 unmodified lines
424424 nf_reset(skb);
425425
426426 if (decaps) {
427+ skb->sp->olen = 0;
427428 skb_dst_drop(skb);
428429 gro_cells_receive(&gro_cells, skb);
429430 return 0;
@@ -434,6 +435,7 @@ resume: · 4 unmodified lines
434435
435436 err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
436437 if (xfrm_gro) {
438+ skb->sp->olen = 0;
437439 skb_dst_drop(skb);
438440 gro_cells_receive(&gro_cells, skb);
439441 return err;
net/xfrm/xfrm_output.c+3−0
@@ -66,6 +66,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err) · 65 unmodified lines
6666 goto error_nolock;
6767 }
6868
69+ if (x->props.output_mark)
70+ skb->mark = x->props.output_mark;
71+
6972 err = x->outer_mode->output(x, skb);
7073 if (err) {
7174 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
net/xfrm/xfrm_policy.c+9−8
@@ -122,7 +122,7 @@ static const struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short fa · 121 unmodified lines
122122 struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
123123 const xfrm_address_t *saddr,
124124 const xfrm_address_t *daddr,
125− int family)
125+ int family, u32 mark)
126126 {
127127 const struct xfrm_policy_afinfo *afinfo;
128128 struct dst_entry *dst;
@@ -131,7 +131,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif, · 2 unmodified lines
131131 if (unlikely(afinfo == NULL))
132132 return ERR_PTR(-EAFNOSUPPORT);
133133
134− dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);
134+ dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
135135
136136 rcu_read_unlock();
137137
@@ -143,7 +143,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, · 5 unmodified lines
143143 int tos, int oif,
144144 xfrm_address_t *prev_saddr,
145145 xfrm_address_t *prev_daddr,
146− int family)
146+ int family, u32 mark)
147147 {
148148 struct net *net = xs_net(x);
149149 xfrm_address_t *saddr = &x->props.saddr;
@@ -159,7 +159,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, · 9 unmodified lines
159159 daddr = x->coaddr;
160160 }
161161
162− dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);
162+ dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
163163
164164 if (!IS_ERR(dst)) {
165165 if (prev_saddr != saddr)
@@ -1340,14 +1340,14 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) · 1174 unmodified lines
13401340
13411341 static int
13421342 xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
1343− xfrm_address_t *remote, unsigned short family)
1343+ xfrm_address_t *remote, unsigned short family, u32 mark)
13441344 {
13451345 int err;
13461346 const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
13471347
13481348 if (unlikely(afinfo == NULL))
13491349 return -EINVAL;
1350− err = afinfo->get_saddr(net, oif, local, remote);
1350+ err = afinfo->get_saddr(net, oif, local, remote, mark);
13511351 rcu_read_unlock();
13521352 return err;
13531353 }
@@ -1378,7 +1378,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, · 24 unmodified lines
13781378 if (xfrm_addr_any(local, tmpl->encap_family)) {
13791379 error = xfrm_get_saddr(net, fl->flowi_oif,
13801380 &tmp, remote,
1381− tmpl->encap_family);
1381+ tmpl->encap_family, 0);
13821382 if (error)
13831383 goto fail;
13841384 local = &tmp;
@@ -1598,7 +1598,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, · 213 unmodified lines
15981598 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
15991599 family = xfrm[i]->props.family;
16001600 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
1601− &saddr, &daddr, family);
1601+ &saddr, &daddr, family,
1602+ xfrm[i]->props.output_mark);
16021603 err = PTR_ERR(dst);
16031604 if (IS_ERR(dst))
16041605 goto put_states;
net/xfrm/xfrm_state.c+12−4
@@ -296,12 +296,14 @@ int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, · 295 unmodified lines
296296 }
297297 EXPORT_SYMBOL(xfrm_unregister_type_offload);
298298
299−static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned short family)
299+static const struct xfrm_type_offload *
300+xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
300301 {
301302 struct xfrm_state_afinfo *afinfo;
302303 const struct xfrm_type_offload **typemap;
303304 const struct xfrm_type_offload *type;
304305
306+retry:
305307 afinfo = xfrm_state_get_afinfo(family);
306308 if (unlikely(afinfo == NULL))
307309 return NULL;
@@ -311,6 +313,12 @@ static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned · 3 unmodified lines
311313 if ((type && !try_module_get(type->owner)))
312314 type = NULL;
313315
316+ if (!type && try_load) {
317+ request_module("xfrm-offload-%d-%d", family, proto);
318+ try_load = 0;
319+ goto retry;
320+ }
321+
314322 rcu_read_unlock();
315323 return type;
316324 }
@@ -2165,7 +2173,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) · 1848 unmodified lines
21652173 return mtu - x->props.header_len;
21662174 }
21672175
2168−int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
2176+int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
21692177 {
21702178 struct xfrm_state_afinfo *afinfo;
21712179 struct xfrm_mode *inner_mode;
@@ -2230,7 +2238,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay) · 58 unmodified lines
22302238 if (x->type == NULL)
22312239 goto error;
22322240
2233− x->type_offload = xfrm_get_type_offload(x->id.proto, family);
2241+ x->type_offload = xfrm_get_type_offload(x->id.proto, family, offload);
22342242
22352243 err = x->type->init_state(x);
22362244 if (err)
@@ -2258,7 +2266,7 @@ EXPORT_SYMBOL(__xfrm_init_state); · 21 unmodified lines
22582266
22592267 int xfrm_init_state(struct xfrm_state *x)
22602268 {
2261− return __xfrm_init_state(x, true);
2269+ return __xfrm_init_state(x, true, false);
22622270 }
22632271
22642272 EXPORT_SYMBOL(xfrm_init_state);
net/xfrm/xfrm_user.c+12−1
@@ -584,7 +584,10 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, · 583 unmodified lines
584584
585585 xfrm_mark_get(attrs, &x->mark);
586586
587− err = __xfrm_init_state(x, false);
587+ if (attrs[XFRMA_OUTPUT_MARK])
588+ x->props.output_mark = nla_get_u32(attrs[XFRMA_OUTPUT_MARK]);
589+
590+ err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
588591 if (err)
589592 goto error;
590593
@@ -899,6 +902,11 @@ static int copy_to_user_state_extra(struct xfrm_state *x, · 308 unmodified lines
899902 goto out;
900903 if (x->security)
901904 ret = copy_sec_ctx(x->security, skb);
905+ if (x->props.output_mark) {
906+ ret = nla_put_u32(skb, XFRMA_OUTPUT_MARK, x->props.output_mark);
907+ if (ret)
908+ goto out;
909+ }
902910 out:
903911 return ret;
904912 }
@@ -2454,6 +2462,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { · 1549 unmodified lines
24542462 [XFRMA_PROTO] = { .type = NLA_U8 },
24552463 [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },
24562464 [XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) },
2465+ [XFRMA_OUTPUT_MARK] = { .len = NLA_U32 },
24572466 };
24582467
24592468 static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
@@ -2673,6 +2682,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) · 213 unmodified lines
26732682 l += nla_total_size(sizeof(x->props.extra_flags));
26742683 if (x->xso.dev)
26752684 l += nla_total_size(sizeof(x->xso));
2685+ if (x->props.output_mark)
2686+ l += nla_total_size(sizeof(x->props.output_mark));
26762687
26772688 /* Must count x->lastused as it may become non-zero behind our back. */
26782689 l += nla_total_size_64bit(sizeof(u64));