Lines Matching +full:foo +full:- +full:over +full:- +full:udp
1 // SPDX-License-Identifier: GPL-2.0-only
8 #include <linux/udp.h>
17 #include <net/udp.h>
53 return sk->sk_user_data; in fou_from_sock()
58 /* Remove 'len' bytes from the packet (UDP header and in fou_recv_pull()
61 if (fou->family == AF_INET) in fou_recv_pull()
62 ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len); in fou_recv_pull()
64 ipv6_hdr(skb)->payload_len = in fou_recv_pull()
65 htons(ntohs(ipv6_hdr(skb)->payload_len) - len); in fou_recv_pull()
83 return -fou->protocol; in fou_udp_recv()
100 if (skb->remcsum_offload) in gue_remcsum()
138 switch (guehdr->version) { in gue_udp_recv()
147 switch (((struct iphdr *)guehdr)->version) { in gue_udp_recv()
161 return -prot; in gue_udp_recv()
168 optlen = guehdr->hlen << 2; in gue_udp_recv()
182 if (fou->family == AF_INET) in gue_udp_recv()
183 ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len); in gue_udp_recv()
185 ipv6_hdr(skb)->payload_len = in gue_udp_recv()
186 htons(ntohs(ipv6_hdr(skb)->payload_len) - len); in gue_udp_recv()
195 if (guehdr->flags & GUE_FLAG_PRIV) { in gue_udp_recv()
202 hdrlen, guehdr->proto_ctype, in gue_udp_recv()
203 !!(fou->flags & in gue_udp_recv()
214 if (unlikely(guehdr->control)) in gue_udp_recv()
217 proto_ctype = guehdr->proto_ctype; in gue_udp_recv()
224 return -proto_ctype; in gue_udp_recv()
236 u8 proto = fou_from_sock(sk)->protocol; in fou_gro_receive()
243 * treating the GRE tunnel header as though it is a UDP protocol in fou_gro_receive()
246 NAPI_GRO_CB(skb)->encap_mark = 0; in fou_gro_receive()
249 NAPI_GRO_CB(skb)->is_fou = 1; in fou_gro_receive()
251 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in fou_gro_receive()
253 if (!ops || !ops->callbacks.gro_receive) in fou_gro_receive()
256 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); in fou_gro_receive()
266 u8 proto = fou_from_sock(sk)->protocol; in fou_gro_complete()
268 int err = -ENOSYS; in fou_gro_complete()
270 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in fou_gro_complete()
272 if (WARN_ON(!ops || !ops->callbacks.gro_complete)) in fou_gro_complete()
275 err = ops->callbacks.gro_complete(skb, nhoff); in fou_gro_complete()
292 if (skb->remcsum_offload) in gue_gro_remcsum()
295 if (!NAPI_GRO_CB(skb)->csum_valid) in gue_gro_remcsum()
301 skb->remcsum_offload = 1; in gue_gro_remcsum()
332 switch (guehdr->version) { in gue_gro_receive()
336 switch (((struct iphdr *)guehdr)->version) { in gue_gro_receive()
351 optlen = guehdr->hlen << 2; in gue_gro_receive()
360 if (unlikely(guehdr->control) || guehdr->version != 0 || in gue_gro_receive()
366 /* Adjust NAPI_GRO_CB(skb)->csum to account for guehdr, in gue_gro_receive()
373 if (guehdr->flags & GUE_FLAG_PRIV) { in gue_gro_receive()
381 !!(fou->flags & in gue_gro_receive()
398 if (!NAPI_GRO_CB(p)->same_flow) in gue_gro_receive()
401 guehdr2 = (struct guehdr *)(p->data + off); in gue_gro_receive()
406 if (guehdr->word != guehdr2->word) { in gue_gro_receive()
407 NAPI_GRO_CB(p)->same_flow = 0; in gue_gro_receive()
412 if (guehdr->hlen && memcmp(&guehdr[1], &guehdr2[1], in gue_gro_receive()
413 guehdr->hlen << 2)) { in gue_gro_receive()
414 NAPI_GRO_CB(p)->same_flow = 0; in gue_gro_receive()
419 proto = guehdr->proto_ctype; in gue_gro_receive()
426 * treating the GRE tunnel header as though it is a UDP protocol in gue_gro_receive()
429 NAPI_GRO_CB(skb)->encap_mark = 0; in gue_gro_receive()
432 NAPI_GRO_CB(skb)->is_fou = 1; in gue_gro_receive()
434 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in gue_gro_receive()
436 if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) in gue_gro_receive()
439 pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); in gue_gro_receive()
450 struct guehdr *guehdr = (struct guehdr *)(skb->data + nhoff); in gue_gro_complete()
455 int err = -ENOENT; in gue_gro_complete()
457 switch (guehdr->version) { in gue_gro_complete()
459 proto = guehdr->proto_ctype; in gue_gro_complete()
460 guehlen = sizeof(*guehdr) + (guehdr->hlen << 2); in gue_gro_complete()
463 switch (((struct iphdr *)guehdr)->version) { in gue_gro_complete()
478 offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; in gue_gro_complete()
480 if (WARN_ON(!ops || !ops->callbacks.gro_complete)) in gue_gro_complete()
483 err = ops->callbacks.gro_complete(skb, nhoff + guehlen); in gue_gro_complete()
493 struct sock *sk = fou->sock->sk; in fou_cfg_cmp()
494 struct udp_port_cfg *udp_cfg = &cfg->udp_config; in fou_cfg_cmp()
496 if (fou->family != udp_cfg->family || in fou_cfg_cmp()
497 fou->port != udp_cfg->local_udp_port || in fou_cfg_cmp()
498 sk->sk_dport != udp_cfg->peer_udp_port || in fou_cfg_cmp()
499 sk->sk_bound_dev_if != udp_cfg->bind_ifindex) in fou_cfg_cmp()
502 if (fou->family == AF_INET) { in fou_cfg_cmp()
503 if (sk->sk_rcv_saddr != udp_cfg->local_ip.s_addr || in fou_cfg_cmp()
504 sk->sk_daddr != udp_cfg->peer_ip.s_addr) in fou_cfg_cmp()
510 if (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, &udp_cfg->local_ip6) || in fou_cfg_cmp()
511 ipv6_addr_cmp(&sk->sk_v6_daddr, &udp_cfg->peer_ip6)) in fou_cfg_cmp()
527 mutex_lock(&fn->fou_lock); in fou_add_to_port_list()
528 list_for_each_entry(fout, &fn->fou_list, list) { in fou_add_to_port_list()
530 mutex_unlock(&fn->fou_lock); in fou_add_to_port_list()
531 return -EALREADY; in fou_add_to_port_list()
535 list_add(&fou->list, &fn->fou_list); in fou_add_to_port_list()
536 mutex_unlock(&fn->fou_lock); in fou_add_to_port_list()
543 struct socket *sock = fou->sock; in fou_release()
545 list_del(&fou->list); in fou_release()
560 /* Open UDP socket */ in fou_create()
561 err = udp_sock_create(net, &cfg->udp_config, &sock); in fou_create()
568 err = -ENOMEM; in fou_create()
572 sk = sock->sk; in fou_create()
574 fou->port = cfg->udp_config.local_udp_port; in fou_create()
575 fou->family = cfg->udp_config.family; in fou_create()
576 fou->flags = cfg->flags; in fou_create()
577 fou->type = cfg->type; in fou_create()
578 fou->sock = sock; in fou_create()
586 switch (cfg->type) { in fou_create()
591 fou->protocol = cfg->protocol; in fou_create()
599 err = -EINVAL; in fou_create()
605 sk->sk_allocation = GFP_ATOMIC; in fou_create()
627 int err = -EINVAL; in fou_destroy()
630 mutex_lock(&fn->fou_lock); in fou_destroy()
631 list_for_each_entry(fou, &fn->fou_list, list) { in fou_destroy()
638 mutex_unlock(&fn->fou_lock); in fou_destroy()
655 cfg->udp_config.family = AF_INET; in parse_nl_config()
657 if (info->attrs[FOU_ATTR_AF]) { in parse_nl_config()
658 u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]); in parse_nl_config()
664 cfg->udp_config.ipv6_v6only = 1; in parse_nl_config()
667 return -EAFNOSUPPORT; in parse_nl_config()
670 cfg->udp_config.family = family; in parse_nl_config()
673 if (info->attrs[FOU_ATTR_PORT]) { in parse_nl_config()
674 port = nla_get_be16(info->attrs[FOU_ATTR_PORT]); in parse_nl_config()
675 cfg->udp_config.local_udp_port = port; in parse_nl_config()
678 if (info->attrs[FOU_ATTR_IPPROTO]) in parse_nl_config()
679 cfg->protocol = nla_get_u8(info->attrs[FOU_ATTR_IPPROTO]); in parse_nl_config()
681 if (info->attrs[FOU_ATTR_TYPE]) in parse_nl_config()
682 cfg->type = nla_get_u8(info->attrs[FOU_ATTR_TYPE]); in parse_nl_config()
684 if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL]) in parse_nl_config()
685 cfg->flags |= FOU_F_REMCSUM_NOPARTIAL; in parse_nl_config()
687 if (cfg->udp_config.family == AF_INET) { in parse_nl_config()
688 if (info->attrs[FOU_ATTR_LOCAL_V4]) { in parse_nl_config()
689 attr = info->attrs[FOU_ATTR_LOCAL_V4]; in parse_nl_config()
690 cfg->udp_config.local_ip.s_addr = nla_get_in_addr(attr); in parse_nl_config()
694 if (info->attrs[FOU_ATTR_PEER_V4]) { in parse_nl_config()
695 attr = info->attrs[FOU_ATTR_PEER_V4]; in parse_nl_config()
696 cfg->udp_config.peer_ip.s_addr = nla_get_in_addr(attr); in parse_nl_config()
701 if (info->attrs[FOU_ATTR_LOCAL_V6]) { in parse_nl_config()
702 attr = info->attrs[FOU_ATTR_LOCAL_V6]; in parse_nl_config()
703 cfg->udp_config.local_ip6 = nla_get_in6_addr(attr); in parse_nl_config()
707 if (info->attrs[FOU_ATTR_PEER_V6]) { in parse_nl_config()
708 attr = info->attrs[FOU_ATTR_PEER_V6]; in parse_nl_config()
709 cfg->udp_config.peer_ip6 = nla_get_in6_addr(attr); in parse_nl_config()
716 if (info->attrs[FOU_ATTR_PEER_PORT]) { in parse_nl_config()
717 port = nla_get_be16(info->attrs[FOU_ATTR_PEER_PORT]); in parse_nl_config()
718 cfg->udp_config.peer_udp_port = port; in parse_nl_config()
720 return -EINVAL; in parse_nl_config()
724 if (info->attrs[FOU_ATTR_IFINDEX]) { in parse_nl_config()
726 return -EINVAL; in parse_nl_config()
728 ifindex = nla_get_s32(info->attrs[FOU_ATTR_IFINDEX]); in parse_nl_config()
730 cfg->udp_config.bind_ifindex = ifindex; in parse_nl_config()
764 struct sock *sk = fou->sock->sk; in fou_fill_info()
766 if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) || in fou_fill_info()
767 nla_put_be16(msg, FOU_ATTR_PORT, fou->port) || in fou_fill_info()
768 nla_put_be16(msg, FOU_ATTR_PEER_PORT, sk->sk_dport) || in fou_fill_info()
769 nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) || in fou_fill_info()
770 nla_put_u8(msg, FOU_ATTR_TYPE, fou->type) || in fou_fill_info()
771 nla_put_s32(msg, FOU_ATTR_IFINDEX, sk->sk_bound_dev_if)) in fou_fill_info()
772 return -1; in fou_fill_info()
774 if (fou->flags & FOU_F_REMCSUM_NOPARTIAL) in fou_fill_info()
776 return -1; in fou_fill_info()
778 if (fou->sock->sk->sk_family == AF_INET) { in fou_fill_info()
779 if (nla_put_in_addr(msg, FOU_ATTR_LOCAL_V4, sk->sk_rcv_saddr)) in fou_fill_info()
780 return -1; in fou_fill_info()
782 if (nla_put_in_addr(msg, FOU_ATTR_PEER_V4, sk->sk_daddr)) in fou_fill_info()
783 return -1; in fou_fill_info()
787 &sk->sk_v6_rcv_saddr)) in fou_fill_info()
788 return -1; in fou_fill_info()
790 if (nla_put_in6_addr(msg, FOU_ATTR_PEER_V6, &sk->sk_v6_daddr)) in fou_fill_info()
791 return -1; in fou_fill_info()
805 return -ENOMEM; in fou_dump_info()
815 return -EMSGSIZE; in fou_dump_info()
834 return -EINVAL; in fou_nl_get_doit()
838 return -EINVAL; in fou_nl_get_doit()
842 return -ENOMEM; in fou_nl_get_doit()
844 ret = -ESRCH; in fou_nl_get_doit()
845 mutex_lock(&fn->fou_lock); in fou_nl_get_doit()
846 list_for_each_entry(fout, &fn->fou_list, list) { in fou_nl_get_doit()
848 ret = fou_dump_info(fout, info->snd_portid, in fou_nl_get_doit()
849 info->snd_seq, 0, msg, in fou_nl_get_doit()
850 info->genlhdr->cmd); in fou_nl_get_doit()
854 mutex_unlock(&fn->fou_lock); in fou_nl_get_doit()
867 struct net *net = sock_net(skb->sk); in fou_nl_get_dumpit()
872 mutex_lock(&fn->fou_lock); in fou_nl_get_dumpit()
873 list_for_each_entry(fout, &fn->fou_list, list) { in fou_nl_get_dumpit()
874 if (idx++ < cb->args[0]) in fou_nl_get_dumpit()
876 ret = fou_dump_info(fout, NETLINK_CB(cb->skb).portid, in fou_nl_get_dumpit()
877 cb->nlh->nlmsg_seq, NLM_F_MULTI, in fou_nl_get_dumpit()
882 mutex_unlock(&fn->fou_lock); in fou_nl_get_dumpit()
884 cb->args[0] = idx; in fou_nl_get_dumpit()
885 return skb->len; in fou_nl_get_dumpit()
914 if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) { in gue_encap_hlen()
934 *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), in __fou_build_header()
950 if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) && in __gue_build_header()
951 skb->ip_summed == CHECKSUM_PARTIAL) { in __gue_build_header()
964 *sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), in __gue_build_header()
971 guehdr = (struct guehdr *)skb->data; in __gue_build_header()
973 guehdr->control = 0; in __gue_build_header()
974 guehdr->version = 0; in __gue_build_header()
975 guehdr->hlen = optlen >> 2; in __gue_build_header()
976 guehdr->flags = 0; in __gue_build_header()
977 guehdr->proto_ctype = *protocol; in __gue_build_header()
984 guehdr->flags |= GUE_FLAG_PRIV; in __gue_build_header()
993 return -EINVAL; in __gue_build_header()
995 csum_start -= hdrlen; in __gue_build_header()
997 pd[1] = htons(csum_start + skb->csum_offset); in __gue_build_header()
1000 skb->ip_summed = CHECKSUM_NONE; in __gue_build_header()
1001 skb->encapsulation = 0; in __gue_build_header()
1026 uh->dest = e->dport; in fou_build_udp()
1027 uh->source = sport; in fou_build_udp()
1028 uh->len = htons(skb->len); in fou_build_udp()
1029 udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb, in fou_build_udp()
1030 fl4->saddr, fl4->daddr, skb->len); in fou_build_udp()
1038 int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : in fou_build_header()
1055 int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : in gue_build_header()
1073 if (ipprot && ipprot->err_handler) { in gue_err_proto_handler()
1074 if (!ipprot->err_handler(skb, info)) in gue_err_proto_handler()
1078 return -ENOENT; in gue_err_proto_handler()
1090 return -EINVAL; in gue_err()
1094 switch (guehdr->version) { in gue_err()
1099 skb_set_transport_header(skb, -(int)sizeof(struct icmphdr)); in gue_err()
1101 switch (((struct iphdr *)guehdr)->version) { in gue_err()
1111 ret = -EOPNOTSUPP; in gue_err()
1116 return -EOPNOTSUPP; in gue_err()
1119 if (guehdr->control) in gue_err()
1120 return -ENOENT; in gue_err()
1122 optlen = guehdr->hlen << 2; in gue_err()
1125 return -EINVAL; in gue_err()
1129 return -EINVAL; in gue_err()
1131 /* Handling exceptions for direct UDP encapsulation in GUE would lead to in gue_err()
1135 if (guehdr->proto_ctype == IPPROTO_UDP || in gue_err()
1136 guehdr->proto_ctype == IPPROTO_UDPLITE) in gue_err()
1137 return -EOPNOTSUPP; in gue_err()
1139 skb_set_transport_header(skb, -(int)sizeof(struct icmphdr)); in gue_err()
1140 ret = gue_err_proto_handler(guehdr->proto_ctype, skb, info); in gue_err()
1203 INIT_LIST_HEAD(&fn->fou_list); in fou_init_net()
1204 mutex_init(&fn->fou_lock); in fou_init_net()
1214 mutex_lock(&fn->fou_lock); in fou_exit_net()
1215 list_for_each_entry_safe(fou, next, &fn->fou_list, list) in fou_exit_net()
1217 mutex_unlock(&fn->fou_lock); in fou_exit_net()
1266 MODULE_DESCRIPTION("Foo over UDP");