1 #include <linux/module.h>
2 #include <linux/errno.h>
3 #include <linux/socket.h>
4 #include <linux/skbuff.h>
6 #include <linux/icmp.h>
8 #include <linux/types.h>
9 #include <linux/kernel.h>
10 #include <net/genetlink.h>
14 #include <net/protocol.h>
16 #include <net/udp_tunnel.h>
18 #include <uapi/linux/fou.h>
19 #include <uapi/linux/genetlink.h>
28 struct list_head list
;
32 #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
38 struct udp_port_cfg udp_config
;
41 static unsigned int fou_net_id
;
44 struct list_head fou_list
;
45 struct mutex fou_lock
;
48 static inline struct fou
*fou_from_sock(struct sock
*sk
)
50 return sk
->sk_user_data
;
53 static int fou_recv_pull(struct sk_buff
*skb
, struct fou
*fou
, size_t len
)
55 /* Remove 'len' bytes from the packet (UDP header and
56 * FOU header if present).
58 if (fou
->family
== AF_INET
)
59 ip_hdr(skb
)->tot_len
= htons(ntohs(ip_hdr(skb
)->tot_len
) - len
);
61 ipv6_hdr(skb
)->payload_len
=
62 htons(ntohs(ipv6_hdr(skb
)->payload_len
) - len
);
65 skb_postpull_rcsum(skb
, udp_hdr(skb
), len
);
66 skb_reset_transport_header(skb
);
67 return iptunnel_pull_offloads(skb
);
70 static int fou_udp_recv(struct sock
*sk
, struct sk_buff
*skb
)
72 struct fou
*fou
= fou_from_sock(sk
);
77 if (fou_recv_pull(skb
, fou
, sizeof(struct udphdr
)))
80 return -fou
->protocol
;
87 static struct guehdr
*gue_remcsum(struct sk_buff
*skb
, struct guehdr
*guehdr
,
88 void *data
, size_t hdrlen
, u8 ipproto
,
92 size_t start
= ntohs(pd
[0]);
93 size_t offset
= ntohs(pd
[1]);
94 size_t plen
= sizeof(struct udphdr
) + hdrlen
+
95 max_t(size_t, offset
+ sizeof(u16
), start
);
97 if (skb
->remcsum_offload
)
100 if (!pskb_may_pull(skb
, plen
))
102 guehdr
= (struct guehdr
*)&udp_hdr(skb
)[1];
104 skb_remcsum_process(skb
, (void *)guehdr
+ hdrlen
,
105 start
, offset
, nopartial
);
110 static int gue_control_message(struct sk_buff
*skb
, struct guehdr
*guehdr
)
117 static int gue_udp_recv(struct sock
*sk
, struct sk_buff
*skb
)
119 struct fou
*fou
= fou_from_sock(sk
);
120 size_t len
, optlen
, hdrlen
;
121 struct guehdr
*guehdr
;
129 len
= sizeof(struct udphdr
) + sizeof(struct guehdr
);
130 if (!pskb_may_pull(skb
, len
))
133 guehdr
= (struct guehdr
*)&udp_hdr(skb
)[1];
135 switch (guehdr
->version
) {
136 case 0: /* Full GUE header present */
140 /* Direct encasulation of IPv4 or IPv6 */
144 switch (((struct iphdr
*)guehdr
)->version
) {
155 if (fou_recv_pull(skb
, fou
, sizeof(struct udphdr
)))
161 default: /* Undefined version */
165 optlen
= guehdr
->hlen
<< 2;
168 if (!pskb_may_pull(skb
, len
))
171 /* guehdr may change after pull */
172 guehdr
= (struct guehdr
*)&udp_hdr(skb
)[1];
174 hdrlen
= sizeof(struct guehdr
) + optlen
;
176 if (guehdr
->version
!= 0 || validate_gue_flags(guehdr
, optlen
))
179 hdrlen
= sizeof(struct guehdr
) + optlen
;
181 if (fou
->family
== AF_INET
)
182 ip_hdr(skb
)->tot_len
= htons(ntohs(ip_hdr(skb
)->tot_len
) - len
);
184 ipv6_hdr(skb
)->payload_len
=
185 htons(ntohs(ipv6_hdr(skb
)->payload_len
) - len
);
187 /* Pull csum through the guehdr now . This can be used if
188 * there is a remote checksum offload.
190 skb_postpull_rcsum(skb
, udp_hdr(skb
), len
);
194 if (guehdr
->flags
& GUE_FLAG_PRIV
) {
195 __be32 flags
= *(__be32
*)(data
+ doffset
);
197 doffset
+= GUE_LEN_PRIV
;
199 if (flags
& GUE_PFLAG_REMCSUM
) {
200 guehdr
= gue_remcsum(skb
, guehdr
, data
+ doffset
,
201 hdrlen
, guehdr
->proto_ctype
,
203 FOU_F_REMCSUM_NOPARTIAL
));
209 doffset
+= GUE_PLEN_REMCSUM
;
213 if (unlikely(guehdr
->control
))
214 return gue_control_message(skb
, guehdr
);
216 proto_ctype
= guehdr
->proto_ctype
;
217 __skb_pull(skb
, sizeof(struct udphdr
) + hdrlen
);
218 skb_reset_transport_header(skb
);
220 if (iptunnel_pull_offloads(skb
))
230 static struct sk_buff
*fou_gro_receive(struct sock
*sk
,
231 struct list_head
*head
,
234 u8 proto
= fou_from_sock(sk
)->protocol
;
235 const struct net_offload
**offloads
;
236 const struct net_offload
*ops
;
237 struct sk_buff
*pp
= NULL
;
239 /* We can clear the encap_mark for FOU as we are essentially doing
240 * one of two possible things. We are either adding an L4 tunnel
241 * header to the outer L3 tunnel header, or we are are simply
242 * treating the GRE tunnel header as though it is a UDP protocol
243 * specific header such as VXLAN or GENEVE.
245 NAPI_GRO_CB(skb
)->encap_mark
= 0;
247 /* Flag this frame as already having an outer encap header */
248 NAPI_GRO_CB(skb
)->is_fou
= 1;
251 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
252 ops
= rcu_dereference(offloads
[proto
]);
253 if (!ops
|| !ops
->callbacks
.gro_receive
)
256 pp
= call_gro_receive(ops
->callbacks
.gro_receive
, head
, skb
);
264 static int fou_gro_complete(struct sock
*sk
, struct sk_buff
*skb
,
267 const struct net_offload
*ops
;
268 u8 proto
= fou_from_sock(sk
)->protocol
;
270 const struct net_offload
**offloads
;
273 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
274 ops
= rcu_dereference(offloads
[proto
]);
275 if (WARN_ON(!ops
|| !ops
->callbacks
.gro_complete
))
278 err
= ops
->callbacks
.gro_complete(skb
, nhoff
);
280 skb_set_inner_mac_header(skb
, nhoff
);
288 static struct guehdr
*gue_gro_remcsum(struct sk_buff
*skb
, unsigned int off
,
289 struct guehdr
*guehdr
, void *data
,
290 size_t hdrlen
, struct gro_remcsum
*grc
,
294 size_t start
= ntohs(pd
[0]);
295 size_t offset
= ntohs(pd
[1]);
297 if (skb
->remcsum_offload
)
300 if (!NAPI_GRO_CB(skb
)->csum_valid
)
303 guehdr
= skb_gro_remcsum_process(skb
, (void *)guehdr
, off
, hdrlen
,
304 start
, offset
, grc
, nopartial
);
306 skb
->remcsum_offload
= 1;
311 static struct sk_buff
*gue_gro_receive(struct sock
*sk
,
312 struct list_head
*head
,
315 const struct net_offload
**offloads
;
316 const struct net_offload
*ops
;
317 struct sk_buff
*pp
= NULL
;
319 struct guehdr
*guehdr
;
320 size_t len
, optlen
, hdrlen
, off
;
324 struct fou
*fou
= fou_from_sock(sk
);
325 struct gro_remcsum grc
;
328 skb_gro_remcsum_init(&grc
);
330 off
= skb_gro_offset(skb
);
331 len
= off
+ sizeof(*guehdr
);
333 guehdr
= skb_gro_header_fast(skb
, off
);
334 if (skb_gro_header_hard(skb
, len
)) {
335 guehdr
= skb_gro_header_slow(skb
, len
, off
);
336 if (unlikely(!guehdr
))
340 switch (guehdr
->version
) {
344 switch (((struct iphdr
*)guehdr
)->version
) {
346 proto
= IPPROTO_IPIP
;
349 proto
= IPPROTO_IPV6
;
359 optlen
= guehdr
->hlen
<< 2;
362 if (skb_gro_header_hard(skb
, len
)) {
363 guehdr
= skb_gro_header_slow(skb
, len
, off
);
364 if (unlikely(!guehdr
))
368 if (unlikely(guehdr
->control
) || guehdr
->version
!= 0 ||
369 validate_gue_flags(guehdr
, optlen
))
372 hdrlen
= sizeof(*guehdr
) + optlen
;
374 /* Adjust NAPI_GRO_CB(skb)->csum to account for guehdr,
375 * this is needed if there is a remote checkcsum offload.
377 skb_gro_postpull_rcsum(skb
, guehdr
, hdrlen
);
381 if (guehdr
->flags
& GUE_FLAG_PRIV
) {
382 __be32 flags
= *(__be32
*)(data
+ doffset
);
384 doffset
+= GUE_LEN_PRIV
;
386 if (flags
& GUE_PFLAG_REMCSUM
) {
387 guehdr
= gue_gro_remcsum(skb
, off
, guehdr
,
388 data
+ doffset
, hdrlen
, &grc
,
390 FOU_F_REMCSUM_NOPARTIAL
));
397 doffset
+= GUE_PLEN_REMCSUM
;
401 skb_gro_pull(skb
, hdrlen
);
403 list_for_each_entry(p
, head
, list
) {
404 const struct guehdr
*guehdr2
;
406 if (!NAPI_GRO_CB(p
)->same_flow
)
409 guehdr2
= (struct guehdr
*)(p
->data
+ off
);
411 /* Compare base GUE header to be equal (covers
412 * hlen, version, proto_ctype, and flags.
414 if (guehdr
->word
!= guehdr2
->word
) {
415 NAPI_GRO_CB(p
)->same_flow
= 0;
419 /* Compare optional fields are the same. */
420 if (guehdr
->hlen
&& memcmp(&guehdr
[1], &guehdr2
[1],
421 guehdr
->hlen
<< 2)) {
422 NAPI_GRO_CB(p
)->same_flow
= 0;
427 proto
= guehdr
->proto_ctype
;
431 /* We can clear the encap_mark for GUE as we are essentially doing
432 * one of two possible things. We are either adding an L4 tunnel
433 * header to the outer L3 tunnel header, or we are are simply
434 * treating the GRE tunnel header as though it is a UDP protocol
435 * specific header such as VXLAN or GENEVE.
437 NAPI_GRO_CB(skb
)->encap_mark
= 0;
439 /* Flag this frame as already having an outer encap header */
440 NAPI_GRO_CB(skb
)->is_fou
= 1;
443 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
444 ops
= rcu_dereference(offloads
[proto
]);
445 if (WARN_ON_ONCE(!ops
|| !ops
->callbacks
.gro_receive
))
448 pp
= call_gro_receive(ops
->callbacks
.gro_receive
, head
, skb
);
454 skb_gro_flush_final_remcsum(skb
, pp
, flush
, &grc
);
459 static int gue_gro_complete(struct sock
*sk
, struct sk_buff
*skb
, int nhoff
)
461 const struct net_offload
**offloads
;
462 struct guehdr
*guehdr
= (struct guehdr
*)(skb
->data
+ nhoff
);
463 const struct net_offload
*ops
;
464 unsigned int guehlen
= 0;
468 switch (guehdr
->version
) {
470 proto
= guehdr
->proto_ctype
;
471 guehlen
= sizeof(*guehdr
) + (guehdr
->hlen
<< 2);
474 switch (((struct iphdr
*)guehdr
)->version
) {
476 proto
= IPPROTO_IPIP
;
479 proto
= IPPROTO_IPV6
;
490 offloads
= NAPI_GRO_CB(skb
)->is_ipv6
? inet6_offloads
: inet_offloads
;
491 ops
= rcu_dereference(offloads
[proto
]);
492 if (WARN_ON(!ops
|| !ops
->callbacks
.gro_complete
))
495 err
= ops
->callbacks
.gro_complete(skb
, nhoff
+ guehlen
);
497 skb_set_inner_mac_header(skb
, nhoff
+ guehlen
);
504 static int fou_add_to_port_list(struct net
*net
, struct fou
*fou
)
506 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
509 mutex_lock(&fn
->fou_lock
);
510 list_for_each_entry(fout
, &fn
->fou_list
, list
) {
511 if (fou
->port
== fout
->port
&&
512 fou
->family
== fout
->family
) {
513 mutex_unlock(&fn
->fou_lock
);
518 list_add(&fou
->list
, &fn
->fou_list
);
519 mutex_unlock(&fn
->fou_lock
);
524 static void fou_release(struct fou
*fou
)
526 struct socket
*sock
= fou
->sock
;
528 list_del(&fou
->list
);
529 udp_tunnel_sock_release(sock
);
534 static int fou_create(struct net
*net
, struct fou_cfg
*cfg
,
535 struct socket
**sockp
)
537 struct socket
*sock
= NULL
;
538 struct fou
*fou
= NULL
;
540 struct udp_tunnel_sock_cfg tunnel_cfg
;
543 /* Open UDP socket */
544 err
= udp_sock_create(net
, &cfg
->udp_config
, &sock
);
548 /* Allocate FOU port structure */
549 fou
= kzalloc(sizeof(*fou
), GFP_KERNEL
);
557 fou
->port
= cfg
->udp_config
.local_udp_port
;
558 fou
->family
= cfg
->udp_config
.family
;
559 fou
->flags
= cfg
->flags
;
560 fou
->type
= cfg
->type
;
563 memset(&tunnel_cfg
, 0, sizeof(tunnel_cfg
));
564 tunnel_cfg
.encap_type
= 1;
565 tunnel_cfg
.sk_user_data
= fou
;
566 tunnel_cfg
.encap_destroy
= NULL
;
568 /* Initial for fou type */
570 case FOU_ENCAP_DIRECT
:
571 tunnel_cfg
.encap_rcv
= fou_udp_recv
;
572 tunnel_cfg
.gro_receive
= fou_gro_receive
;
573 tunnel_cfg
.gro_complete
= fou_gro_complete
;
574 fou
->protocol
= cfg
->protocol
;
577 tunnel_cfg
.encap_rcv
= gue_udp_recv
;
578 tunnel_cfg
.gro_receive
= gue_gro_receive
;
579 tunnel_cfg
.gro_complete
= gue_gro_complete
;
586 setup_udp_tunnel_sock(net
, sock
, &tunnel_cfg
);
588 sk
->sk_allocation
= GFP_ATOMIC
;
590 err
= fou_add_to_port_list(net
, fou
);
602 udp_tunnel_sock_release(sock
);
607 static int fou_destroy(struct net
*net
, struct fou_cfg
*cfg
)
609 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
610 __be16 port
= cfg
->udp_config
.local_udp_port
;
611 u8 family
= cfg
->udp_config
.family
;
615 mutex_lock(&fn
->fou_lock
);
616 list_for_each_entry(fou
, &fn
->fou_list
, list
) {
617 if (fou
->port
== port
&& fou
->family
== family
) {
623 mutex_unlock(&fn
->fou_lock
);
628 static struct genl_family fou_nl_family
;
630 static const struct nla_policy fou_nl_policy
[FOU_ATTR_MAX
+ 1] = {
631 [FOU_ATTR_PORT
] = { .type
= NLA_U16
, },
632 [FOU_ATTR_AF
] = { .type
= NLA_U8
, },
633 [FOU_ATTR_IPPROTO
] = { .type
= NLA_U8
, },
634 [FOU_ATTR_TYPE
] = { .type
= NLA_U8
, },
635 [FOU_ATTR_REMCSUM_NOPARTIAL
] = { .type
= NLA_FLAG
, },
638 static int parse_nl_config(struct genl_info
*info
,
641 memset(cfg
, 0, sizeof(*cfg
));
643 cfg
->udp_config
.family
= AF_INET
;
645 if (info
->attrs
[FOU_ATTR_AF
]) {
646 u8 family
= nla_get_u8(info
->attrs
[FOU_ATTR_AF
]);
652 cfg
->udp_config
.ipv6_v6only
= 1;
655 return -EAFNOSUPPORT
;
658 cfg
->udp_config
.family
= family
;
661 if (info
->attrs
[FOU_ATTR_PORT
]) {
662 __be16 port
= nla_get_be16(info
->attrs
[FOU_ATTR_PORT
]);
664 cfg
->udp_config
.local_udp_port
= port
;
667 if (info
->attrs
[FOU_ATTR_IPPROTO
])
668 cfg
->protocol
= nla_get_u8(info
->attrs
[FOU_ATTR_IPPROTO
]);
670 if (info
->attrs
[FOU_ATTR_TYPE
])
671 cfg
->type
= nla_get_u8(info
->attrs
[FOU_ATTR_TYPE
]);
673 if (info
->attrs
[FOU_ATTR_REMCSUM_NOPARTIAL
])
674 cfg
->flags
|= FOU_F_REMCSUM_NOPARTIAL
;
679 static int fou_nl_cmd_add_port(struct sk_buff
*skb
, struct genl_info
*info
)
681 struct net
*net
= genl_info_net(info
);
685 err
= parse_nl_config(info
, &cfg
);
689 return fou_create(net
, &cfg
, NULL
);
692 static int fou_nl_cmd_rm_port(struct sk_buff
*skb
, struct genl_info
*info
)
694 struct net
*net
= genl_info_net(info
);
698 err
= parse_nl_config(info
, &cfg
);
702 return fou_destroy(net
, &cfg
);
705 static int fou_fill_info(struct fou
*fou
, struct sk_buff
*msg
)
707 if (nla_put_u8(msg
, FOU_ATTR_AF
, fou
->sock
->sk
->sk_family
) ||
708 nla_put_be16(msg
, FOU_ATTR_PORT
, fou
->port
) ||
709 nla_put_u8(msg
, FOU_ATTR_IPPROTO
, fou
->protocol
) ||
710 nla_put_u8(msg
, FOU_ATTR_TYPE
, fou
->type
))
713 if (fou
->flags
& FOU_F_REMCSUM_NOPARTIAL
)
714 if (nla_put_flag(msg
, FOU_ATTR_REMCSUM_NOPARTIAL
))
719 static int fou_dump_info(struct fou
*fou
, u32 portid
, u32 seq
,
720 u32 flags
, struct sk_buff
*skb
, u8 cmd
)
724 hdr
= genlmsg_put(skb
, portid
, seq
, &fou_nl_family
, flags
, cmd
);
728 if (fou_fill_info(fou
, skb
) < 0)
729 goto nla_put_failure
;
731 genlmsg_end(skb
, hdr
);
735 genlmsg_cancel(skb
, hdr
);
739 static int fou_nl_cmd_get_port(struct sk_buff
*skb
, struct genl_info
*info
)
741 struct net
*net
= genl_info_net(info
);
742 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
750 ret
= parse_nl_config(info
, &cfg
);
753 port
= cfg
.udp_config
.local_udp_port
;
757 family
= cfg
.udp_config
.family
;
758 if (family
!= AF_INET
&& family
!= AF_INET6
)
761 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
766 mutex_lock(&fn
->fou_lock
);
767 list_for_each_entry(fout
, &fn
->fou_list
, list
) {
768 if (port
== fout
->port
&& family
== fout
->family
) {
769 ret
= fou_dump_info(fout
, info
->snd_portid
,
770 info
->snd_seq
, 0, msg
,
775 mutex_unlock(&fn
->fou_lock
);
779 return genlmsg_reply(msg
, info
);
786 static int fou_nl_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
788 struct net
*net
= sock_net(skb
->sk
);
789 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
793 mutex_lock(&fn
->fou_lock
);
794 list_for_each_entry(fout
, &fn
->fou_list
, list
) {
795 if (idx
++ < cb
->args
[0])
797 ret
= fou_dump_info(fout
, NETLINK_CB(cb
->skb
).portid
,
798 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
803 mutex_unlock(&fn
->fou_lock
);
809 static const struct genl_ops fou_nl_ops
[] = {
812 .doit
= fou_nl_cmd_add_port
,
813 .policy
= fou_nl_policy
,
814 .flags
= GENL_ADMIN_PERM
,
818 .doit
= fou_nl_cmd_rm_port
,
819 .policy
= fou_nl_policy
,
820 .flags
= GENL_ADMIN_PERM
,
824 .doit
= fou_nl_cmd_get_port
,
825 .dumpit
= fou_nl_dump
,
826 .policy
= fou_nl_policy
,
830 static struct genl_family fou_nl_family __ro_after_init
= {
832 .name
= FOU_GENL_NAME
,
833 .version
= FOU_GENL_VERSION
,
834 .maxattr
= FOU_ATTR_MAX
,
836 .module
= THIS_MODULE
,
838 .n_ops
= ARRAY_SIZE(fou_nl_ops
),
841 size_t fou_encap_hlen(struct ip_tunnel_encap
*e
)
843 return sizeof(struct udphdr
);
845 EXPORT_SYMBOL(fou_encap_hlen
);
847 size_t gue_encap_hlen(struct ip_tunnel_encap
*e
)
850 bool need_priv
= false;
852 len
= sizeof(struct udphdr
) + sizeof(struct guehdr
);
854 if (e
->flags
& TUNNEL_ENCAP_FLAG_REMCSUM
) {
855 len
+= GUE_PLEN_REMCSUM
;
859 len
+= need_priv
? GUE_LEN_PRIV
: 0;
863 EXPORT_SYMBOL(gue_encap_hlen
);
865 int __fou_build_header(struct sk_buff
*skb
, struct ip_tunnel_encap
*e
,
866 u8
*protocol
, __be16
*sport
, int type
)
870 err
= iptunnel_handle_offloads(skb
, type
);
874 *sport
= e
->sport
? : udp_flow_src_port(dev_net(skb
->dev
),
879 EXPORT_SYMBOL(__fou_build_header
);
881 int __gue_build_header(struct sk_buff
*skb
, struct ip_tunnel_encap
*e
,
882 u8
*protocol
, __be16
*sport
, int type
)
884 struct guehdr
*guehdr
;
885 size_t hdrlen
, optlen
= 0;
887 bool need_priv
= false;
890 if ((e
->flags
& TUNNEL_ENCAP_FLAG_REMCSUM
) &&
891 skb
->ip_summed
== CHECKSUM_PARTIAL
) {
892 optlen
+= GUE_PLEN_REMCSUM
;
893 type
|= SKB_GSO_TUNNEL_REMCSUM
;
897 optlen
+= need_priv
? GUE_LEN_PRIV
: 0;
899 err
= iptunnel_handle_offloads(skb
, type
);
903 /* Get source port (based on flow hash) before skb_push */
904 *sport
= e
->sport
? : udp_flow_src_port(dev_net(skb
->dev
),
907 hdrlen
= sizeof(struct guehdr
) + optlen
;
909 skb_push(skb
, hdrlen
);
911 guehdr
= (struct guehdr
*)skb
->data
;
915 guehdr
->hlen
= optlen
>> 2;
917 guehdr
->proto_ctype
= *protocol
;
922 __be32
*flags
= data
;
924 guehdr
->flags
|= GUE_FLAG_PRIV
;
926 data
+= GUE_LEN_PRIV
;
928 if (type
& SKB_GSO_TUNNEL_REMCSUM
) {
929 u16 csum_start
= skb_checksum_start_offset(skb
);
932 if (csum_start
< hdrlen
)
935 csum_start
-= hdrlen
;
936 pd
[0] = htons(csum_start
);
937 pd
[1] = htons(csum_start
+ skb
->csum_offset
);
939 if (!skb_is_gso(skb
)) {
940 skb
->ip_summed
= CHECKSUM_NONE
;
941 skb
->encapsulation
= 0;
944 *flags
|= GUE_PFLAG_REMCSUM
;
945 data
+= GUE_PLEN_REMCSUM
;
952 EXPORT_SYMBOL(__gue_build_header
);
954 #ifdef CONFIG_NET_FOU_IP_TUNNELS
956 static void fou_build_udp(struct sk_buff
*skb
, struct ip_tunnel_encap
*e
,
957 struct flowi4
*fl4
, u8
*protocol
, __be16 sport
)
961 skb_push(skb
, sizeof(struct udphdr
));
962 skb_reset_transport_header(skb
);
968 uh
->len
= htons(skb
->len
);
969 udp_set_csum(!(e
->flags
& TUNNEL_ENCAP_FLAG_CSUM
), skb
,
970 fl4
->saddr
, fl4
->daddr
, skb
->len
);
972 *protocol
= IPPROTO_UDP
;
975 static int fou_build_header(struct sk_buff
*skb
, struct ip_tunnel_encap
*e
,
976 u8
*protocol
, struct flowi4
*fl4
)
978 int type
= e
->flags
& TUNNEL_ENCAP_FLAG_CSUM
? SKB_GSO_UDP_TUNNEL_CSUM
:
983 err
= __fou_build_header(skb
, e
, protocol
, &sport
, type
);
987 fou_build_udp(skb
, e
, fl4
, protocol
, sport
);
992 static int gue_build_header(struct sk_buff
*skb
, struct ip_tunnel_encap
*e
,
993 u8
*protocol
, struct flowi4
*fl4
)
995 int type
= e
->flags
& TUNNEL_ENCAP_FLAG_CSUM
? SKB_GSO_UDP_TUNNEL_CSUM
:
1000 err
= __gue_build_header(skb
, e
, protocol
, &sport
, type
);
1004 fou_build_udp(skb
, e
, fl4
, protocol
, sport
);
1009 static int gue_err_proto_handler(int proto
, struct sk_buff
*skb
, u32 info
)
1011 const struct net_protocol
*ipprot
= rcu_dereference(inet_protos
[proto
]);
1013 if (ipprot
&& ipprot
->err_handler
) {
1014 if (!ipprot
->err_handler(skb
, info
))
1021 static int gue_err(struct sk_buff
*skb
, u32 info
)
1023 int transport_offset
= skb_transport_offset(skb
);
1024 struct guehdr
*guehdr
;
1028 len
= sizeof(struct udphdr
) + sizeof(struct guehdr
);
1029 if (!pskb_may_pull(skb
, transport_offset
+ len
))
1032 guehdr
= (struct guehdr
*)&udp_hdr(skb
)[1];
1034 switch (guehdr
->version
) {
1035 case 0: /* Full GUE header present */
1038 /* Direct encasulation of IPv4 or IPv6 */
1039 skb_set_transport_header(skb
, -(int)sizeof(struct icmphdr
));
1041 switch (((struct iphdr
*)guehdr
)->version
) {
1043 ret
= gue_err_proto_handler(IPPROTO_IPIP
, skb
, info
);
1045 #if IS_ENABLED(CONFIG_IPV6)
1047 ret
= gue_err_proto_handler(IPPROTO_IPV6
, skb
, info
);
1055 default: /* Undefined version */
1059 if (guehdr
->control
)
1062 optlen
= guehdr
->hlen
<< 2;
1064 if (!pskb_may_pull(skb
, transport_offset
+ len
+ optlen
))
1067 guehdr
= (struct guehdr
*)&udp_hdr(skb
)[1];
1068 if (validate_gue_flags(guehdr
, optlen
))
1071 /* Handling exceptions for direct UDP encapsulation in GUE would lead to
1072 * recursion. Besides, this kind of encapsulation can't even be
1073 * configured currently. Discard this.
1075 if (guehdr
->proto_ctype
== IPPROTO_UDP
||
1076 guehdr
->proto_ctype
== IPPROTO_UDPLITE
)
1079 skb_set_transport_header(skb
, -(int)sizeof(struct icmphdr
));
1080 ret
= gue_err_proto_handler(guehdr
->proto_ctype
, skb
, info
);
1083 skb_set_transport_header(skb
, transport_offset
);
1088 static const struct ip_tunnel_encap_ops fou_iptun_ops
= {
1089 .encap_hlen
= fou_encap_hlen
,
1090 .build_header
= fou_build_header
,
1091 .err_handler
= gue_err
,
1094 static const struct ip_tunnel_encap_ops gue_iptun_ops
= {
1095 .encap_hlen
= gue_encap_hlen
,
1096 .build_header
= gue_build_header
,
1097 .err_handler
= gue_err
,
1100 static int ip_tunnel_encap_add_fou_ops(void)
1104 ret
= ip_tunnel_encap_add_ops(&fou_iptun_ops
, TUNNEL_ENCAP_FOU
);
1106 pr_err("can't add fou ops\n");
1110 ret
= ip_tunnel_encap_add_ops(&gue_iptun_ops
, TUNNEL_ENCAP_GUE
);
1112 pr_err("can't add gue ops\n");
1113 ip_tunnel_encap_del_ops(&fou_iptun_ops
, TUNNEL_ENCAP_FOU
);
1120 static void ip_tunnel_encap_del_fou_ops(void)
1122 ip_tunnel_encap_del_ops(&fou_iptun_ops
, TUNNEL_ENCAP_FOU
);
1123 ip_tunnel_encap_del_ops(&gue_iptun_ops
, TUNNEL_ENCAP_GUE
);
1128 static int ip_tunnel_encap_add_fou_ops(void)
1133 static void ip_tunnel_encap_del_fou_ops(void)
1139 static __net_init
int fou_init_net(struct net
*net
)
1141 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
1143 INIT_LIST_HEAD(&fn
->fou_list
);
1144 mutex_init(&fn
->fou_lock
);
1148 static __net_exit
void fou_exit_net(struct net
*net
)
1150 struct fou_net
*fn
= net_generic(net
, fou_net_id
);
1151 struct fou
*fou
, *next
;
1153 /* Close all the FOU sockets */
1154 mutex_lock(&fn
->fou_lock
);
1155 list_for_each_entry_safe(fou
, next
, &fn
->fou_list
, list
)
1157 mutex_unlock(&fn
->fou_lock
);
1160 static struct pernet_operations fou_net_ops
= {
1161 .init
= fou_init_net
,
1162 .exit
= fou_exit_net
,
1164 .size
= sizeof(struct fou_net
),
1167 static int __init
fou_init(void)
1171 ret
= register_pernet_device(&fou_net_ops
);
1175 ret
= genl_register_family(&fou_nl_family
);
1179 ret
= ip_tunnel_encap_add_fou_ops();
1183 genl_unregister_family(&fou_nl_family
);
1185 unregister_pernet_device(&fou_net_ops
);
1190 static void __exit
fou_fini(void)
1192 ip_tunnel_encap_del_fou_ops();
1193 genl_unregister_family(&fou_nl_family
);
1194 unregister_pernet_device(&fou_net_ops
);
1197 module_init(fou_init
);
1198 module_exit(fou_fini
);
1199 MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
1200 MODULE_LICENSE("GPL");