1 /* 2 * xfrm_device.c - IPsec device offloading code. 3 * 4 * Copyright (c) 2015 secunet Security Networks AG 5 * 6 * Author: 7 * Steffen Klassert <steffen.klassert@secunet.com> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation; either version 12 * 2 of the License, or (at your option) any later version. 13 */ 14 15 #include <linux/errno.h> 16 #include <linux/module.h> 17 #include <linux/netdevice.h> 18 #include <linux/skbuff.h> 19 #include <linux/slab.h> 20 #include <linux/spinlock.h> 21 #include <net/dst.h> 22 #include <net/xfrm.h> 23 #include <linux/notifier.h> 24 25 int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features) 26 { 27 int err; 28 struct xfrm_state *x; 29 struct xfrm_offload *xo = xfrm_offload(skb); 30 31 if (skb_is_gso(skb)) 32 return 0; 33 34 if (xo) { 35 x = skb->sp->xvec[skb->sp->len - 1]; 36 if (xo->flags & XFRM_GRO || x->xso.flags & XFRM_OFFLOAD_INBOUND) 37 return 0; 38 39 x->outer_mode->xmit(x, skb); 40 41 err = x->type_offload->xmit(x, skb, features); 42 if (err) { 43 XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR); 44 return err; 45 } 46 47 skb_push(skb, skb->data - skb_mac_header(skb)); 48 } 49 50 return 0; 51 } 52 EXPORT_SYMBOL_GPL(validate_xmit_xfrm); 53 54 int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, 55 struct xfrm_user_offload *xuo) 56 { 57 int err; 58 struct dst_entry *dst; 59 struct net_device *dev; 60 struct xfrm_state_offload *xso = &x->xso; 61 xfrm_address_t *saddr; 62 xfrm_address_t *daddr; 63 64 if (!x->type_offload) 65 return 0; 66 67 /* We don't yet support UDP encapsulation, TFC padding and ESN. */ 68 if (x->encap || x->tfcpad || (x->props.flags & XFRM_STATE_ESN)) 69 return 0; 70 71 dev = dev_get_by_index(net, xuo->ifindex); 72 if (!dev) { 73 if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) { 74 saddr = &x->props.saddr; 75 daddr = &x->id.daddr; 76 } else { 77 saddr = &x->id.daddr; 78 daddr = &x->props.saddr; 79 } 80 81 dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr, x->props.family); 82 if (IS_ERR(dst)) 83 return 0; 84 85 dev = dst->dev; 86 87 dev_hold(dev); 88 dst_release(dst); 89 } 90 91 if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) { 92 dev_put(dev); 93 return 0; 94 } 95 96 xso->dev = dev; 97 xso->num_exthdrs = 1; 98 xso->flags = xuo->flags; 99 100 err = dev->xfrmdev_ops->xdo_dev_state_add(x); 101 if (err) { 102 dev_put(dev); 103 return err; 104 } 105 106 return 0; 107 } 108 EXPORT_SYMBOL_GPL(xfrm_dev_state_add); 109 110 bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x) 111 { 112 int mtu; 113 struct dst_entry *dst = skb_dst(skb); 114 struct xfrm_dst *xdst = (struct xfrm_dst *)dst; 115 struct net_device *dev = x->xso.dev; 116 117 if (!x->type_offload || x->encap) 118 return false; 119 120 if ((x->xso.offload_handle && (dev == dst->path->dev)) && 121 !dst->child->xfrm && x->type->get_mtu) { 122 mtu = x->type->get_mtu(x, xdst->child_mtu_cached); 123 124 if (skb->len <= mtu) 125 goto ok; 126 127 if (skb_is_gso(skb) && skb_gso_validate_mtu(skb, mtu)) 128 goto ok; 129 } 130 131 return false; 132 133 ok: 134 if (dev && dev->xfrmdev_ops && dev->xfrmdev_ops->xdo_dev_offload_ok) 135 return x->xso.dev->xfrmdev_ops->xdo_dev_offload_ok(skb, x); 136 137 return true; 138 } 139 EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok); 140 141 int xfrm_dev_register(struct net_device *dev) 142 { 143 if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops) 144 return NOTIFY_BAD; 145 if ((dev->features & NETIF_F_HW_ESP_TX_CSUM) && 146 !(dev->features & NETIF_F_HW_ESP)) 147 return NOTIFY_BAD; 148 149 return NOTIFY_DONE; 150 } 151 152 static int xfrm_dev_unregister(struct net_device *dev) 153 { 154 return NOTIFY_DONE; 155 } 156 157 static int xfrm_dev_feat_change(struct net_device *dev) 158 { 159 if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops) 160 return NOTIFY_BAD; 161 else if (!(dev->features & NETIF_F_HW_ESP)) 162 dev->xfrmdev_ops = NULL; 163 164 if ((dev->features & NETIF_F_HW_ESP_TX_CSUM) && 165 !(dev->features & NETIF_F_HW_ESP)) 166 return NOTIFY_BAD; 167 168 return NOTIFY_DONE; 169 } 170 171 static int xfrm_dev_down(struct net_device *dev) 172 { 173 if (dev->features & NETIF_F_HW_ESP) 174 xfrm_dev_state_flush(dev_net(dev), dev, true); 175 176 xfrm_garbage_collect(dev_net(dev)); 177 178 return NOTIFY_DONE; 179 } 180 181 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) 182 { 183 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 184 185 switch (event) { 186 case NETDEV_REGISTER: 187 return xfrm_dev_register(dev); 188 189 case NETDEV_UNREGISTER: 190 return xfrm_dev_unregister(dev); 191 192 case NETDEV_FEAT_CHANGE: 193 return xfrm_dev_feat_change(dev); 194 195 case NETDEV_DOWN: 196 return xfrm_dev_down(dev); 197 } 198 return NOTIFY_DONE; 199 } 200 201 static struct notifier_block xfrm_dev_notifier = { 202 .notifier_call = xfrm_dev_event, 203 }; 204 205 void __net_init xfrm_dev_init(void) 206 { 207 register_netdevice_notifier(&xfrm_dev_notifier); 208 } 209