ip6_offload.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * IPV6 GSO/GRO offload support
  4. * Linux INET6 implementation
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/socket.h>
  8. #include <linux/netdevice.h>
  9. #include <linux/skbuff.h>
  10. #include <linux/printk.h>
  11. #include <net/protocol.h>
  12. #include <net/ipv6.h>
  13. #include <net/inet_common.h>
  14. #include <net/tcp.h>
  15. #include <net/udp.h>
  16. #include <net/gro.h>
  17. #include <net/gso.h>
  18. #include "ip6_offload.h"
  19. /* All GRO functions are always builtin, except UDP over ipv6, which lays in
  20. * ipv6 module, as it depends on UDPv6 lookup function, so we need special care
  21. * when ipv6 is built as a module
  22. */
  23. #if IS_BUILTIN(CONFIG_IPV6)
  24. #define INDIRECT_CALL_L4(f, f2, f1, ...) INDIRECT_CALL_2(f, f2, f1, __VA_ARGS__)
  25. #else
  26. #define INDIRECT_CALL_L4(f, f2, f1, ...) INDIRECT_CALL_1(f, f2, __VA_ARGS__)
  27. #endif
  28. #define indirect_call_gro_receive_l4(f2, f1, cb, head, skb) \
  29. ({ \
  30. unlikely(gro_recursion_inc_test(skb)) ? \
  31. NAPI_GRO_CB(skb)->flush |= 1, NULL : \
  32. INDIRECT_CALL_L4(cb, f2, f1, head, skb); \
  33. })
  34. static int ipv6_gro_pull_exthdrs(struct sk_buff *skb, int off, int proto)
  35. {
  36. const struct net_offload *ops = NULL;
  37. struct ipv6_opt_hdr *opth;
  38. for (;;) {
  39. int len;
  40. ops = rcu_dereference(inet6_offloads[proto]);
  41. if (unlikely(!ops))
  42. break;
  43. if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
  44. break;
  45. opth = skb_gro_header(skb, off + sizeof(*opth), off);
  46. if (unlikely(!opth))
  47. break;
  48. len = ipv6_optlen(opth);
  49. opth = skb_gro_header(skb, off + len, off);
  50. if (unlikely(!opth))
  51. break;
  52. proto = opth->nexthdr;
  53. off += len;
  54. }
  55. skb_gro_pull(skb, off - skb_gro_receive_network_offset(skb));
  56. return proto;
  57. }
  58. static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
  59. {
  60. const struct net_offload *ops = NULL;
  61. for (;;) {
  62. struct ipv6_opt_hdr *opth;
  63. int len;
  64. ops = rcu_dereference(inet6_offloads[proto]);
  65. if (unlikely(!ops))
  66. break;
  67. if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
  68. break;
  69. if (unlikely(!pskb_may_pull(skb, 8)))
  70. break;
  71. opth = (void *)skb->data;
  72. len = ipv6_optlen(opth);
  73. if (unlikely(!pskb_may_pull(skb, len)))
  74. break;
  75. opth = (void *)skb->data;
  76. proto = opth->nexthdr;
  77. __skb_pull(skb, len);
  78. }
  79. return proto;
  80. }
  81. static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
  82. netdev_features_t features)
  83. {
  84. struct sk_buff *segs = ERR_PTR(-EINVAL);
  85. struct ipv6hdr *ipv6h;
  86. const struct net_offload *ops;
  87. int proto, err;
  88. struct frag_hdr *fptr;
  89. unsigned int payload_len;
  90. u8 *prevhdr;
  91. int offset = 0;
  92. bool encap, udpfrag;
  93. int nhoff;
  94. bool gso_partial;
  95. skb_reset_network_header(skb);
  96. err = ipv6_hopopt_jumbo_remove(skb);
  97. if (err)
  98. return ERR_PTR(err);
  99. nhoff = skb_network_header(skb) - skb_mac_header(skb);
  100. if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
  101. goto out;
  102. encap = SKB_GSO_CB(skb)->encap_level > 0;
  103. if (encap)
  104. features &= skb->dev->hw_enc_features;
  105. SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
  106. ipv6h = ipv6_hdr(skb);
  107. __skb_pull(skb, sizeof(*ipv6h));
  108. segs = ERR_PTR(-EPROTONOSUPPORT);
  109. proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
  110. if (skb->encapsulation &&
  111. skb_shinfo(skb)->gso_type & (SKB_GSO_IPXIP4 | SKB_GSO_IPXIP6))
  112. udpfrag = proto == IPPROTO_UDP && encap &&
  113. (skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
  114. else
  115. udpfrag = proto == IPPROTO_UDP && !skb->encapsulation &&
  116. (skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
  117. ops = rcu_dereference(inet6_offloads[proto]);
  118. if (likely(ops && ops->callbacks.gso_segment)) {
  119. if (!skb_reset_transport_header_careful(skb))
  120. goto out;
  121. segs = ops->callbacks.gso_segment(skb, features);
  122. if (!segs)
  123. skb->network_header = skb_mac_header(skb) + nhoff - skb->head;
  124. }
  125. if (IS_ERR_OR_NULL(segs))
  126. goto out;
  127. gso_partial = !!(skb_shinfo(segs)->gso_type & SKB_GSO_PARTIAL);
  128. for (skb = segs; skb; skb = skb->next) {
  129. ipv6h = (struct ipv6hdr *)(skb_mac_header(skb) + nhoff);
  130. if (gso_partial && skb_is_gso(skb))
  131. payload_len = skb_shinfo(skb)->gso_size +
  132. SKB_GSO_CB(skb)->data_offset +
  133. skb->head - (unsigned char *)(ipv6h + 1);
  134. else
  135. payload_len = skb->len - nhoff - sizeof(*ipv6h);
  136. ipv6h->payload_len = htons(payload_len);
  137. skb->network_header = (u8 *)ipv6h - skb->head;
  138. skb_reset_mac_len(skb);
  139. if (udpfrag) {
  140. int err = ip6_find_1stfragopt(skb, &prevhdr);
  141. if (err < 0) {
  142. kfree_skb_list(segs);
  143. return ERR_PTR(err);
  144. }
  145. fptr = (struct frag_hdr *)((u8 *)ipv6h + err);
  146. fptr->frag_off = htons(offset);
  147. if (skb->next)
  148. fptr->frag_off |= htons(IP6_MF);
  149. offset += (ntohs(ipv6h->payload_len) -
  150. sizeof(struct frag_hdr));
  151. }
  152. if (encap)
  153. skb_reset_inner_headers(skb);
  154. }
  155. out:
  156. return segs;
  157. }
  158. /* Return the total length of all the extension hdrs, following the same
  159. * logic in ipv6_gso_pull_exthdrs() when parsing ext-hdrs.
  160. */
  161. static int ipv6_exthdrs_len(struct ipv6hdr *iph,
  162. const struct net_offload **opps)
  163. {
  164. struct ipv6_opt_hdr *opth = (void *)iph;
  165. int len = 0, proto, optlen = sizeof(*iph);
  166. proto = iph->nexthdr;
  167. for (;;) {
  168. *opps = rcu_dereference(inet6_offloads[proto]);
  169. if (unlikely(!(*opps)))
  170. break;
  171. if (!((*opps)->flags & INET6_PROTO_GSO_EXTHDR))
  172. break;
  173. opth = (void *)opth + optlen;
  174. optlen = ipv6_optlen(opth);
  175. len += optlen;
  176. proto = opth->nexthdr;
  177. }
  178. return len;
  179. }
  180. INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
  181. struct sk_buff *skb)
  182. {
  183. const struct net_offload *ops;
  184. struct sk_buff *pp = NULL;
  185. struct sk_buff *p;
  186. struct ipv6hdr *iph;
  187. unsigned int nlen;
  188. unsigned int hlen;
  189. unsigned int off;
  190. u16 flush = 1;
  191. int proto;
  192. off = skb_gro_offset(skb);
  193. hlen = off + sizeof(*iph);
  194. iph = skb_gro_header(skb, hlen, off);
  195. if (unlikely(!iph))
  196. goto out;
  197. NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = off;
  198. flush += ntohs(iph->payload_len) != skb->len - hlen;
  199. proto = iph->nexthdr;
  200. ops = rcu_dereference(inet6_offloads[proto]);
  201. if (!ops || !ops->callbacks.gro_receive) {
  202. proto = ipv6_gro_pull_exthdrs(skb, hlen, proto);
  203. ops = rcu_dereference(inet6_offloads[proto]);
  204. if (!ops || !ops->callbacks.gro_receive)
  205. goto out;
  206. iph = skb_gro_network_header(skb);
  207. } else {
  208. skb_gro_pull(skb, sizeof(*iph));
  209. }
  210. skb_set_transport_header(skb, skb_gro_offset(skb));
  211. NAPI_GRO_CB(skb)->proto = proto;
  212. flush--;
  213. nlen = skb_gro_offset(skb) - off;
  214. list_for_each_entry(p, head, list) {
  215. const struct ipv6hdr *iph2;
  216. __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
  217. if (!NAPI_GRO_CB(p)->same_flow)
  218. continue;
  219. iph2 = (struct ipv6hdr *)(p->data + off);
  220. first_word = *(__be32 *)iph ^ *(__be32 *)iph2;
  221. /* All fields must match except length and Traffic Class.
  222. * XXX skbs on the gro_list have all been parsed and pulled
  223. * already so we don't need to compare nlen
  224. * (nlen != (sizeof(*iph2) + ipv6_exthdrs_len(iph2, &ops)))
  225. * memcmp() alone below is sufficient, right?
  226. */
  227. if ((first_word & htonl(0xF00FFFFF)) ||
  228. !ipv6_addr_equal(&iph->saddr, &iph2->saddr) ||
  229. !ipv6_addr_equal(&iph->daddr, &iph2->daddr) ||
  230. iph->nexthdr != iph2->nexthdr) {
  231. not_same_flow:
  232. NAPI_GRO_CB(p)->same_flow = 0;
  233. continue;
  234. }
  235. if (unlikely(nlen > sizeof(struct ipv6hdr))) {
  236. if (memcmp(iph + 1, iph2 + 1,
  237. nlen - sizeof(struct ipv6hdr)))
  238. goto not_same_flow;
  239. }
  240. }
  241. NAPI_GRO_CB(skb)->flush |= flush;
  242. skb_gro_postpull_rcsum(skb, iph, nlen);
  243. pp = indirect_call_gro_receive_l4(tcp6_gro_receive, udp6_gro_receive,
  244. ops->callbacks.gro_receive, head, skb);
  245. out:
  246. skb_gro_flush_final(skb, pp, flush);
  247. return pp;
  248. }
  249. static struct sk_buff *sit_ip6ip6_gro_receive(struct list_head *head,
  250. struct sk_buff *skb)
  251. {
  252. /* Common GRO receive for SIT and IP6IP6 */
  253. if (NAPI_GRO_CB(skb)->encap_mark) {
  254. NAPI_GRO_CB(skb)->flush = 1;
  255. return NULL;
  256. }
  257. NAPI_GRO_CB(skb)->encap_mark = 1;
  258. return ipv6_gro_receive(head, skb);
  259. }
  260. static struct sk_buff *ip4ip6_gro_receive(struct list_head *head,
  261. struct sk_buff *skb)
  262. {
  263. /* Common GRO receive for SIT and IP6IP6 */
  264. if (NAPI_GRO_CB(skb)->encap_mark) {
  265. NAPI_GRO_CB(skb)->flush = 1;
  266. return NULL;
  267. }
  268. NAPI_GRO_CB(skb)->encap_mark = 1;
  269. return inet_gro_receive(head, skb);
  270. }
  271. INDIRECT_CALLABLE_SCOPE int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
  272. {
  273. const struct net_offload *ops;
  274. struct ipv6hdr *iph;
  275. int err = -ENOSYS;
  276. u32 payload_len;
  277. if (skb->encapsulation) {
  278. skb_set_inner_protocol(skb, cpu_to_be16(ETH_P_IPV6));
  279. skb_set_inner_network_header(skb, nhoff);
  280. }
  281. payload_len = skb->len - nhoff - sizeof(*iph);
  282. if (unlikely(payload_len > IPV6_MAXPLEN)) {
  283. struct hop_jumbo_hdr *hop_jumbo;
  284. int hoplen = sizeof(*hop_jumbo);
  285. /* Move network header left */
  286. memmove(skb_mac_header(skb) - hoplen, skb_mac_header(skb),
  287. skb->transport_header - skb->mac_header);
  288. skb->data -= hoplen;
  289. skb->len += hoplen;
  290. skb->mac_header -= hoplen;
  291. skb->network_header -= hoplen;
  292. iph = (struct ipv6hdr *)(skb->data + nhoff);
  293. hop_jumbo = (struct hop_jumbo_hdr *)(iph + 1);
  294. /* Build hop-by-hop options */
  295. hop_jumbo->nexthdr = iph->nexthdr;
  296. hop_jumbo->hdrlen = 0;
  297. hop_jumbo->tlv_type = IPV6_TLV_JUMBO;
  298. hop_jumbo->tlv_len = 4;
  299. hop_jumbo->jumbo_payload_len = htonl(payload_len + hoplen);
  300. iph->nexthdr = NEXTHDR_HOP;
  301. iph->payload_len = 0;
  302. } else {
  303. iph = (struct ipv6hdr *)(skb->data + nhoff);
  304. iph->payload_len = htons(payload_len);
  305. }
  306. nhoff += sizeof(*iph) + ipv6_exthdrs_len(iph, &ops);
  307. if (WARN_ON(!ops || !ops->callbacks.gro_complete))
  308. goto out;
  309. err = INDIRECT_CALL_L4(ops->callbacks.gro_complete, tcp6_gro_complete,
  310. udp6_gro_complete, skb, nhoff);
  311. out:
  312. return err;
  313. }
  314. static int sit_gro_complete(struct sk_buff *skb, int nhoff)
  315. {
  316. skb->encapsulation = 1;
  317. skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP4;
  318. return ipv6_gro_complete(skb, nhoff);
  319. }
  320. static int ip6ip6_gro_complete(struct sk_buff *skb, int nhoff)
  321. {
  322. skb->encapsulation = 1;
  323. skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6;
  324. return ipv6_gro_complete(skb, nhoff);
  325. }
  326. static int ip4ip6_gro_complete(struct sk_buff *skb, int nhoff)
  327. {
  328. skb->encapsulation = 1;
  329. skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6;
  330. return inet_gro_complete(skb, nhoff);
  331. }
  332. static struct sk_buff *sit_gso_segment(struct sk_buff *skb,
  333. netdev_features_t features)
  334. {
  335. if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP4))
  336. return ERR_PTR(-EINVAL);
  337. return ipv6_gso_segment(skb, features);
  338. }
  339. static struct sk_buff *ip4ip6_gso_segment(struct sk_buff *skb,
  340. netdev_features_t features)
  341. {
  342. if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
  343. return ERR_PTR(-EINVAL);
  344. return inet_gso_segment(skb, features);
  345. }
  346. static struct sk_buff *ip6ip6_gso_segment(struct sk_buff *skb,
  347. netdev_features_t features)
  348. {
  349. if (!(skb_shinfo(skb)->gso_type & SKB_GSO_IPXIP6))
  350. return ERR_PTR(-EINVAL);
  351. return ipv6_gso_segment(skb, features);
  352. }
  353. static const struct net_offload sit_offload = {
  354. .callbacks = {
  355. .gso_segment = sit_gso_segment,
  356. .gro_receive = sit_ip6ip6_gro_receive,
  357. .gro_complete = sit_gro_complete,
  358. },
  359. };
  360. static const struct net_offload ip4ip6_offload = {
  361. .callbacks = {
  362. .gso_segment = ip4ip6_gso_segment,
  363. .gro_receive = ip4ip6_gro_receive,
  364. .gro_complete = ip4ip6_gro_complete,
  365. },
  366. };
  367. static const struct net_offload ip6ip6_offload = {
  368. .callbacks = {
  369. .gso_segment = ip6ip6_gso_segment,
  370. .gro_receive = sit_ip6ip6_gro_receive,
  371. .gro_complete = ip6ip6_gro_complete,
  372. },
  373. };
  374. static int __init ipv6_offload_init(void)
  375. {
  376. if (tcpv6_offload_init() < 0)
  377. pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
  378. if (ipv6_exthdrs_offload_init() < 0)
  379. pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);
  380. net_hotdata.ipv6_packet_offload = (struct packet_offload) {
  381. .type = cpu_to_be16(ETH_P_IPV6),
  382. .callbacks = {
  383. .gso_segment = ipv6_gso_segment,
  384. .gro_receive = ipv6_gro_receive,
  385. .gro_complete = ipv6_gro_complete,
  386. },
  387. };
  388. dev_add_offload(&net_hotdata.ipv6_packet_offload);
  389. inet_add_offload(&sit_offload, IPPROTO_IPV6);
  390. inet6_add_offload(&ip6ip6_offload, IPPROTO_IPV6);
  391. inet6_add_offload(&ip4ip6_offload, IPPROTO_IPIP);
  392. return 0;
  393. }
  394. fs_initcall(ipv6_offload_init);