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
43 MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))43 MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
44#define MODULE_ALIAS_XFRM_TYPE(family, proto) \44#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
45 MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))45 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))
46 48
47#ifdef CONFIG_XFRM_STATISTICS49#ifdef CONFIG_XFRM_STATISTICS
48#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)50#define XFRM_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.xfrm_statistics, field)
@@ -163,6 +165,7 @@ struct xfrm_state { · 114 unmodified lines
163 int header_len;165 int header_len;
164 int trailer_len;166 int trailer_len;
165 u32 extra_flags;167 u32 extra_flags;
168 u32 output_mark;
166 } props;169 } props;
167 170
168 struct xfrm_lifetime_cfg lft;171 struct xfrm_lifetime_cfg lft;
@@ -296,10 +299,12 @@ struct xfrm_policy_afinfo { · 127 unmodified lines
296 struct dst_entry *(*dst_lookup)(struct net *net,299 struct dst_entry *(*dst_lookup)(struct net *net,
297 int tos, int oif,300 int tos, int oif,
298 const xfrm_address_t *saddr,301 const xfrm_address_t *saddr,
299 const xfrm_address_t *daddr);302 const xfrm_address_t *daddr,
303 u32 mark);
300 int (*get_saddr)(struct net *net, int oif,304 int (*get_saddr)(struct net *net, int oif,
301 xfrm_address_t *saddr,305 xfrm_address_t *saddr,
302 xfrm_address_t *daddr);306 xfrm_address_t *daddr,
307 u32 mark);
303 void (*decode_session)(struct sk_buff *skb,308 void (*decode_session)(struct sk_buff *skb,
304 struct flowi *fl,309 struct flowi *fl,
305 int reverse);310 int reverse);
@@ -1558,7 +1563,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); · 1252 unmodified lines
1558u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);1563u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
1559int xfrm_init_replay(struct xfrm_state *x);1564int xfrm_init_replay(struct xfrm_state *x);
1560int xfrm_state_mtu(struct xfrm_state *x, int mtu);1565int xfrm_state_mtu(struct xfrm_state *x, int mtu);
1561int __xfrm_init_state(struct xfrm_state *x, bool init_replay);1566int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
1562int xfrm_init_state(struct xfrm_state *x);1567int xfrm_init_state(struct xfrm_state *x);
1563int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);1568int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
1564int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);1569int 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
1638struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,1643struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
1639 const xfrm_address_t *saddr,1644 const xfrm_address_t *saddr,
1640 const xfrm_address_t *daddr,1645 const xfrm_address_t *daddr,
1641 int family);1646 int family, u32 mark);
1642 1647
1643struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);1648struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
1644 1649
@@ -1856,6 +1861,20 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, · 211 unmodified lines
1856 struct xfrm_user_offload *xuo);1861 struct xfrm_user_offload *xuo);
1857bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);1862bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
1858 1863
1864static 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
1859static inline void xfrm_dev_state_delete(struct xfrm_state *x)1878static inline void xfrm_dev_state_delete(struct xfrm_state *x)
1860{1879{
1861 struct xfrm_state_offload *xso = &x->xso;1880 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
1898{1917{
1899 return false;1918 return false;
1900}1919}
1920
1921static inline bool xfrm_dst_offload_ok(struct dst_entry *dst)
1922{
1923 return false;
1924}
1901#endif1925#endif
1902 1926
1903static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)1927static 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
304 XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */304 XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
305 XFRMA_PAD,305 XFRMA_PAD,
306 XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */306 XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
307 XFRMA_OUTPUT_MARK, /* __u32 */
307 __XFRMA_MAX308 __XFRMA_MAX
308 309
309#define XFRMA_MAX (__XFRMA_MAX - 1)310#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
1776 sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;1776 sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
1777 sk->sk_route_caps &= ~sk->sk_route_nocaps;1777 sk->sk_route_caps &= ~sk->sk_route_nocaps;
1778 if (sk_can_gso(sk)) {1778 if (sk_can_gso(sk)) {
1779 if (dst->header_len) {1779 if (dst->header_len && !xfrm_dst_offload_ok(dst)) {
1780 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;1780 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
1781 } else {1781 } else {
1782 sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;1782 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
510 int elen = skb->len - hlen;510 int elen = skb->len - hlen;
511 int ihl;511 int ihl;
512 u8 nexthdr[2];512 u8 nexthdr[2];
513 int padlen;513 int padlen, trimlen;
514 __wsum csumdiff;
514 515
515 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))516 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
516 kfree(ESP_SKB_CB(skb)->tmp);517 kfree(ESP_SKB_CB(skb)->tmp);
@@ -568,8 +569,15 @@ int esp_input_done2(struct sk_buff *skb, int err) · 51 unmodified lines
568 skb->ip_summed = CHECKSUM_UNNECESSARY;569 skb->ip_summed = CHECKSUM_UNNECESSARY;
569 }570 }
570 571
571 pskb_trim(skb, skb->len - alen - padlen - 2);572 trimlen = alen + padlen + 2;
572 __skb_pull(skb, hlen);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);
573 if (x->props.mode == XFRM_MODE_TUNNEL)581 if (x->props.mode == XFRM_MODE_TUNNEL)
574 skb_reset_transport_header(skb);582 skb_reset_transport_header(skb);
575 else583 else
net/ipv4/esp4_offload.c+4−1
@@ -182,11 +182,13 @@ out: · 181 unmodified lines
182static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)182static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
183{183{
184 struct crypto_aead *aead = x->data;184 struct crypto_aead *aead = x->data;
185 struct xfrm_offload *xo = xfrm_offload(skb);
185 186
186 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))187 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
187 return -EINVAL;188 return -EINVAL;
188 189
189 skb->ip_summed = CHECKSUM_NONE;190 if (!(xo->flags & CRYPTO_DONE))
191 skb->ip_summed = CHECKSUM_NONE;
190 192
191 return esp_input_done2(skb, 0);193 return esp_input_done2(skb, 0);
192}194}
@@ -303,3 +305,4 @@ module_init(esp4_offload_init); · 110 unmodified lines
303module_exit(esp4_offload_exit);305module_exit(esp4_offload_exit);
304MODULE_LICENSE("GPL");306MODULE_LICENSE("GPL");
305MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");307MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
308MODULE_ALIAS_XFRM_OFFLOAD_TYPE(AF_INET, XFRM_PROTO_ESP);
net/ipv4/xfrm4_policy.c+9−5
@@ -20,7 +20,8 @@ · 19 unmodified lines
20static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,20static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
21 int tos, int oif,21 int tos, int oif,
22 const xfrm_address_t *saddr,22 const xfrm_address_t *saddr,
23 const xfrm_address_t *daddr)23 const xfrm_address_t *daddr,
24 u32 mark)
24{25{
25 struct rtable *rt;26 struct rtable *rt;
26 27
@@ -28,6 +29,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, · 1 unmodified line
28 fl4->daddr = daddr->a4;29 fl4->daddr = daddr->a4;
29 fl4->flowi4_tos = tos;30 fl4->flowi4_tos = tos;
30 fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);31 fl4->flowi4_oif = l3mdev_master_ifindex_by_index(net, oif);
32 fl4->flowi4_mark = mark;
31 if (saddr)33 if (saddr)
32 fl4->saddr = saddr->a4;34 fl4->saddr = saddr->a4;
33 35
@@ -42,20 +44,22 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, · 8 unmodified lines
42 44
43static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,45static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
44 const xfrm_address_t *saddr,46 const xfrm_address_t *saddr,
45 const xfrm_address_t *daddr)47 const xfrm_address_t *daddr,
48 u32 mark)
46{49{
47 struct flowi4 fl4;50 struct flowi4 fl4;
48 51
49 return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr);52 return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
50}53}
51 54
52static int xfrm4_get_saddr(struct net *net, int oif,55static 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)
54{58{
55 struct dst_entry *dst;59 struct dst_entry *dst;
56 struct flowi4 fl4;60 struct flowi4 fl4;
57 61
58 dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr);62 dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
59 if (IS_ERR(dst))63 if (IS_ERR(dst))
60 return -EHOSTUNREACH;64 return -EHOSTUNREACH;
61 65
net/ipv6/esp6.c+13−3
@@ -470,7 +470,8 @@ int esp6_input_done2(struct sk_buff *skb, int err) · 469 unmodified lines
470 int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);470 int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
471 int elen = skb->len - hlen;471 int elen = skb->len - hlen;
472 int hdr_len = skb_network_header_len(skb);472 int hdr_len = skb_network_header_len(skb);
473 int padlen;473 int padlen, trimlen;
474 __wsum csumdiff;
474 u8 nexthdr[2];475 u8 nexthdr[2];
475 476
476 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))477 if (!xo || (xo && !(xo->flags & CRYPTO_DONE)))
@@ -492,8 +493,17 @@ int esp6_input_done2(struct sk_buff *skb, int err) · 15 unmodified lines
492 493
493 /* ... check padding bits here. Silly. :-) */494 /* ... check padding bits here. Silly. :-) */
494 495
495 pskb_trim(skb, skb->len - alen - padlen - 2);496 trimlen = alen + padlen + 2;
496 __skb_pull(skb, hlen);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);
497 if (x->props.mode == XFRM_MODE_TUNNEL)507 if (x->props.mode == XFRM_MODE_TUNNEL)
498 skb_reset_transport_header(skb);508 skb_reset_transport_header(skb);
499 else509 else
net/ipv6/esp6_offload.c+4−1
@@ -209,11 +209,13 @@ out: · 208 unmodified lines
209static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)209static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
210{210{
211 struct crypto_aead *aead = x->data;211 struct crypto_aead *aead = x->data;
212 struct xfrm_offload *xo = xfrm_offload(skb);
212 213
213 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))214 if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead)))
214 return -EINVAL;215 return -EINVAL;
215 216
216 skb->ip_summed = CHECKSUM_NONE;217 if (!(xo->flags & CRYPTO_DONE))
218 skb->ip_summed = CHECKSUM_NONE;
217 219
218 return esp6_input_done2(skb, 0);220 return esp6_input_done2(skb, 0);
219}221}
@@ -332,3 +334,4 @@ module_init(esp6_offload_init); · 112 unmodified lines
332module_exit(esp6_offload_exit);334module_exit(esp6_offload_exit);
333MODULE_LICENSE("GPL");335MODULE_LICENSE("GPL");
334MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");336MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
337MODULE_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
34int xfrm6_transport_finish(struct sk_buff *skb, int async)34int xfrm6_transport_finish(struct sk_buff *skb, int async)
35{35{
36 struct xfrm_offload *xo = xfrm_offload(skb);36 struct xfrm_offload *xo = xfrm_offload(skb);
37 int nhlen = skb->data - skb_network_header(skb);
37 38
38 skb_network_header(skb)[IP6CB(skb)->nhoff] =39 skb_network_header(skb)[IP6CB(skb)->nhoff] =
39 XFRM_MODE_SKB_CB(skb)->protocol;40 XFRM_MODE_SKB_CB(skb)->protocol;
@@ -43,8 +44,9 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) · 3 unmodified lines
43 return 1;44 return 1;
44#endif45#endif
45 46
46 __skb_push(skb, skb->data - skb_network_header(skb));47 __skb_push(skb, nhlen);
47 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));48 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
49 skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
48 50
49 if (xo && (xo->flags & XFRM_GRO)) {51 if (xo && (xo->flags & XFRM_GRO)) {
50 skb_mac_header_rebuild(skb);52 skb_mac_header_rebuild(skb);
net/ipv6/xfrm6_policy.c+6−3
@@ -27,7 +27,8 @@ · 26 unmodified lines
27 27
28static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,28static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
29 const xfrm_address_t *saddr,29 const xfrm_address_t *saddr,
30 const xfrm_address_t *daddr)30 const xfrm_address_t *daddr,
31 u32 mark)
31{32{
32 struct flowi6 fl6;33 struct flowi6 fl6;
33 struct dst_entry *dst;34 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
36 memset(&fl6, 0, sizeof(fl6));37 memset(&fl6, 0, sizeof(fl6));
37 fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);38 fl6.flowi6_oif = l3mdev_master_ifindex_by_index(net, oif);
38 fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;39 fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
40 fl6.flowi6_mark = mark;
39 memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));41 memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
40 if (saddr)42 if (saddr)
41 memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));43 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
52}54}
53 55
54static int xfrm6_get_saddr(struct net *net, int oif,56static 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)
56{59{
57 struct dst_entry *dst;60 struct dst_entry *dst;
58 struct net_device *dev;61 struct net_device *dev;
59 62
60 dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr);63 dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
61 if (IS_ERR(dst))64 if (IS_ERR(dst))
62 return -EHOSTUNREACH;65 return -EHOSTUNREACH;
63 66
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
63 xfrm_address_t *daddr;63 xfrm_address_t *daddr;
64 64
65 if (!x->type_offload)65 if (!x->type_offload)
66 return 0;66 return -EINVAL;
67 67
68 /* We don't yet support UDP encapsulation, TFC padding and ESN. */68 /* We don't yet support UDP encapsulation, TFC padding and ESN. */
69 if (x->encap || x->tfcpad || (x->props.flags & XFRM_STATE_ESN))69 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
79 daddr = &x->props.saddr;79 daddr = &x->props.saddr;
80 }80 }
81 81
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);
83 if (IS_ERR(dst))84 if (IS_ERR(dst))
84 return 0;85 return 0;
85 86
net/xfrm/xfrm_input.c+2−0
@@ -424,6 +424,7 @@ resume: · 423 unmodified lines
424 nf_reset(skb);424 nf_reset(skb);
425 425
426 if (decaps) {426 if (decaps) {
427 skb->sp->olen = 0;
427 skb_dst_drop(skb);428 skb_dst_drop(skb);
428 gro_cells_receive(&gro_cells, skb);429 gro_cells_receive(&gro_cells, skb);
429 return 0;430 return 0;
@@ -434,6 +435,7 @@ resume: · 4 unmodified lines
434 435
435 err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);436 err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async);
436 if (xfrm_gro) {437 if (xfrm_gro) {
438 skb->sp->olen = 0;
437 skb_dst_drop(skb);439 skb_dst_drop(skb);
438 gro_cells_receive(&gro_cells, skb);440 gro_cells_receive(&gro_cells, skb);
439 return err;441 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
66 goto error_nolock;66 goto error_nolock;
67 }67 }
68 68
69 if (x->props.output_mark)
70 skb->mark = x->props.output_mark;
71
69 err = x->outer_mode->output(x, skb);72 err = x->outer_mode->output(x, skb);
70 if (err) {73 if (err) {
71 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);74 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
122struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,122struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
123 const xfrm_address_t *saddr,123 const xfrm_address_t *saddr,
124 const xfrm_address_t *daddr,124 const xfrm_address_t *daddr,
125 int family)125 int family, u32 mark)
126{126{
127 const struct xfrm_policy_afinfo *afinfo;127 const struct xfrm_policy_afinfo *afinfo;
128 struct dst_entry *dst;128 struct dst_entry *dst;
@@ -131,7 +131,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif, · 2 unmodified lines
131 if (unlikely(afinfo == NULL))131 if (unlikely(afinfo == NULL))
132 return ERR_PTR(-EAFNOSUPPORT);132 return ERR_PTR(-EAFNOSUPPORT);
133 133
134 dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr);134 dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
135 135
136 rcu_read_unlock();136 rcu_read_unlock();
137 137
@@ -143,7 +143,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, · 5 unmodified lines
143 int tos, int oif,143 int tos, int oif,
144 xfrm_address_t *prev_saddr,144 xfrm_address_t *prev_saddr,
145 xfrm_address_t *prev_daddr,145 xfrm_address_t *prev_daddr,
146 int family)146 int family, u32 mark)
147{147{
148 struct net *net = xs_net(x);148 struct net *net = xs_net(x);
149 xfrm_address_t *saddr = &x->props.saddr;149 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
159 daddr = x->coaddr;159 daddr = x->coaddr;
160 }160 }
161 161
162 dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family);162 dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
163 163
164 if (!IS_ERR(dst)) {164 if (!IS_ERR(dst)) {
165 if (prev_saddr != saddr)165 if (prev_saddr != saddr)
@@ -1340,14 +1340,14 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) · 1174 unmodified lines
1340 1340
1341static int1341static int
1342xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,1342xfrm_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)
1344{1344{
1345 int err;1345 int err;
1346 const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);1346 const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
1347 1347
1348 if (unlikely(afinfo == NULL))1348 if (unlikely(afinfo == NULL))
1349 return -EINVAL;1349 return -EINVAL;
1350 err = afinfo->get_saddr(net, oif, local, remote);1350 err = afinfo->get_saddr(net, oif, local, remote, mark);
1351 rcu_read_unlock();1351 rcu_read_unlock();
1352 return err;1352 return err;
1353}1353}
@@ -1378,7 +1378,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl, · 24 unmodified lines
1378 if (xfrm_addr_any(local, tmpl->encap_family)) {1378 if (xfrm_addr_any(local, tmpl->encap_family)) {
1379 error = xfrm_get_saddr(net, fl->flowi_oif,1379 error = xfrm_get_saddr(net, fl->flowi_oif,
1380 &tmp, remote,1380 &tmp, remote,
1381 tmpl->encap_family);1381 tmpl->encap_family, 0);
1382 if (error)1382 if (error)
1383 goto fail;1383 goto fail;
1384 local = &tmp;1384 local = &tmp;
@@ -1598,7 +1598,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, · 213 unmodified lines
1598 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {1598 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
1599 family = xfrm[i]->props.family;1599 family = xfrm[i]->props.family;
1600 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,1600 dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
1601 &saddr, &daddr, family);1601 &saddr, &daddr, family,
1602 xfrm[i]->props.output_mark);
1602 err = PTR_ERR(dst);1603 err = PTR_ERR(dst);
1603 if (IS_ERR(dst))1604 if (IS_ERR(dst))
1604 goto put_states;1605 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
296}296}
297EXPORT_SYMBOL(xfrm_unregister_type_offload);297EXPORT_SYMBOL(xfrm_unregister_type_offload);
298 298
299static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned short family)299static const struct xfrm_type_offload *
300xfrm_get_type_offload(u8 proto, unsigned short family, bool try_load)
300{301{
301 struct xfrm_state_afinfo *afinfo;302 struct xfrm_state_afinfo *afinfo;
302 const struct xfrm_type_offload **typemap;303 const struct xfrm_type_offload **typemap;
303 const struct xfrm_type_offload *type;304 const struct xfrm_type_offload *type;
304 305
306retry:
305 afinfo = xfrm_state_get_afinfo(family);307 afinfo = xfrm_state_get_afinfo(family);
306 if (unlikely(afinfo == NULL))308 if (unlikely(afinfo == NULL))
307 return NULL;309 return NULL;
@@ -311,6 +313,12 @@ static const struct xfrm_type_offload *xfrm_get_type_offload(u8 proto, unsigned · 3 unmodified lines
311 if ((type && !try_module_get(type->owner)))313 if ((type && !try_module_get(type->owner)))
312 type = NULL;314 type = NULL;
313 315
316 if (!type && try_load) {
317 request_module("xfrm-offload-%d-%d", family, proto);
318 try_load = 0;
319 goto retry;
320 }
321
314 rcu_read_unlock();322 rcu_read_unlock();
315 return type;323 return type;
316}324}
@@ -2165,7 +2173,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) · 1848 unmodified lines
2165 return mtu - x->props.header_len;2173 return mtu - x->props.header_len;
2166}2174}
2167 2175
2168int __xfrm_init_state(struct xfrm_state *x, bool init_replay)2176int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2169{2177{
2170 struct xfrm_state_afinfo *afinfo;2178 struct xfrm_state_afinfo *afinfo;
2171 struct xfrm_mode *inner_mode;2179 struct xfrm_mode *inner_mode;
@@ -2230,7 +2238,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay) · 58 unmodified lines
2230 if (x->type == NULL)2238 if (x->type == NULL)
2231 goto error;2239 goto error;
2232 2240
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);
2234 2242
2235 err = x->type->init_state(x);2243 err = x->type->init_state(x);
2236 if (err)2244 if (err)
@@ -2258,7 +2266,7 @@ EXPORT_SYMBOL(__xfrm_init_state); · 21 unmodified lines
2258 2266
2259int xfrm_init_state(struct xfrm_state *x)2267int xfrm_init_state(struct xfrm_state *x)
2260{2268{
2261 return __xfrm_init_state(x, true);2269 return __xfrm_init_state(x, true, false);
2262}2270}
2263 2271
2264EXPORT_SYMBOL(xfrm_init_state);2272EXPORT_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
584 584
585 xfrm_mark_get(attrs, &x->mark);585 xfrm_mark_get(attrs, &x->mark);
586 586
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]);
588 if (err)591 if (err)
589 goto error;592 goto error;
590 593
@@ -899,6 +902,11 @@ static int copy_to_user_state_extra(struct xfrm_state *x, · 308 unmodified lines
899 goto out;902 goto out;
900 if (x->security)903 if (x->security)
901 ret = copy_sec_ctx(x->security, skb);904 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 }
902out:910out:
903 return ret;911 return ret;
904}912}
@@ -2454,6 +2462,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { · 1549 unmodified lines
2454 [XFRMA_PROTO] = { .type = NLA_U8 },2462 [XFRMA_PROTO] = { .type = NLA_U8 },
2455 [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },2463 [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },
2456 [XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) },2464 [XFRMA_OFFLOAD_DEV] = { .len = sizeof(struct xfrm_user_offload) },
2465 [XFRMA_OUTPUT_MARK] = { .len = NLA_U32 },
2457};2466};
2458 2467
2459static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {2468static 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
2673 l += nla_total_size(sizeof(x->props.extra_flags));2682 l += nla_total_size(sizeof(x->props.extra_flags));
2674 if (x->xso.dev)2683 if (x->xso.dev)
2675 l += nla_total_size(sizeof(x->xso));2684 l += nla_total_size(sizeof(x->xso));
2685 if (x->props.output_mark)
2686 l += nla_total_size(sizeof(x->props.output_mark));
2676 2687
2677 /* Must count x->lastused as it may become non-zero behind our back. */2688 /* Must count x->lastused as it may become non-zero behind our back. */
2678 l += nla_total_size_64bit(sizeof(u64));2689 l += nla_total_size_64bit(sizeof(u64));